Etch has become a TLP

git-svn-id: https://svn.apache.org/repos/asf/etch/branches/config@1440293 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..88fd557
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="util/src/main/java"/>
+	<classpathentry kind="src" path="util/src/test/java"/>
+	<classpathentry kind="src" path="compiler/src/main/javacc"/>
+	<classpathentry kind="src" path="compiler/src/main/java"/>
+	<classpathentry kind="src" path="compiler/src/main/resources"/>
+	<classpathentry kind="src" path="compiler/target/generated-sources/main/javacc/java"/>
+	<classpathentry kind="src" path="compiler/src/test/java"/>
+	<classpathentry kind="src" path="compiler/src/test/resources"/>
+	<classpathentry kind="src" path="plugins/ant/src/main/java"/>
+	<classpathentry kind="src" path="plugins/ant/src/main/resources"/>
+	<classpathentry kind="src" path="plugins/ant/src/test/java"/>
+	<classpathentry kind="src" path="binding-java/compiler/src/main/java"/>
+	<classpathentry kind="src" path="binding-java/compiler/src/main/resources"/>
+	<classpathentry kind="src" path="binding-java/runtime/src/main/java"/>
+	<classpathentry kind="src" path="binding-java/runtime/src/test/java"/>
+	<classpathentry kind="src" path="binding-csharp/compiler/src/main/java"/>
+	<classpathentry kind="src" path="binding-csharp/compiler/src/main/resources"/>
+	<classpathentry kind="src" path="binding-xml/compiler/src/main/java"/>
+	<classpathentry kind="src" path="binding-xml/compiler/src/main/resources"/>
+	<classpathentry kind="src" path="tests/src/main/java"/>
+	<classpathentry kind="src" path="tests/src/main/resources"/>
+	<classpathentry kind="src" path="tests/target/generated-sources/main/etch/java"/>
+	<classpathentry kind="src" path="tests/src/test/java"/>
+	<classpathentry kind="src" path="examples/chat/src/main/java"/>
+	<classpathentry kind="src" path="examples/chat/target/generated-sources/main/etch/java"/>
+	<classpathentry kind="src" path="examples/chat/src/test/java"/>
+	<classpathentry kind="src" path="examples/distmap/src/main/java"/>
+	<classpathentry kind="src" path="examples/distmap/target/generated-sources/main/etch/java"/>
+	<classpathentry kind="src" path="examples/distmap/src/test/java"/>
+	<classpathentry kind="src" path="examples/example/src/main/java"/>
+	<classpathentry kind="src" path="examples/example/target/generated-sources/main/etch/java"/>
+	<classpathentry kind="src" path="examples/example/src/test/java"/>
+	<classpathentry kind="src" path="examples/perf/src/main/java"/>
+	<classpathentry kind="src" path="examples/perf/target/generated-sources/main/etch/java"/>
+	<classpathentry kind="src" path="examples/perf/src/test/java"/>
+	<classpathentry kind="src" path="binding-c/compiler/src/main/java"/>
+	<classpathentry kind="src" path="binding-c/compiler/src/main/resources"/>
+	<classpathentry kind="src" path="binding-python/compiler/src/main/java"/>
+	<classpathentry kind="src" path="binding-python/compiler/src/main/resources"/>
+	<classpathentry kind="src" path="interoptester/src/main/java"/>
+	<classpathentry kind="src" path="interoptester/src/test/java"/>
+	<classpathentry kind="src" path="interoptester/example/src/main/java"/>
+	<classpathentry kind="src" path="interoptester/example/target/generated-sources/main/etch/java"/>
+	<classpathentry kind="src" path="services/config/src/main/java"/>
+	<classpathentry kind="src" path="services/config/src/test/java"/>
+	<classpathentry kind="src" path="services/config/target/generated-sources/main/etch/java"/>
+	<classpathentry kind="src" path="services/config/example/src/main/java"/>
+	<classpathentry kind="src" path="services/config/example/target/generated-sources/main/etch/java"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/ETCH_DEPENDENT_JARS"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/.project b/.project
new file mode 100644
index 0000000..5dd978a
--- /dev/null
+++ b/.project
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>etch</name>
+	<comment>JavaCC Nature</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>sf.eclipse.javacc.javaccbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>sf.eclipse.javacc.javaccnature</nature>
+		<nature>org.python.pydev.pythonNature</nature>
+	</natures>
+</projectDescription>
diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..6c2e886
--- /dev/null
+++ b/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,3 @@
+#Wed Jul 16 14:26:18 CDT 2008

+eclipse.preferences.version=1

+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>

diff --git a/.settings/org.eclipse.ltk.core.refactoring.prefs b/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..d365e83
--- /dev/null
+++ b/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Sat Aug 18 15:24:44 CDT 2007

+eclipse.preferences.version=1

+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false

diff --git a/BUILD.txt b/BUILD.txt
new file mode 100644
index 0000000..7d20dd6
--- /dev/null
+++ b/BUILD.txt
@@ -0,0 +1,271 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+*/
+Build Instructions for Apache Etch
+==================================
+
+Contents
+--------
+  Source tree
+  Dependencies
+  Setup Development Environment
+  Building from ANT
+  Building from Eclipse
+  
+
+Source tree
+-----------
+
+This is the source tree for Etch. It is organized as follows:
+
+   build.xml         - top-level ant build script
+   build.dependecies - locations for jars this compile depends on
+   etch.properties   - static build properties 
+   
+   compiler/      - core compiler
+   build-support/ - common ant scripts shared by all modules
+   plugins/       - extensions that embed the compiler, e.g. ant, maven, etc.
+   scripts/       - common scripts for eclipse
+   util/          - shared java classes
+   tests/         - functional tests
+   examples/      - Etch application examples
+      chat/       - simple IM application
+      distmap/    - example implementation of a distributed map in etch
+      perf/       - etch client/server performance test
+      example/    - minimal example
+   installers/    - project for NSIS installer and tar.gz, .zip archives
+       
+   binding-xml    - xml binding
+   binding-java   - java-language binding
+   binding-csharp - C#-language binding
+   
+
+  About the Structure of Etch bindings
+  ------------------------------------
+
+Each binding is factored into its own structure into the build tree. The intent
+is to provide an easy pattern for potential binding authors to emulate.
+Essentially each binding has two components:
+
+   - compiler/
+   - runtime/
+   
+The 'compiler' is always implemented in Java and is coded to implement a
+backend interface for the target of choice.
+
+The 'runtime' is coded in the target language. The most useful language
+bindings implement identical functionality as the Java and C# bindings.
+Non-languages bindings (like binding-xml) may not have a runtime component
+at all.
+
+Dependencies
+------------
+
+To build the compiler core and the Java and XML bindings and Java-based examples,
+you need the following:
+
+ * Java JDK 1.5_011 or later
+ * Apache Ant 1.7+
+ * JavaCC 4.0
+ * Junit 4.3.1
+ * Velocity 1.5
+
+To compile the C# bindings and examples:
+
+ * Apache Ant DotNet 1.0
+ * .NET Framework 2.0 (Visual Studio 2005)
+ ** (Mono 1.9 support is experimental)
+ * NUnit 2.4.7
+ 
+To compile NSIS installers:
+
+ * NSIS 2.23
+
+Setup development environment
+-----------------------------
+
+The primary development environments for the Etch committers are Win32 and
+*nix (Mac OS X). As such we have attempted to make the build process platform
+neutral. In addition, Etch builds are done daily on our internal Bamboo server
+here at Cisco on the win32 platform. This means that we tend to have a bias
+towards a working Win32 build. To further complicate matters, we have much
+development-environment divergence in our committer base, some of us being very
+shell-centric (dixson) while others of us being firmly rooted in Eclipse (sccomer).
+So the compromise has been to attempt to structure the build such it can be
+friendly and productive to both groups and keep the sectarian violence to
+a minimum. :-)
+
+1. Install JDK. Make certain that you set your JAVA_HOME environment variable
+   to point to the correct location.
+   
+Building from ANT
+-----------------
+
+1. Install Apache ANT (version 1.7 or later). 
+
+2. Put /path/to/apache-ant-1.7/bin in your PATH.
+
+3. If you have Mono, make certain MONO_HOME is set correctly. If you have .NET
+   framework, make certain msbuild.exe is in your PATH.
+
+4. If building C#, make certain NUNIT_HOME is set correctly.
+
+5. If building on Win32 and you want to build the NSIS installers, set
+   NSIS_HOME to /path/to/nsis/2.23.
+
+6. [IMPORTANT] Update 'build.dependencies' with the correct paths to the jar's
+   this project depends upon:
+
+  * javacc.home=/path/to/javacc-4.0      
+        ('${javacc.home}/bin/lib/javacc.jar' should exist)
+        
+  * junit.lib=/path/to/junit-4.3.1
+        ('${junit.lib}/junit-4.3.1.jar' should exist)
+        
+  * velocity.lib=/path/to/velocity-1.5            
+        ('${velocity.lib}/velocity-dep-1.5.jar' should exist)
+
+  --OPTIONAL--        
+  * ant-dotnet.lib=/path/to/apache-ant-dotnet-1.0 
+
+(dixson) This is a hack until I get autoconf working. Just not there yet :-(
+
+
+7. At the shell prompt type:
+
+ > ant release
+
+This will build all compilers and all the bindings for which you have setup
+dependencies. It will also build and run all unit/functional tests and build
+all the examples in examples/.
+
+Once complete, the dist tree can be found in 'target/Installers/dist'. Copy
+this directory manually to the desired install location.
+
+Building from Eclipse
+---------------------
+
+After you checkout the project in eclipse, you will likely be told that there are
+build path problems. There are three dependent projects you need to get going with
+etch for eclipse, and one plugin:
+
+ javacc 4.0
+ ant 1.7.0
+ junit 4.3.1
+ velocity 1.5
+
+JavaCC is an eclipse plugin, get it from here:
+
+ http://eclipse-javacc.sourceforge.net/
+
+On that page are directions to install the plugin from within eclipse. The other two
+you download:
+
+ http://sourceforge.net/projects/junit/
+ http://velocity.apache.org/engine/releases/velocity-1.5/
+ http://archive.apache.org/dist/ant/binaries/
+
+NOTE: junit-4.3.1 is a hard dependency. Later versions of ant, JavaCC and Velocity may
+work, but later versions of JUnit will not (true as of etch-1.0.2).
+
+Once downloaded, you will need to create an environment variable (for example):
+
+ ETCH_DEPENDENT_JARS=C:\workspace-etch\tools\velocity\1.5\velocity-dep-1.5.jar
+
+These are the extra jar files required to actually run the compiler. You will need
+to restart eclipse if it is running. Once eclipse is started, you will need to 
+configure the Etch project:
+
+ Right click on the etch project, and select Build Path / Configure Build Path
+ 
+ Select the Libraries tab on the right.
+ 
+ If ETCH_DEPENDENT_JARS is here, delete it.
+
+ Select Add Library... on the right.
+
+ Select User Library and click Next.
+
+ Select User Libraries...
+
+ Select New...
+
+ Enter the name ETCH_DEPENDENT_JARS and click Ok.
+
+ With ETCH_DEPENDENT_JARS selected, click Add JARs...
+
+ Navigate to junit-4.3.1.jar and select it.
+
+ With ETCH_DEPENDENT_JARS selected, click Add JARs... again...
+
+ Navigate to velocity-dep-1.5.jar and select it.
+
+ Navigate to ant.jar and select it.
+
+ Click Ok.
+
+ Click Finish.
+
+ Click Ok.
+
+Eclipse should rebuild the project. There may still be errors, that's ok:
+
+ Open Window / Preferences / Java / Compiler / Building.
+
+ Expand Build path problems.
+
+ Set Incomplete build path to be a warning.
+ 
+ Set Circular dependencies to be an error.
+
+ Set Incompatible required binaries to warning.
+
+ Click Ok.
+
+Make sure JavaCC compiled EtchGrammar.jj. There should be a JavaCC console
+view open. If not, open it (Window / Show View / Other... / JavaCC console /
+JavaCC console).
+
+If JavaCC console is empty, Select Project / Clean... and clean all projects.
+A few JavaCC messages should appear. It is ok if JavaCC warns about creating
+a directory.
+
+Now that the compiler is built, you will still have errors for etch build
+products which are missing. you will need to recompile all the etch files.
+You can do this by:
+
+ Select the etch project.
+
+ Select Run / External Tools / Compile Java Etch Files.
+
+(You may want to configure the external tools first. Select Run / External
+Tools / Organize Favorites... Click Add... Select All. Ok. Ok.)
+
+You should see a nice output in the Console reporting successful compilation
+of a bunch of etch files. Eclipse should then rebuilt the project.
+
+Finally, you can check things out by running the unit tests.
+
+ Right click on the etch project, select Run as... / Junit test.
+
+You'll get some output on the console window, including scary looking stack
+traces. That's ok. JUnit runner should tell you that 1197 tests passed, 22
+ignored, with 0 errors and 0 failures. This takes 66 seconds for me (sccomer).
+
+You're done, start exploring. Check out examples, perf or chat.
+
diff --git a/CSharp.sln b/CSharp.sln
new file mode 100644
index 0000000..7bd8bca
--- /dev/null
+++ b/CSharp.sln
@@ -0,0 +1,140 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EtchTestProj", "binding-csharp\runtime\src\test\csharp\EtchTestProj.csproj", "{3D44C33C-0E5F-443B-A0B4-ABDF16B64AC5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EtchProj", "binding-csharp\runtime\src\main\csharp\EtchProj.csproj", "{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerfListenerProj", "examples\perf\src\main\csharp\PerfListenerProj\PerfListenerProj.csproj", "{4B9CE732-601A-4A74-A1D5-AF78251FEDD2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerfClientProj", "examples\perf\src\main\csharp\PerfClientProj\PerfClientProj.csproj", "{D2AA03D8-1555-4A9B-8618-FF12A15BBB6E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DistMapClientProj", "examples\distmap\src\main\csharp\DistMapClientProj\DistMapClientProj.csproj", "{7613961B-FD82-40DB-BF99-EEF50BB20887}"
+	ProjectSection(ProjectDependencies) = postProject
+		{0E518F2A-3016-4C2F-A21B-9BD52B2DC846} = {0E518F2A-3016-4C2F-A21B-9BD52B2DC846}
+	EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DistMapListenerProj", "examples\distmap\src\main\csharp\DistMapListenerProj\DistMapListenerProj.csproj", "{75F8A513-4500-4AC3-8E97-8B7609A8AEA9}"
+	ProjectSection(ProjectDependencies) = postProject
+		{0E518F2A-3016-4C2F-A21B-9BD52B2DC846} = {0E518F2A-3016-4C2F-A21B-9BD52B2DC846}
+	EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatClientProj", "examples\chat\src\main\csharp\ChatClientProj\ChatClientProj.csproj", "{13BBC268-2F31-4C68-B62B-3C2CFD0228BE}"
+	ProjectSection(ProjectDependencies) = postProject
+		{0E518F2A-3016-4C2F-A21B-9BD52B2DC846} = {0E518F2A-3016-4C2F-A21B-9BD52B2DC846}
+	EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatListenerProj", "examples\chat\src\main\csharp\ChatListenerProj\ChatListenerProj.csproj", "{574C28F9-1D0D-47CB-9F18-221E5128D5A6}"
+	ProjectSection(ProjectDependencies) = postProject
+		{0E518F2A-3016-4C2F-A21B-9BD52B2DC846} = {0E518F2A-3016-4C2F-A21B-9BD52B2DC846}
+	EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExampleClientProj", "examples\example\src\main\csharp\ExampleClientProj\ExampleClientProj.csproj", "{38953BC0-A834-4939-A25F-8C7F2C7F8758}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExampleListenerProj", "examples\example\src\main\csharp\ExampleListenerProj\ExampleListenerProj.csproj", "{7EEA2F47-0D96-4187-B9EF-CA0B9E839841}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsProj", "tests\src\test\csharp\TestsProj\TestsProj.csproj", "{70701740-652A-4E07-9B85-59DDCC9D43D4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DistMapTestProj", "examples\distmap\src\test\csharp\DistMapTestProj\DistMapTestProj.csproj", "{39699FEE-D21E-42AC-ADD7-22484A985C27}"
+	ProjectSection(ProjectDependencies) = postProject
+		{0E518F2A-3016-4C2F-A21B-9BD52B2DC846} = {0E518F2A-3016-4C2F-A21B-9BD52B2DC846}
+	EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExampleTestProj", "examples\example\src\test\csharp\ExampleTestProj\ExampleTestProj.csproj", "{36991AC6-21DE-4F7A-8672-8CFCC8AF70C7}"
+	ProjectSection(ProjectDependencies) = postProject
+		{0E518F2A-3016-4C2F-A21B-9BD52B2DC846} = {0E518F2A-3016-4C2F-A21B-9BD52B2DC846}
+	EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerfTestProj", "examples\perf\src\test\csharp\PerfTestProj\PerfTestProj.csproj", "{47FDB15C-6DE2-4191-A41C-1993B714B4CD}"
+	ProjectSection(ProjectDependencies) = postProject
+		{0E518F2A-3016-4C2F-A21B-9BD52B2DC846} = {0E518F2A-3016-4C2F-A21B-9BD52B2DC846}
+	EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatTestProj", "examples\chat\src\test\csharp\ChatTestProj\ChatTestProj.csproj", "{01A7F0CC-78AB-4CFE-88DB-32AAC6D6C00B}"
+	ProjectSection(ProjectDependencies) = postProject
+		{0E518F2A-3016-4C2F-A21B-9BD52B2DC846} = {0E518F2A-3016-4C2F-A21B-9BD52B2DC846}
+	EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IOTListenerProj", "interoptester\example\src\main\csharp\IOTListenerProj\IOTListenerProj.csproj", "{5EED552A-09C1-42D0-9E0A-7822B0EC3603}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IOTClientProj", "interoptester\example\src\main\csharp\IOTClientProj\IOTClientProj.csproj", "{14D7A923-0CB4-442A-9499-7F0C25C239EE}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{3D44C33C-0E5F-443B-A0B4-ABDF16B64AC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3D44C33C-0E5F-443B-A0B4-ABDF16B64AC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3D44C33C-0E5F-443B-A0B4-ABDF16B64AC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{3D44C33C-0E5F-443B-A0B4-ABDF16B64AC5}.Release|Any CPU.Build.0 = Release|Any CPU
+		{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}.Release|Any CPU.Build.0 = Release|Any CPU
+		{4B9CE732-601A-4A74-A1D5-AF78251FEDD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{4B9CE732-601A-4A74-A1D5-AF78251FEDD2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{4B9CE732-601A-4A74-A1D5-AF78251FEDD2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{4B9CE732-601A-4A74-A1D5-AF78251FEDD2}.Release|Any CPU.Build.0 = Release|Any CPU
+		{D2AA03D8-1555-4A9B-8618-FF12A15BBB6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{D2AA03D8-1555-4A9B-8618-FF12A15BBB6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{D2AA03D8-1555-4A9B-8618-FF12A15BBB6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{D2AA03D8-1555-4A9B-8618-FF12A15BBB6E}.Release|Any CPU.Build.0 = Release|Any CPU
+		{7613961B-FD82-40DB-BF99-EEF50BB20887}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{7613961B-FD82-40DB-BF99-EEF50BB20887}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{7613961B-FD82-40DB-BF99-EEF50BB20887}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{7613961B-FD82-40DB-BF99-EEF50BB20887}.Release|Any CPU.Build.0 = Release|Any CPU
+		{75F8A513-4500-4AC3-8E97-8B7609A8AEA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{75F8A513-4500-4AC3-8E97-8B7609A8AEA9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{75F8A513-4500-4AC3-8E97-8B7609A8AEA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{75F8A513-4500-4AC3-8E97-8B7609A8AEA9}.Release|Any CPU.Build.0 = Release|Any CPU
+		{13BBC268-2F31-4C68-B62B-3C2CFD0228BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{13BBC268-2F31-4C68-B62B-3C2CFD0228BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{13BBC268-2F31-4C68-B62B-3C2CFD0228BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{13BBC268-2F31-4C68-B62B-3C2CFD0228BE}.Release|Any CPU.Build.0 = Release|Any CPU
+		{574C28F9-1D0D-47CB-9F18-221E5128D5A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{574C28F9-1D0D-47CB-9F18-221E5128D5A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{574C28F9-1D0D-47CB-9F18-221E5128D5A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{574C28F9-1D0D-47CB-9F18-221E5128D5A6}.Release|Any CPU.Build.0 = Release|Any CPU
+		{38953BC0-A834-4939-A25F-8C7F2C7F8758}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{38953BC0-A834-4939-A25F-8C7F2C7F8758}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{38953BC0-A834-4939-A25F-8C7F2C7F8758}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{38953BC0-A834-4939-A25F-8C7F2C7F8758}.Release|Any CPU.Build.0 = Release|Any CPU
+		{7EEA2F47-0D96-4187-B9EF-CA0B9E839841}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{7EEA2F47-0D96-4187-B9EF-CA0B9E839841}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{7EEA2F47-0D96-4187-B9EF-CA0B9E839841}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{7EEA2F47-0D96-4187-B9EF-CA0B9E839841}.Release|Any CPU.Build.0 = Release|Any CPU
+		{70701740-652A-4E07-9B85-59DDCC9D43D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{70701740-652A-4E07-9B85-59DDCC9D43D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{70701740-652A-4E07-9B85-59DDCC9D43D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{70701740-652A-4E07-9B85-59DDCC9D43D4}.Release|Any CPU.Build.0 = Release|Any CPU
+		{39699FEE-D21E-42AC-ADD7-22484A985C27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{39699FEE-D21E-42AC-ADD7-22484A985C27}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{39699FEE-D21E-42AC-ADD7-22484A985C27}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{39699FEE-D21E-42AC-ADD7-22484A985C27}.Release|Any CPU.Build.0 = Release|Any CPU
+		{36991AC6-21DE-4F7A-8672-8CFCC8AF70C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{36991AC6-21DE-4F7A-8672-8CFCC8AF70C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{36991AC6-21DE-4F7A-8672-8CFCC8AF70C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{36991AC6-21DE-4F7A-8672-8CFCC8AF70C7}.Release|Any CPU.Build.0 = Release|Any CPU
+		{47FDB15C-6DE2-4191-A41C-1993B714B4CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{47FDB15C-6DE2-4191-A41C-1993B714B4CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{47FDB15C-6DE2-4191-A41C-1993B714B4CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{47FDB15C-6DE2-4191-A41C-1993B714B4CD}.Release|Any CPU.Build.0 = Release|Any CPU
+		{01A7F0CC-78AB-4CFE-88DB-32AAC6D6C00B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{01A7F0CC-78AB-4CFE-88DB-32AAC6D6C00B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{01A7F0CC-78AB-4CFE-88DB-32AAC6D6C00B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{01A7F0CC-78AB-4CFE-88DB-32AAC6D6C00B}.Release|Any CPU.Build.0 = Release|Any CPU
+		{5EED552A-09C1-42D0-9E0A-7822B0EC3603}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{5EED552A-09C1-42D0-9E0A-7822B0EC3603}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{5EED552A-09C1-42D0-9E0A-7822B0EC3603}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{5EED552A-09C1-42D0-9E0A-7822B0EC3603}.Release|Any CPU.Build.0 = Release|Any CPU
+		{14D7A923-0CB4-442A-9499-7F0C25C239EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{14D7A923-0CB4-442A-9499-7F0C25C239EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{14D7A923-0CB4-442A-9499-7F0C25C239EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{14D7A923-0CB4-442A-9499-7F0C25C239EE}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/ChangeLog.txt b/ChangeLog.txt
new file mode 100644
index 0000000..309952f
--- /dev/null
+++ b/ChangeLog.txt
@@ -0,0 +1,361 @@
+-------------
+Release 1.0.2
+-------------
+
+r738160 | sccomer | 2009-01-27 11:30:43 CST
+
+fix for ETCH-31: MySessionListener in TcpTransportFactory does not override
+toString() method to show something useful about the transport stack
+----------------------------------------------------------------------------
+r737984 | dixson | 2009-01-26 21:14:36 CST
+
+update SVN and homepage to apache.org URLs
+----------------------------------------------------------------------------
+r737770 | sccomer | 2009-01-26 11:59:24 CST
+
+fix for ETCH-29: Installing all Maven artifacts along with their sources.
+----------------------------------------------------------------------------
+r737767 | sccomer | 2009-01-26 11:55:12 CST
+
+fix for ETCH-27: mixins cause trouble when two or more mixed in files define a
+type with the same name.
+----------------------------------------------------------------------------
+r737764 | sccomer | 2009-01-26 11:43:19 CST
+
+fix for ETCH-28: Examples do not build due to outdated ant files.
+----------------------------------------------------------------------------
+r736737 | sccomer | 2009-01-22 12:32:13 CST
+
+fix for ETCH-24: The message direction is always "server" for the result_method
+messages in the java-binding valuefactory (also csharp)
+----------------------------------------------------------------------------
+r736725 | sccomer | 2009-01-22 11:43:19 CST
+
+comment out conflicting assignment of JAVA_HOME
+----------------------------------------------------------------------------
+r736724 | sccomer | 2009-01-22 11:42:41 CST
+
+bump the version number to 1.0.2.
+----------------------------------------------------------------------------
+r736169 | sccomer | 2009-01-20 17:25:34 CST
+
+fix for ETCH-25: DefaultDeliveryService ends call with mb.CloseDelivery() and it
+should end it with mb.CloseRead()
+----------------------------------------------------------------------------
+r733843 | rebarraz | 2009-01-12 11:11:12 CST
+
+fix for ETCH-13: added examples to distribution
+----------------------------------------------------------------------------
+r724340 | sccomer | 2008-12-08 07:32:04 CST
+
+factor perf tests into individual static functions called from main.
+
+pull configuration options to the top.
+----------------------------------------------------------------------------
+r723340 | sccomer | 2008-12-04 08:49:24 CST
+
+csharp fix for ETCH-19: Break out common tcp transport options so that they may
+be shared among various transports.
+----------------------------------------------------------------------------
+r723112 | sccomer | 2008-12-03 16:49:22 CST
+
+do the right math related to relative timing tests.
+----------------------------------------------------------------------------
+r723034 | sccomer | 2008-12-03 13:42:19 CST
+
+csharp fix for ETCH-11: AlarmManager deadlocks during shutdown(). break lock on
+AbstractStartable start() and stop() methods. Add back necessary synchronization
+for Monitor.PulseAll() in Stop0(). Port java version of unit test.
+----------------------------------------------------------------------------
+r723032 | sccomer | 2008-12-03 13:39:56 CST
+
+drop blank string for thrown exception in unit test for AlarmManager.
+----------------------------------------------------------------------------
+r722646 | sccomer | 2008-12-02 16:38:21 CST
+
+change the exception thrown by AbstractStartable for already started and is not
+started to Exception from ThreadInterruptedException.
+
+change NullReferenceException thrown by AlarmManager when listener is null to
+ArgumentNullException.
+
+shell of unit test for AlarmManager.
+----------------------------------------------------------------------------
+r722629 | sccomer | 2008-12-02 16:04:52 CST
+
+expanded unit test for AlarmManager.
+
+mostly cosmetic edits for AlarmManager, except tightened up code which notifies
+worker thread when an alarm is removed (if no alarm is removed, then notify is
+not needed).
+----------------------------------------------------------------------------
+r722262 | sccomer | 2008-12-01 16:15:09 CST
+
+java fix for ETCH-11: AlarmManager deadlocks during shutdown().
+
+AlarmManager.shutdown() just calls AbstractStartable.stop() on the static
+instance.
+the bug was actually in AbstractStartable.stop().
+created unit test for AlarmManager which covers this case.
+----------------------------------------------------------------------------
+r722250 | sccomer | 2008-12-01 15:50:56 CST
+
+csharp fix for ETCH-17: SessionListener needs to be more independent.
+----------------------------------------------------------------------------
+r722248 | sccomer | 2008-12-01 15:48:53 CST
+
+improved the comment.
+----------------------------------------------------------------------------
+r722242 | sccomer | 2008-12-01 15:31:41 CST
+
+fix ETCH-6: if free pool exceeds maximum number of threads the exception thrown
+will kill the connection.
+
+also rearrange code in StubBase sessionMessage to enable optimization of NONE
+case.
+----------------------------------------------------------------------------
+r722240 | sccomer | 2008-12-01 15:29:21 CST
+
+fix issue with clock tick quanta in free pool tests.
+----------------------------------------------------------------------------
+r722208 | sccomer | 2008-12-01 14:00:37 CST
+
+implemented unit tests for FreePool in both csharp and java bindings.
+----------------------------------------------------------------------------
+r722205 | sccomer | 2008-12-01 13:58:44 CST
+
+fix for ETCH-23: FreePool has synchronization issues with quick back to back
+calls to Run.
+----------------------------------------------------------------------------
+r722116 | sccomer | 2008-12-01 10:33:04 CST
+
+csharp fix for ETCH-18: KeepAlive throws exception while trying to shutdown
+connection.
+
+fixed both csharp and java versions to use Todo during wakeup to send request
+so as to not block AlarmManager if there is a problem with the connection.
+----------------------------------------------------------------------------
+r722098 | sccomer | 2008-12-01 09:35:14 CST
+
+fix the fix for ETCH-8: canceling mailbox notification registration throws
+exception if not registered.
+
+unit tests for fix for ETCH-8.
+
+----------------------------------------------------------------------------
+r722085 | sccomer | 2008-12-01 08:42:58 CST
+
+java unit test for fix for ETCH-8.
+----------------------------------------------------------------------------
+r720572 | sccomer | 2008-11-25 13:43:44 CST
+
+fix for ETCH-8: canceling mailbox notification registration throws exception if
+not registered.
+----------------------------------------------------------------------------
+r720115 | sccomer | 2008-11-23 22:56:45 CST
+
+changes for selector code to be compatible with jdk 1.5.0_16.
+
+regularize the start/stop handling between Tcp2Listener and Tcp2Connection.
+----------------------------------------------------------------------------
+r719644 | sccomer | 2008-11-21 11:17:48 CST
+
+fixed the test for whether a Tcp2Connection is started.
+
+finalized some instance variables, and made handler private.
+
+synchronized setHandler.
+----------------------------------------------------------------------------
+r719414 | sccomer | 2008-11-20 16:50:55 CST
+
+checkpoint on selectors and transport which uses them.
+----------------------------------------------------------------------------
+r719413 | sccomer | 2008-11-20 16:43:43 CST
+
+correct the name of this test of TcpListener.
+----------------------------------------------------------------------------
+r719286 | sccomer | 2008-11-20 11:02:42 CST
+
+fix for etch-17: SessionListener needs to be more independent.
+fix for etch-19: Break out common tcp transport options so that they may be
+shared among various transports.
+----------------------------------------------------------------------------
+r719279 | sccomer | 2008-11-20 10:47:12 CST
+
+fix for etch-18: KeepAlive throws exception while trying to shutdown connection.
+----------------------------------------------------------------------------
+r713417 | gsandhir | 2008-11-12 10:13:38 CST
+
+Test to see if commit goes through
+----------------------------------------------------------------------------
+r713257 | niclas | 2008-11-11 21:55:20 CST
+
+Checking my own access.
+----------------------------------------------------------------------------
+r712814 | sccomer | 2008-09-30 10:13:12 CDT
+
+fix bug whereby a null enum value would not deserialize correctly. this also
+caused problems when additional elements were added to a service enum and then
+a mix of old and new implementations of the service used together.
+----------------------------------------------------------------------------
+r712813 | dixson3 | 2008-09-10 10:00:41 CDT
+
+skip csharp build on non-windows
+----------------------------------------------------------------------------
+
+-------------
+Release 1.0.1
+-------------
+
+r80 | sccomer | 2008-09-08 15:33:33 CDT
+
+added antlib resource for etch ant plugin, changed chat example to use it.
+----------------------------------------------------------------------------
+r79 | sccomer | 2008-09-08 13:40:12 CDT
+
+add csharp build to dist chat example.
+----------------------------------------------------------------------------
+r78 | sccomer | 2008-09-08 13:00:36 CDT
+
+custom README.txt for chat dist and make the directions all very similar.
+----------------------------------------------------------------------------
+r77 | sccomer | 2008-09-08 12:34:02 CDT
+
+added chat source to the distribution.
+----------------------------------------------------------------------------
+r76 | dixson3 | 2008-09-08 10:30:32 CDT
+
+Filter 'etch-maven-install.bat' to include the correct version number for etch
+Update csharp-unit-test targets to only run when 'BUILD.csharp' is set
+
+----------------------------------------------------------------------------
+r75 | sccomer | 2008-09-07 10:19:23 CDT
+
+updated ChangeLog.txt to the current state of the release.
+----------------------------------------------------------------------------
+
+r74 | sccomer | 2008-09-07 09:56:18 CDT
+r73 | sccomer | 2008-09-05 16:03:49 CDT
+r72 | sccomer | 2008-09-05 15:32:36 CDT
+r71 | sccomer | 2008-09-05 15:31:46 CDT
+r70 | dixson3 | 2008-09-05 08:31:53 CDT
+r69 | sccomer | 2008-09-04 18:03:04 CDT
+r68 | sccomer | 2008-09-04 18:02:24 CDT
+r67 | sccomer | 2008-09-04 09:16:38 CDT
+r66 | sccomer | 2008-09-04 09:14:53 CDT
+r65 | sccomer | 2008-09-02 16:25:03 CDT
+r64 | dixson3 | 2008-09-02 15:44:35 CDT
+r63 | sccomer | 2008-09-02 14:39:23 CDT
+r62 | sccomer | 2008-09-02 14:07:09 CDT
+r61 | sccomer | 2008-09-02 13:42:47 CDT
+r60 | dixson3 | 2008-09-02 11:16:17 CDT
+r59 | sccomer | 2008-09-02 10:41:54 CDT
+
+(various improvements to build scripts.)
+----------------------------------------------------------------------------
+r58 | sccomer | 2008-09-02 10:27:40 CDT
+
+make TestEtchMain.test7 dump msgs upon failure.
+----------------------------------------------------------------------------
+r57 | sccomer | 2008-09-02 07:49:21 CDT
+r56 | sccomer | 2008-09-02 07:35:20 CDT
+r55 | dixson3 | 2008-08-29 21:52:03 CDT
+r54 | dixson3 | 2008-08-29 15:48:01 CDT
+r53 | sccomer | 2008-08-29 10:37:05 CDT
+r52 | sccomer | 2008-08-28 16:05:49 CDT
+r51 | sccomer | 2008-08-28 15:40:26 CDT
+r50 | sccomer | 2008-08-28 14:23:50 CDT
+r49 | sccomer | 2008-08-28 11:04:32 CDT
+
+(various improvements to build scripts.)
+----------------------------------------------------------------------------
+r48 | sccomer | 2008-08-28 10:20:18 CDT
+
+merging changes to various build.xml from release 1.0.0 rev 5-6: mono support
+is not fully baked, use -DUSE.mono to test
+----------------------------------------------------------------------------
+r47 | sccomer | 2008-08-28 09:00:13 CDT
+
+fixed problem with java generated remote rejecting exceptions which are
+subclasses of allowed exceptions.
+----------------------------------------------------------------------------
+r46 | sccomer | 2008-08-27 19:31:44 CDT
+
+fix several bugs and add missing functionality to url so that java and csharp
+versions work the same.
+----------------------------------------------------------------------------
+r45 | sccomer | 2008-08-27 12:44:50 CDT
+
+if last chance exception handler in EtchMain catches an exception, it should
+print it.
+
+correct spelling of csharp Validator.Level enum element MISSING_OK.
+
+implement name for types and fields in csharp BinaryTaggedDataOutput.
+
+add named types and fields testing for csharp binary tagged data.
+----------------------------------------------------------------------------
+r44 | sccomer | 2008-08-26 13:29:24 CDT
+
+fix csharp BinaryTaggedDataInput to support names for types and fields.
+----------------------------------------------------------------------------
+r43 | sccomer | 2008-08-26 10:24:49 CDT
+
+merge compiler driver changes (and a few misc updates to unit tests) from
+branch sccomer-compiler-1 (revs 20-42) to trunk.
+----------------------------------------------------------------------------
+r28 | sccomer | 2008-08-22 11:39:29 CDT
+
+support for java BinaryTaggedDataInput and BinaryTaggedDataOutput using names
+instead of hashes of names for types and fields.
+----------------------------------------------------------------------------
+r27 | sccomer | 2008-08-22 11:38:24 CDT
+
+change java testUrl to better name (TestUrl1).
+----------------------------------------------------------------------------
+r26 | sccomer | 2008-08-22 11:37:41 CDT
+
+changed java codes from using Integer constructor to Integer.valueOf.
+----------------------------------------------------------------------------
+r25 | sccomer | 2008-08-22 11:36:51 CDT
+
+added command line control of starting listener also.
+----------------------------------------------------------------------------
+r24 | sccomer | 2008-08-22 11:35:45 CDT
+
+fix up java URL support of non-string terms.
+
+fully support Boolean in java URL.
+
+properly implement in java URL handling of remove( name, value ) when value
+is a singleton.
+----------------------------------------------------------------------------
+r9 | sccomer | 2008-08-01 15:37:49 CDT
+
+corrected csharp project dependences.
+
+corrected port numbers in distmap test.
+----------------------------------------------------------------------------
+r8 | sccomer | 2008-08-01 14:17:27 CDT
+
+integrated remaining examples into csharp build.
+
+bumped version numbers of expected build to 1.0.1.
+----------------------------------------------------------------------------
+r7 | sccomer | 2008-07-31 15:58:29 CDT
+
+added csharp build of most of the examples.
+
+substitute DOTNET_HOME environment variable for gnarley dot net path in various
+build.xml. this allows disabling the csharp build for those that don't want it.
+
+example ant build setup (antsetup.bat), shows which environment variable and
+path manipulations you need for a build. also shows which ones are optional.
+
+corrected port numbers of distmap example.
+----------------------------------------------------------------------------
+Gaurav was Here
+
+-------------
+Release 1.0.0
+-------------
diff --git a/KEYS b/KEYS
new file mode 100644
index 0000000..987d488
--- /dev/null
+++ b/KEYS
@@ -0,0 +1,46 @@
+This file contains the PGP keys of various developers.
+
+Users: pgp < KEYS
+       gpg --import KEYS
+       Developers: 
+               pgp -kxa <your name> and append it to this file.
+               (pgpk -ll <your name> && pgpk -xa <your name>) >> this file.
+               (gpg --list-sigs <your name>
+                    && gpg --armor --export <your name>) >> this file.
+
+pub   1024D/F18E2A13 2009-02-04
+uid                  James Dixson (CODE SIGNING KEY) <dixson@apache.org>
+sig 3        F18E2A13 2009-02-04  James Dixson (CODE SIGNING KEY) <dixson@apache.org>
+sub   2048g/353721F9 2009-02-04
+sig          F18E2A13 2009-02-04  James Dixson (CODE SIGNING KEY) <dixson@apache.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.9 (Darwin)
+
+mQGiBEmKEnsRBAChrlGgZom8tAup/WeNnq09HjsvUw1shEGmIYmQ1My0u+zNA0OK
+iF/ZkJW4ao22eYqIvw+3a80CG/QHqf7VPUdh48TddVsDeYgpqoYCL+SaXJ0djWH2
+45piZmAawdd0gnuJkVUGjVm2lHQJIAhgpxh2dR3BN4RgMInyZAqXReq0VwCgnvRn
+iDm3doCUnfhl00UkQcl4KAED/RReavNu/tNR5Ourv62KTs36yKIBOqfz0q+9QErl
+h3E9SQsEqYp8tuQ8MqOVo50+vtrOldHEiOnBjbLG12dN8anR44l9rNT022JRA3V0
+kuXQw85chsTy5m6IBcLRemCe4cKN37YHyAzeFsSLry4wyc84B1jVJiUdajvTmW+p
+kPnGA/9MUd6oIvGTa2fbg4Vo8yPHeOq4QfgkU8hNW70uMPU4wCMMJ6BH5LdwNrNc
+iruBW4wFAbBufWYsW5FAY3j89/Lv1oHYfMIiHaU1QfrpzmvlFpnlPZEFB1uTJjQT
+MU3dQxzq9t8BvnqWrxpRx7ZxQosIGqFmKLXn5GEayhN/hyqwIrQzSmFtZXMgRGl4
+c29uIChDT0RFIFNJR05JTkcgS0VZKSA8ZGl4c29uQGFwYWNoZS5vcmc+iGAEExEC
+ACAFAkmKEnsCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCerigk8Y4qE1Yx
+AJ495RyPWkTxVfKN3g8KGNw6UGVFUgCeLwdHaoynhtHP9TwHnK3HU/gRLK65Ag0E
+SYoSexAIAN3fRCOy0F/GhBA9oNHtDK4IRcs44YF9P3sTlmGIniJ7xKsSZlYNe5wy
+VLTrmXk2ERWFueH9jUBeDM9AzHGMQBX+8IqKI4Z3Doow1rg2VHLclERR9eyRzH3b
+Scub8Asn7qLZwhuBFpIsJ1gGygirFw+wNlmX00MVQmHwFJoudkEXBcXMxhlergeS
+NldBTIraKC5/dzTakENq5nJqCKqYj8CHp4ZDfGUFvVaw+Wza2VwzBc5sACxyIVqO
+xfPRRiEfVhEqd1Y3DXkTU4OSqTqZnnnVGZx3LZNyfyG4Ku9Fm5OWrOX4Gy2Hmp7U
+KxTrV5e/AFUri3mIBsoZIDBPlN/9VG8ABAsH/RLbnZib0He0JG3evIqzks5SCH74
+fXFjEtOSuDqcyGYu93eD+Ui3BwrMogEDUQ62MlxKRb4bvb6CqlgGhO0zr38i6i82
+yfw3iAnj8s62qKgW/Fk+M+Qi55990NIIygbRdoRp390kJESccN/gaE61j4ES+gqQ
+/F/qCxb9gmoxCNRJIbhRacRhX3Zk0dF99meygF8hc++lXF9p//Mv0/CTRch6YIW4
+V0U0+VYsS2fZdFT/wSiqI6Wt+CZxzAorEO7QZOrCSU9w/8tvFuPp5tdTvJDkO7kW
+8avQwvpwr3rOJWZj0v+BehwQ0brDKqavgR3aHr+85RzuMNe7oso34hrAfByISQQY
+EQIACQUCSYoSewIbDAAKCRCerigk8Y4qE/2zAJ0Yh12VznL3tk2/OZU2oPIMA0FR
+sACfSn/Myyx3nrpwWtQTFf83n/8Lu2E=
+=LLpx
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..1572beb
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,203 @@
+/*
+ *                                 Apache License
+ *                           Version 2.0, January 2004
+ *                        http://www.apache.org/licenses/
+ *
+ *   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+ *
+ *   1. Definitions.
+ *
+ *      "License" shall mean the terms and conditions for use, reproduction,
+ *      and distribution as defined by Sections 1 through 9 of this document.
+ *
+ *      "Licensor" shall mean the copyright owner or entity authorized by
+ *      the copyright owner that is granting the License.
+ *
+ *      "Legal Entity" shall mean the union of the acting entity and all
+ *      other entities that control, are controlled by, or are under common
+ *      control with that entity. For the purposes of this definition,
+ *      "control" means (i) the power, direct or indirect, to cause the
+ *      direction or management of such entity, whether by contract or
+ *      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ *      outstanding shares, or (iii) beneficial ownership of such entity.
+ *
+ *      "You" (or "Your") shall mean an individual or Legal Entity
+ *      exercising permissions granted by this License.
+ *
+ *      "Source" form shall mean the preferred form for making modifications,
+ *      including but not limited to software source code, documentation
+ *      source, and configuration files.
+ *
+ *      "Object" form shall mean any form resulting from mechanical
+ *      transformation or translation of a Source form, including but
+ *      not limited to compiled object code, generated documentation,
+ *      and conversions to other media types.
+ *
+ *      "Work" shall mean the work of authorship, whether in Source or
+ *      Object form, made available under the License, as indicated by a
+ *      copyright notice that is included in or attached to the work
+ *      (an example is provided in the Appendix below).
+ *
+ *      "Derivative Works" shall mean any work, whether in Source or Object
+ *      form, that is based on (or derived from) the Work and for which the
+ *      editorial revisions, annotations, elaborations, or other modifications
+ *      represent, as a whole, an original work of authorship. For the purposes
+ *      of this License, Derivative Works shall not include works that remain
+ *      separable from, or merely link (or bind by name) to the interfaces of,
+ *      the Work and Derivative Works thereof.
+ *
+ *      "Contribution" shall mean any work of authorship, including
+ *      the original version of the Work and any modifications or additions
+ *      to that Work or Derivative Works thereof, that is intentionally
+ *      submitted to Licensor for inclusion in the Work by the copyright owner
+ *      or by an individual or Legal Entity authorized to submit on behalf of
+ *      the copyright owner. For the purposes of this definition, "submitted"
+ *      means any form of electronic, verbal, or written communication sent
+ *      to the Licensor or its representatives, including but not limited to
+ *      communication on electronic mailing lists, source code control systems,
+ *      and issue tracking systems that are managed by, or on behalf of, the
+ *      Licensor for the purpose of discussing and improving the Work, but
+ *      excluding communication that is conspicuously marked or otherwise
+ *      designated in writing by the copyright owner as "Not a Contribution."
+ *
+ *      "Contributor" shall mean Licensor and any individual or Legal Entity
+ *      on behalf of whom a Contribution has been received by Licensor and
+ *      subsequently incorporated within the Work.
+ *
+ *   2. Grant of Copyright License. Subject to the terms and conditions of
+ *      this License, each Contributor hereby grants to You a perpetual,
+ *      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ *      copyright license to reproduce, prepare Derivative Works of,
+ *      publicly display, publicly perform, sublicense, and distribute the
+ *      Work and such Derivative Works in Source or Object form.
+ *
+ *   3. Grant of Patent License. Subject to the terms and conditions of
+ *      this License, each Contributor hereby grants to You a perpetual,
+ *      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ *      (except as stated in this section) patent license to make, have made,
+ *      use, offer to sell, sell, import, and otherwise transfer the Work,
+ *      where such license applies only to those patent claims licensable
+ *      by such Contributor that are necessarily infringed by their
+ *      Contribution(s) alone or by combination of their Contribution(s)
+ *      with the Work to which such Contribution(s) was submitted. If You
+ *      institute patent litigation against any entity (including a
+ *      cross-claim or counterclaim in a lawsuit) alleging that the Work
+ *      or a Contribution incorporated within the Work constitutes direct
+ *      or contributory patent infringement, then any patent licenses
+ *      granted to You under this License for that Work shall terminate
+ *      as of the date such litigation is filed.
+ *
+ *   4. Redistribution. You may reproduce and distribute copies of the
+ *      Work or Derivative Works thereof in any medium, with or without
+ *      modifications, and in Source or Object form, provided that You
+ *      meet the following conditions:
+ *
+ *      (a) You must give any other recipients of the Work or
+ *          Derivative Works a copy of this License; and
+ *
+ *      (b) You must cause any modified files to carry prominent notices
+ *          stating that You changed the files; and
+ *
+ *      (c) You must retain, in the Source form of any Derivative Works
+ *          that You distribute, all copyright, patent, trademark, and
+ *          attribution notices from the Source form of the Work,
+ *          excluding those notices that do not pertain to any part of
+ *          the Derivative Works; and
+ *
+ *      (d) If the Work includes a "NOTICE" text file as part of its
+ *          distribution, then any Derivative Works that You distribute must
+ *          include a readable copy of the attribution notices contained
+ *          within such NOTICE file, excluding those notices that do not
+ *          pertain to any part of the Derivative Works, in at least one
+ *          of the following places: within a NOTICE text file distributed
+ *          as part of the Derivative Works; within the Source form or
+ *          documentation, if provided along with the Derivative Works; or,
+ *          within a display generated by the Derivative Works, if and
+ *          wherever such third-party notices normally appear. The contents
+ *          of the NOTICE file are for informational purposes only and
+ *          do not modify the License. You may add Your own attribution
+ *          notices within Derivative Works that You distribute, alongside
+ *          or as an addendum to the NOTICE text from the Work, provided
+ *          that such additional attribution notices cannot be construed
+ *          as modifying the License.
+ *
+ *      You may add Your own copyright statement to Your modifications and
+ *      may provide additional or different license terms and conditions
+ *      for use, reproduction, or distribution of Your modifications, or
+ *      for any such Derivative Works as a whole, provided Your use,
+ *      reproduction, and distribution of the Work otherwise complies with
+ *      the conditions stated in this License.
+ *
+ *   5. Submission of Contributions. Unless You explicitly state otherwise,
+ *      any Contribution intentionally submitted for inclusion in the Work
+ *      by You to the Licensor shall be under the terms and conditions of
+ *      this License, without any additional terms or conditions.
+ *      Notwithstanding the above, nothing herein shall supersede or modify
+ *      the terms of any separate license agreement you may have executed
+ *      with Licensor regarding such Contributions.
+ *
+ *   6. Trademarks. This License does not grant permission to use the trade
+ *      names, trademarks, service marks, or product names of the Licensor,
+ *      except as required for reasonable and customary use in describing the
+ *      origin of the Work and reproducing the content of the NOTICE file.
+ *
+ *   7. Disclaimer of Warranty. Unless required by applicable law or
+ *      agreed to in writing, Licensor provides the Work (and each
+ *      Contributor provides its Contributions) on an "AS IS" BASIS,
+ *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ *      implied, including, without limitation, any warranties or conditions
+ *      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ *      PARTICULAR PURPOSE. You are solely responsible for determining the
+ *      appropriateness of using or redistributing the Work and assume any
+ *      risks associated with Your exercise of permissions under this License.
+ *
+ *   8. Limitation of Liability. In no event and under no legal theory,
+ *      whether in tort (including negligence), contract, or otherwise,
+ *      unless required by applicable law (such as deliberate and grossly
+ *      negligent acts) or agreed to in writing, shall any Contributor be
+ *      liable to You for damages, including any direct, indirect, special,
+ *      incidental, or consequential damages of any character arising as a
+ *      result of this License or out of the use or inability to use the
+ *      Work (including but not limited to damages for loss of goodwill,
+ *      work stoppage, computer failure or malfunction, or any and all
+ *      other commercial damages or losses), even if such Contributor
+ *      has been advised of the possibility of such damages.
+ *
+ *   9. Accepting Warranty or Additional Liability. While redistributing
+ *      the Work or Derivative Works thereof, You may choose to offer,
+ *      and charge a fee for, acceptance of support, warranty, indemnity,
+ *      or other liability obligations and/or rights consistent with this
+ *      License. However, in accepting such obligations, You may act only
+ *      on Your own behalf and on Your sole responsibility, not on behalf
+ *      of any other Contributor, and only if You agree to indemnify,
+ *      defend, and hold each Contributor harmless for any liability
+ *      incurred by, or claims asserted against, such Contributor by reason
+ *      of your accepting any such warranty or additional liability.
+ *
+ *   END OF TERMS AND CONDITIONS
+ *
+ *   APPENDIX: How to apply the Apache License to your work.
+ *
+ *      To apply the Apache License to your work, attach the following
+ *      boilerplate notice, with the fields enclosed by brackets "[]"
+ *      replaced with your own identifying information. (Don't include
+ *      the brackets!)  The text should be enclosed in the appropriate
+ *      comment syntax for the file format. We also recommend that a
+ *      file or class name and description of purpose be included on the
+ *      same "printed page" as the copyright notice for easier
+ *      identification within third-party archives.
+ *
+ *   Copyright [yyyy] [name of copyright owner]
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ */
\ No newline at end of file
diff --git a/NOTICE.txt b/NOTICE.txt
new file mode 100644
index 0000000..ad3daf3
--- /dev/null
+++ b/NOTICE.txt
@@ -0,0 +1,8 @@
+Apache Etch (incubating)
+
+Copyright (C) 2008-2009 The Apache Software Foundation
+Copyright (C) 2007-2008 Cisco Systems Inc.
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..cee51b3
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,97 @@
+Welcome to the 1.0.2-incubating release of Apache Etch.
+
+The jumping off point for Etch information and help is here:
+
+http://cwiki.apache.org/ETCH
+
+The top-level structure of the install image is:
+
+	ChangeLog.txt
+	LICENSE.txt
+	README.txt
+    NOTICE.txt
+    RELEASE_NOTES.txt
+	bin/
+	lib/
+    examples/
+	maven/
+    uninst.exe (windows only)
+
+Please take a moment to review the RELEASE_NOTES.txt, ChangeLog.txt and
+LICENSE.txt files.
+
+The Windows installer (apache-etch-1.0.2-incubating-setup.exe) has created a 
+user environment variable (ETCH_HOME) which points to the Etch installation
+directory. If you installed Etch using either apache-etch-1.0.2-incubating-bin.tar.gz
+or apache-etch-1.0.2-incubating-bin.zip, you will want to create this environment
+variable yourself:
+
+windows:
+	set ETCH_HOME=C:\Program Files\Apache Software Foundation\apache-etch-1.0.2-incubating
+
+*nix:
+	export ETCH_HOME=/path/to/apache-etch-1.0.2-incubating
+
+The bin directory has also been put on your path by the Windows installer. If
+you are using the archives, you will need to do this yourself:
+
+windows:
+	PATH %PATH%;%ETCH_HOME%\bin
+
+*nix:
+	export PATH="$PATH:$ETCH_HOME/bin"
+
+The bin/ directory contains a Windows bat script and a unix shell script.
+
+You will also need to have a java sdk installed (later versions of 1.5 or
+any version of 1.6). A JAVA_HOME environment variable should point to the
+installation directory of the java sdk.
+
+In the end, at a command line or shell, you should be able to run the etch
+compiler and see some basic output:
+
+windows:
+	C:\>etch
+	etch: option '-b binding' must be specified on the command line
+
+unix:
+	bash-3.2$ etch
+	etch: option '-b binding' must be specified on the command line
+
+The lib directory contains the various jar files, zipped sources, and a C# dll:
+
+	Etch.dll
+	etch-ant-plugin-1.0.2-src.zip
+	etch-ant-plugin-1.0.2.jar
+	etch-java-runtime-1.0.2-src.zip
+	etch-java-runtime-1.0.2.jar
+	...
+
+The main items of interest are the language binding runtimes, which you need to
+link with your projects.
+
+For java you need to put on the classpath of your projects: etch-java-runtime-1.0.2.jar.
+There is source code to go with it in etch-java-runtime-1.0.2-src.zip.
+
+The C# (.NET 2.0) Etch.dll should be added to any C# projects.
+
+There is an ant plugin which you can use with ant 1.7.0 or later to invoke the
+compiler as a task. It is documented on the wiki referenced above.
+
+If you are using maven, then you might want to install the Etch artifacts into
+your local maven repository. There is a Windows bat script to do this in the
+maven directory:
+
+	etch-maven-install.bat
+
+You need to have maven on your path when you run this script. The file
+etch-java-runtime-1.0.2.jar will be installed into your local repository with
+group "etch.etch", artifact id "etch-java-runtime", and version "1.0.2". You
+may then reference Etch from your maven projects.
+
+Examples have been provided in the examples/ subdirectory.
+
+Unit tests can be had by checking out the source code from the
+subversion repository and performing a complete build:
+
+ https://svn.apache.org/repos/asf/incubator/etch/releases/release-1.0.2
diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt
new file mode 100644
index 0000000..e56cd13
--- /dev/null
+++ b/RELEASE_NOTES.txt
@@ -0,0 +1,68 @@
+Welcome to Apache Etch 1.0.2. Etch is now incubating at apache.org. You can find
+us here:
+
+Project info:
+
+	http://incubator.apache.org/projects/etch.html
+
+Documentation info:
+
+	http://cwiki.apache.org/ETCH/
+
+Issues:
+
+	https://issues.apache.org/jira/browse/ETCH
+
+SVN:
+
+	http://svn.apache.org/repos/asf/incubator/etch/
+
+Mailing lists:
+
+	mailto:etch-dev@incubator.apache.org (etch developers)
+	mailto:etch-users@incubator.apache.org (etch users)
+
+Subscribing to the mailing lists:
+
+	mailto:etch-dev-subscribe@incubator.apache.org (etch developers)
+	mailto:etch-users-subscribe@incubator.apache.org (etch users)
+
+This release of Etch is the first from our new home at Apache. It is a bug fix
+release only. While some new functionality has been committed to the tree, it
+is not yet functional enough to claim that you should use it.
+
+Here are the issues resolved in this release:
+
+Key			Res		Summary
+ETCH-6		Fixed	If free pool exceeds maximum number of threads the exception
+					thrown will kill the connection.
+ETCH-8		Fixed 	Canceling mailbox notification registration throws exception
+					if not registered.
+ETCH-11 	Fixed 	AlarmManager deadlocks during shutdown().
+ETCH-13 	Fixed 	Copy the rest of the example sources into the distribution.
+ETCH-17 	Fixed 	SessionListener needs to be more independent.
+ETCH-18 	Fixed 	KeepAlive throws exception while trying to shutdown
+					connection.
+ETCH-19 	Fixed 	Break out common tcp transport options so that they may be
+					shared among various transports.
+ETCH-23 	Fixed 	FreePool has synchronization issues with quick back to back
+					calls to Run.
+ETCH-24 	Fixed 	The message direction is always "server" for the
+					result_method messages in the java-binding valuefactory.
+ETCH-25 	Fixed 	DefaultDeliveryService ends call with mb.CloseDelivery() and
+					it should end it with mb.CloseRead().
+ETCH-27 	Fixed 	Mixins cause trouble when two or more mixed in files define
+					a type with the same name.
+ETCH-28 	Fixed 	Examples do not build due to outdated ant files.
+ETCH-29 	Fixed 	Installing all Maven artifacts along with their sources.
+ETCH-31 	Fixed 	MySessionListener in TcpTransportFactory does not override
+					toString() method to show something useful about the
+					transport stack.
+
+Here are the outstanding issues in this release:
+
+Key 		Summary
+ETCH-12 	An exception return value from a message is indistinguishable from a
+			thrown exception.
+ETCH-26 	Some unexpected exceptions are thrown if .Net Framework Language
+			Pack is installed.
diff --git a/binding-csharp/build.xml b/binding-csharp/build.xml
new file mode 100644
index 0000000..d2b4179
--- /dev/null
+++ b/binding-csharp/build.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+-->
+<project name="etch-csharp-binding" basedir="." default="help">
+    <description>Etch-to-Csharp Binding</description>
+    <property name="Etch.basedir" location="${basedir}/.." />
+    <import file="${Etch.basedir}/build-support/etch.common.xml" />
+	<target name="help"><echo>Please select a target...</echo></target>
+
+    <!-- standard, supported targets -->
+    <target name="Debug"         depends="debug" />
+    <target name="Release"       depends="release" />
+    <target name="Clean"         depends="clean" />
+    <target name="debug"         depends="init-debug,component-all,post-debug"   />
+    <target name="release"       depends="init-release,component-all,post-release" />
+    <target name="clean"         depends="init-clean,component-all,post-clean" />
+    <target name="maven-install" depends="init-maven,release" />
+
+    <target name="init-maven" >
+        <property name="DO.maven.install" value="true" />
+    </target>
+
+    <target name="validate-dependencies" >
+        <mkdir dir="${Etch.logDirectory}" />
+    </target>
+
+    <target name="init-debug" depends="validate-dependencies" >
+        <property name="Etch.build.target" value="Debug" />
+        <property name="Etch.javac.debug" value="on" />
+        <property name="Etch.javac.optimize" value="off" />
+    </target>
+
+    <target name="post-debug" >
+    </target>
+
+    <target name="init-release" depends="validate-dependencies">
+        <!-- For now, keep debug-symbols and no-optimize, even for release builds -->
+        <property name="Etch.build.target" value="Release" />
+        <property name="Etch.javac.debug"  value="on" />
+        <property name="Etch.javac.optimize" value="off" />
+        <!--
+        <property name="Etch.javac.debug"  value="off" />
+        <property name="Etch.javac.optimize" value="on" />
+        -->
+    </target>
+
+    <target name="post-release" >
+    </target>
+
+    <target name="init-clean" depends="validate-dependencies">
+        <property name="Etch.build.target" value="Clean" />
+    </target>
+
+    <target name="post-clean" >
+        <echo message="Executing clean" />
+    </target>
+
+    <target name="component-all" >
+        <build_component dir="compiler" />
+        <build_component dir="runtime" />
+    </target>
+
+</project>
diff --git a/binding-csharp/compiler/build.xml b/binding-csharp/compiler/build.xml
new file mode 100644
index 0000000..1f4df4c
--- /dev/null
+++ b/binding-csharp/compiler/build.xml
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+-->
+<project name="etch-csharp-compiler" basedir="." default="help">
+    <description>Etch-to-Csharp compiler implementation</description>
+    <property name="Etch.basedir" location="${basedir}/../.." />
+    <import file="${Etch.basedir}/build-support/etch.includes.xml" />
+
+    <!-- Static properties of the sub-project -->
+    <property name="proj"                 location="${Etch.basedir}/binding-csharp/compiler" />
+    <property name="target"               location="${proj}/target" />
+    <property name="src"                  location="${proj}/src" />
+    <property name="generatedSrc"         location="${target}/generated-sources" />
+    <property name="classesDirectory"     location="${target}/classes" />
+    <property name="resourcesDirectory"   location="${target}/resources" />
+    <property name="testResultsDirectory" location="${target}/test-results" />
+
+    <!-- MACRO: init-target -->
+    <macrodef name="init-target" >
+        <sequential>
+            <delete dir="${classesDirectory}"   failonerror="false" quiet="true" />
+            <delete dir="${resourcesDirectory}" failonerror="false" quiet="true" />
+            <mkdir dir="${classesDirectory}" />
+            <mkdir dir="${classesDirectory}/main" />
+            <mkdir dir="${classesDirectory}/test" />
+            <mkdir dir="${resourcesDirectory}" />
+        </sequential>
+    </macrodef>
+
+    <!-- MACRO: compile-sources -->
+    <macrodef name="compile-sources" >
+        <sequential>
+            <!-- compile compiler plugin -->
+            <javac  debug="${Etch.javac.debug}"
+                    target="1.5"
+                    optimize="${Etch.javac.optimize}"
+                    destdir="${classesDirectory}/main" >
+                <src path="${src}/main/java" />
+                <exclude name="**/.svn/**" />
+                <classpath refid="Etch.dependencies.jar.paths" />
+                <classpath>
+                    <pathelement location="${Etch.HOME}/lib/${etch-compiler.jar}" />
+                </classpath>
+            </javac>
+
+            <!-- compiler plugin resources -->
+            <copy todir="${classesDirectory}/main" >
+                <fileset dir="${src}/main/resources">
+                    <include name="**/*.kwd" />
+                    <include name="**/*.vm" />
+                </fileset>
+            </copy>
+
+            <!--
+            <javac  debug="${Etch.javac.debug}"
+                    target="1.5"
+                    optimize="${Etch.javac.optimize}"
+                    destdir="${classesDirectory}/test" >
+                <src path="${src}/test/java" />
+                <exclude name="**/.svn/**" />
+                <classpath refid="Etch.dependencies.jar.paths" />
+                <classpath>
+                    <pathelement location="${classesDirectory}/main" />
+                    <pathelement location="${Etch.HOME}/lib/${etch-compiler.jar}" />
+                </classpath>
+            </javac>
+            -->
+
+        </sequential>
+    </macrodef>
+
+    <!-- MACRO: bundle-jars -->
+    <macrodef name="bundle-jars" >
+        <attribute name="dist" default="${Etch.dist}" />
+        <sequential>
+            <mkdir dir="@{dist}/lib" />
+
+            <!-- CREATE jars -->
+
+            <!-- Package up etch-csharp-compiler jar -->
+            <jar jarfile="@{dist}/lib/${etch-csharp-compiler.jar}" >
+                <manifest>
+                    <attribute name="Copyright"    value="${Etch.copyrightNotice}" />
+                    <attribute name="Version"      value="${Etch.version}" />
+                    <attribute name="LongVersion"  value="${Etch.longversion}" />
+                    <attribute name="Build-Tag"    value="${Etch.buildTag}" />
+                    <attribute name="SVN-Revision" value="${Etch.runtime.revisionNumber}" />
+                </manifest>
+                <metainf dir="${Etch.basedir}" >
+                    <include name="NOTICE.txt" />
+                    <include name="LICENSE.txt" />
+                </metainf>
+                <fileset dir="${classesDirectory}/main">
+                    <include name="org/apache/etch/bindings/**" />
+                    <!-- <include name="resources/**" /> -->
+                </fileset>
+            </jar>
+
+            <!-- CREATE source archives -->
+
+            <!-- package up etch-csharp-compiler src -->
+            <zip destfile="@{dist}/lib/${etch-csharp-compiler-src.zip}" >
+                <fileset dir="${src}/main/java" >
+                    <include name="org/apache/etch/bindings/**/*.java" />
+                </fileset>
+                <fileset dir="${src}/main/resources" >
+                    <include name="**/*" />
+                </fileset>
+            </zip>
+
+        </sequential>
+    </macrodef>
+
+    <!-- INIT TARGET -->
+    <!-- Modify this target to define project specific properties that can only be set at runtime -->
+    <target name="do-init">
+        <delete dir="${target}" failonerror="false" quiet="true" />
+
+        <mkdir dir="${target}" />
+        <mkdir dir="${generatedSrc}" />
+        <mkdir dir="${classesDirectory}" />
+        <mkdir dir="${resourcesDirectory}" />
+        <mkdir dir="${testResultsDirectory}" />
+    </target>
+
+    <!-- CLEAN TARGET -->
+    <target name="do-clean">
+        <delete dir="${target}" />
+    </target>
+
+    <!-- BUILD TARGET -->
+
+    <target name="generate-sources" >
+        <!-- Generate version info -->
+        <update-tokens filename="${src}/main/java/org/apache/etch/bindings/csharp/compiler/CompilerVersion.java" />
+    </target>
+
+    <target name="compile-for-dist" >
+        <!-- Initialize target directories -->
+        <init-target />
+
+        <!-- Compile Source -->
+        <compile-sources />
+
+        <!-- Bundle Jars -->
+        <bundle-jars dist="${Etch.dist}" />
+    </target>
+
+    <target name="compile-for-clover" if="Clover.enabled" >
+
+        <echo message="Rebuilding with clover" />
+
+        <!-- initialize-clover -->
+        <initialize-clover suffix="etchcsharpcompiler" >
+            <fileset dir="${src}/main/java">
+                <include name="**/*.java" />
+            </fileset>
+            <!--
+            <testsources dir="${src}/test/java">
+                <include name="**/*.java" />
+            </testsources>
+            -->
+        </initialize-clover>
+
+        <!-- Initialize target directories -->
+        <init-target />
+
+        <!-- Compile Source -->
+        <compile-sources />
+
+        <!-- Bundle Jars -->
+        <bundle-jars dist="${Etch.clover-dist}" />
+
+    </target>
+
+    <target name="do-build" depends="generate-sources,compile-for-dist,compile-for-clover" />
+
+    <!-- TEST TARGET -->
+    <target name="do-test">
+
+        <!-- Run Unit Tests -->
+        <!--
+        <junit printsummary="yes" haltonfailure="no" dir="${classesDirectory}"
+            errorProperty="build.tests.fail" failureProperty="build.tests.fail">
+            <classpath>
+                <pathelement location="${classesDirectory}/main" />
+                <pathelement location="${classesDirectory}/test" />
+                <pathelement location="${Etch.dependency.junit.jar}" />
+                <pathelement location="${Etch.HOME}/lib/${etch-compiler.jar}" />
+                <pathelement location="${Etch.dependency.clover.jar}"/>
+            </classpath>
+            <formatter type="xml"/>
+            <batchtest fork="true" todir="${testResultsDirectory}">
+                <fileset dir="${src}/test/java">
+                    <include name="**/*.java" />
+                </fileset>
+            </batchtest>
+        </junit>
+        -->
+    </target>
+
+    <!-- POSTBUILD TARGET -->
+    <target name="do-postbuild">
+    </target>
+
+    <target name="do-publish" if="build.tests.fail">
+        <!-- Set flag file if any tests failed -->
+        <touch file="${Etch.runtime.tests.fail}"/>
+    </target>
+
+</project>
diff --git a/binding-csharp/compiler/src/main/java/org/apache/etch/bindings/csharp/compiler/Compiler.java b/binding-csharp/compiler/src/main/java/org/apache/etch/bindings/csharp/compiler/Compiler.java
new file mode 100644
index 0000000..56661ab
--- /dev/null
+++ b/binding-csharp/compiler/src/main/java/org/apache/etch/bindings/csharp/compiler/Compiler.java
@@ -0,0 +1,1161 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.csharp.compiler;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.CmdLineOptions;
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.LogHandler;
+import org.apache.etch.compiler.Output;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.Token;
+import org.apache.etch.compiler.Version;
+import org.apache.etch.compiler.ast.Builtin;
+import org.apache.etch.compiler.ast.Except;
+import org.apache.etch.compiler.ast.Item;
+import org.apache.etch.compiler.ast.Message;
+import org.apache.etch.compiler.ast.MessageDirection;
+import org.apache.etch.compiler.ast.Module;
+import org.apache.etch.compiler.ast.MsgDirHelper;
+import org.apache.etch.compiler.ast.Name;
+import org.apache.etch.compiler.ast.Named;
+import org.apache.etch.compiler.ast.ParamList;
+import org.apache.etch.compiler.ast.Parameter;
+import org.apache.etch.compiler.ast.ReservedWordChecker;
+import org.apache.etch.compiler.ast.Service;
+import org.apache.etch.compiler.ast.Struct;
+import org.apache.etch.compiler.ast.Thrown;
+import org.apache.etch.compiler.ast.TypeRef;
+import org.apache.etch.compiler.opt.ToString;
+import org.apache.etch.compiler.opt.ToString.FieldItem;
+import org.apache.etch.compiler.opt.ToString.FmtItem;
+import org.apache.etch.compiler.opt.ToString.StringItem;
+import org.apache.etch.util.Assertion;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.exception.ResourceNotFoundException;
+import org.apache.velocity.runtime.RuntimeServices;
+import org.apache.velocity.runtime.log.LogChute;
+
+
+/**
+ * Compiler is a helper class not only for Backend, but also for the templates.
+ * They call methods here to perform "hard" tasks.
+ */
+public class Compiler extends Backend
+{
+	private final static String tmplPath1 = "org/apache/etch/bindings/csharp/compiler/";
+
+	private final static String tmplPath2 = "resources/org/apache/etch/bindings/csharp/compiler/";
+
+	private final static String fnSuffix = ".cs";
+
+	private final static String VERSION = Version.VERSION + " / "
+		+ CompilerVersion.VERSION;
+
+	/**
+	 * Constructs the Compiler. This is a helper class not only for Backend, but
+	 * also for the templates. They call methods here to perform "hard" tasks.
+	 *
+	 * @throws Exception
+	 */
+	public Compiler() throws Exception
+	{
+		initVelocity();
+		
+		String[] path = { tmplPath1, tmplPath2 };
+		vf_vm = getTemplate( path, "vf.vm" );
+		intf_vm = getTemplate( path, "intf.vm" );
+		remote_vm = getTemplate( path, "remote.vm" );
+		stub_vm = getTemplate( path, "stub.vm" );
+		helper_vm = getTemplate( path, "helper.vm" );
+		readme_vm = getTemplate( path, "readme.vm" );
+		main_vm = getTemplate( path, "main.vm" );
+		base_vm = getTemplate( path, "base.vm" );
+		impl_vm = getTemplate( path, "impl.vm" );
+
+		local_kwd = getPath( path, "csharpKeywords.kwd" );
+	}
+
+	private final Template vf_vm;
+
+	private final Template intf_vm;
+
+	private final Template remote_vm;
+
+	private final Template stub_vm;
+
+	private final Template helper_vm;
+
+	private final Template readme_vm;
+
+	private final Template main_vm;
+
+	private final Template base_vm;
+
+	private final Template impl_vm;
+
+	private final String local_kwd;
+
+	private LogHandler lh;
+	
+	/**
+	 * Initializes use of velocity engine and sets up
+	 * resource loaders.
+	 * @throws Exception
+	 */
+	private void initVelocity()
+		throws Exception
+	{
+		Velocity.setProperty( Velocity.RUNTIME_LOG_LOGSYSTEM, new MyLogger() );
+		
+		Velocity.setProperty( Velocity.RESOURCE_LOADER, "file, class" );
+
+		Velocity.setProperty( "file.resource.loader.description", "Velocity File Resource Loader" );
+		Velocity.setProperty( "file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.FileResourceLoader" );
+		Velocity.setProperty( "file.resource.loader.path", "." );
+
+		Velocity.setProperty( "class.resource.loader.description", "Velocity Classpath Resource Loader" );
+		Velocity.setProperty( "class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader" );
+		
+		Velocity.init();
+	}
+	
+	private static class MyLogger implements LogChute
+	{
+		private final LogHandler lh = null;
+		
+		public void init( RuntimeServices rts ) throws Exception
+		{
+			// ignore.
+		}
+
+		public boolean isLevelEnabled( int level )
+		{
+			return level >= 2;
+		}
+
+		public void log( int level, String msg )
+		{
+			if (level < 2)
+				return;
+			
+			if (lh != null)
+				lh.report( level == 2 ? LogHandler.LEVEL_WARNING : LogHandler.LEVEL_ERROR, null, msg );
+			else
+				System.out.printf( "Velocity msg (%d): %s\n", level, msg );
+		}
+
+		public void log( int level, String msg, Throwable e )
+		{
+			if (level < 2)
+				return;
+			
+			if (lh != null)
+				lh.report( level == 2 ? LogHandler.LEVEL_WARNING : LogHandler.LEVEL_ERROR, null, msg );
+			else
+				System.out.printf( "Velocity msg (%d): %s: %s\n", level, msg, e );
+		}
+	}
+
+	/**
+	 * @param path
+	 * @param fn
+	 * @return the velocity template
+	 * @throws Exception
+	 */
+	private Template getTemplate( String[] path, String fn )
+		throws Exception
+	{
+		ResourceNotFoundException rnfe = null;
+		
+		for (String p: path)
+		{
+			if (p == null)
+				continue;
+			
+//			System.out.println( "trying to load template "+(p+fn) );
+			try
+			{
+				if (Velocity.resourceExists( p+fn ))
+					return Velocity.getTemplate( p+fn );
+			}
+			catch ( ResourceNotFoundException e )
+			{
+				rnfe = e;
+			}
+			catch ( Exception e )
+			{
+				System.out.println( "ignoring "+e);
+			}
+		}
+		
+		if (rnfe != null)
+			throw rnfe;
+		
+		throw new ResourceNotFoundException("could not find resource: "+fn);
+	}
+
+	@Override
+	public void generate( Module module, CmdLineOptions options )
+		throws Exception
+	{
+		lh = options.lh;
+
+		boolean ignoreGlobal = options.ignoreGlobalWordsList;
+		boolean ignoreLocal = options.ignoreLocalWordsList;
+		String userWords = options.userWordsList != null ? options.userWordsList.getPath() : null;
+		Set<String> what = options.what;
+
+		// Load the reserved words lists if any have been provided.
+		Map<String, String> words = new HashMap<String, String>();
+		if (!ignoreGlobal)
+			mapWords( global_kwd, words );
+		if (!ignoreLocal)
+			mapWords( local_kwd, words );
+		if (userWords != null)
+			mapWords( userWords, words );
+
+		// check for collisions with the reserved word list.
+		ReservedWordChecker checker = new ReservedWordChecker( words, false, lh );
+		module.treewalk( checker );
+		if (!checker.ok())
+		{
+			lh.report( LogHandler.LEVEL_ERROR, null, "Encountered errors during java generation." );
+			return;
+		}
+
+		// ok, we're ready to generate code. make sure the
+		// output directories exist.
+
+		Output dir = options.output;
+		Output templateDir = options.templateOutput;
+		
+		String m = module.name().name;
+		if (m.length() > 0)
+		{
+			dir = dir.newPackage( m );
+			templateDir = templateDir.newPackage( m );
+		}
+		
+		// generate code for each service.
+
+		for (Service intf : module)
+		{
+			generate( intf, what, dir, templateDir );
+		}
+	}
+
+	private void generate( final Service intf, Set<String> what, Output dir,
+		Output templateDir ) throws Exception
+	{
+		what = populateWhat( what );
+
+		if (what.isEmpty())
+		{
+			// lh.logMessage( lh.LEVEL_ERROR, null, "User has selected NONE\n" );
+			return;
+		}
+
+		final MessageDirection msgDir = getMessageDirection( what );
+
+		if (what.contains( WHAT_INTF ))
+		{
+			// Generate the value factory file.
+			
+			generateVf( intf, dir );
+	
+			// Generate the interface, remote, and stub files.
+	
+			generateIntfRemoteStub( intf, dir, msgDir, MessageDirection.BOTH, false );
+	
+			generateIntfRemoteStub( intf, dir, msgDir, MessageDirection.SERVER, true );
+	
+			generateIntfRemoteStub( intf, dir, msgDir, MessageDirection.CLIENT, true );
+	
+			// Generate helper file.
+	
+			generateHelper( intf, dir, msgDir );
+			
+			// Generate base file.
+			
+			generateBase( intf, dir, msgDir );
+	
+			// Generate readme file.
+			
+			generateReadme( intf, dir, msgDir );
+		}
+
+		// Generate main template file.
+
+		if (what.contains( WHAT_MAIN ))
+			generateMain( intf, templateDir, msgDir );
+
+		// Generate impl template file.
+
+		if (what.contains( WHAT_IMPL ))
+			generateImpl( intf, templateDir, msgDir );
+	}
+
+	private void generateReadme( final Service intf, Output dir,
+		final MessageDirection msgDir ) throws Exception
+	{
+		doFile( dir, "readme-etch-csharp-files.txt", lh, new Gen()
+		{
+			public void run( PrintWriter pw ) throws Exception
+			{
+				generateReadme( pw, intf, msgDir );
+			}
+		} );
+	}
+
+	private void generateVf( final Service intf, Output dir )
+		throws Exception
+	{
+		doFile( dir, getVfName( intf ) + fnSuffix, lh, new Gen()
+		{
+			public void run( PrintWriter pw ) throws Exception
+			{
+				generateVf( pw, intf );
+			}
+		} );
+	}
+
+	private void generateHelper( final Service intf, Output dir,
+		final MessageDirection msgDir ) throws Exception
+	{
+		doFile( dir, getHelperName( intf ) + fnSuffix, lh, new Gen()
+		{
+			public void run( PrintWriter pw ) throws Exception
+			{
+				generateHelper( pw, intf, msgDir );
+			}
+		} );
+	}
+
+	private void generateMain( final Service intf, Output dir,
+		MessageDirection msgDir ) throws Exception
+	{
+		if (msgDir == MessageDirection.BOTH
+				|| msgDir == MessageDirection.CLIENT)
+			doFile( dir, getMainName( intf, MessageDirection.CLIENT ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateMain( pw, intf, MessageDirection.CLIENT, false );
+				}
+			} );
+
+		if (msgDir == MessageDirection.BOTH
+				|| msgDir == MessageDirection.SERVER)
+			doFile( dir, getMainName( intf, MessageDirection.SERVER ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateMain( pw, intf, MessageDirection.SERVER, false );
+				}
+			} );
+	}
+
+	private void generateBase( final Service intf, Output dir,
+		MessageDirection msgDir ) throws Exception
+	{
+		if (msgDir == MessageDirection.BOTH || msgDir == MessageDirection.CLIENT)
+			doFile( dir, getBaseName( intf, MessageDirection.CLIENT ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateBase (pw, intf, MessageDirection.CLIENT, false );
+				}
+			} );
+
+		if (msgDir == MessageDirection.BOTH || msgDir == MessageDirection.SERVER)
+			doFile( dir, getBaseName( intf, MessageDirection.SERVER ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateBase (pw, intf, MessageDirection.SERVER, false );
+				}
+			} );
+	}
+
+	private void generateImpl( final Service intf, Output dir,
+		MessageDirection msgDir ) throws Exception
+	{
+		if (msgDir == MessageDirection.BOTH
+				|| msgDir == MessageDirection.CLIENT)
+			doFile( dir, getImplName( intf, MessageDirection.CLIENT ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateImpl( pw, intf, MessageDirection.CLIENT, false );
+				}
+			} );
+
+		if (msgDir == MessageDirection.BOTH
+				|| msgDir == MessageDirection.SERVER)
+			doFile( dir, getImplName( intf, MessageDirection.SERVER ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateImpl( pw, intf, MessageDirection.SERVER, false );
+				}
+			} );
+	}
+
+	private void generateIntfRemoteStub( final Service intf, Output dir,
+		final MessageDirection what, final MessageDirection mc,
+		final boolean hasBaseClass ) throws Exception
+	{
+		// Generate interface file
+
+		doFile( dir, getIntfName( intf, mc ) + fnSuffix, lh, new Gen()
+		{
+			public void run( PrintWriter pw ) throws Exception
+			{
+				generateIntf( pw, intf, mc, hasBaseClass );
+			}
+		} );
+
+		// Generate remote file
+
+		if (mc == MessageDirection.BOTH || what == MessageDirection.BOTH
+				|| mc != what)
+			doFile( dir, getRemoteName( intf, mc ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateRemote( pw, intf, mc, hasBaseClass );
+				}
+			} );
+
+		// Generate stub file
+
+		if (mc == MessageDirection.BOTH || what == MessageDirection.BOTH
+				|| mc == what)
+			doFile( dir, getStubName( intf, mc ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateStub( pw, intf, mc, hasBaseClass );
+				}
+			} );
+	}
+
+	/**
+	 * Generate the value factory for the service.
+	 *
+	 * @param pw
+	 * @param intf
+	 * @throws Exception
+	 */
+	void generateVf( PrintWriter pw, Service intf ) throws Exception
+	{
+		// params keeps track of the total set of parameters
+		// named (for enums, structs, exceptions, and messages).
+		Set<String> params = new HashSet<String>();
+
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "params", params );
+		vf_vm.merge( context, pw );
+	}
+
+	/**
+	 * Generate the interface for the service.
+	 *
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @param hasBaseClass
+	 * @throws Exception
+	 */
+	void generateIntf( PrintWriter pw, Service intf, MessageDirection mc,
+		boolean hasBaseClass ) throws Exception
+	{
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "mc", mc );
+		context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
+		context.put( "hasBaseClass", hasBaseClass );
+		intf_vm.merge( context, pw );
+	}
+
+	/**
+	 * Generate the call to message implementation of the interface. This class
+	 * turns calls on its methods into messages which are sent to the remote
+	 * stub. For two-way calls, it then waits for a response message, returning
+	 * the result therein to the caller.
+	 *
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @param hasBaseClass
+	 * @throws Exception
+	 */
+	void generateRemote( PrintWriter pw, Service intf, MessageDirection mc,
+		boolean hasBaseClass ) throws Exception
+	{
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "mc", mc );
+		context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
+		context.put( "hasBaseClass", hasBaseClass );
+		context.put( "methodList", new ArrayList<String>());
+		remote_vm.merge( context, pw );
+	}
+
+	/**
+	 * Generate the message to call implementation. This class accepts a message
+	 * and turns it back into a call on the user's implementation. For two-way
+	 * messages, the return value from the user's implementation method is turned
+	 * into the appropriate response message and sent.
+	 *
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @param hasBaseClass
+	 * @throws Exception
+	 */
+	void generateStub( PrintWriter pw, Service intf, MessageDirection mc,
+		boolean hasBaseClass ) throws Exception
+	{
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "mc", mc );
+		context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
+		context.put( "hasBaseClass", hasBaseClass );
+		stub_vm.merge( context, pw );
+	}
+
+	/**
+	 * Generate the transport plumbing helper.
+	 *
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @throws Exception
+	 */
+	void generateHelper( PrintWriter pw, Service intf, MessageDirection mc )
+		throws Exception
+	{
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "mc", mc );
+
+		helper_vm.merge( context, pw );
+	}
+
+	/**
+	 * Generate the readme.txt.
+	 *
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @throws Exception
+	 */
+	void generateReadme( PrintWriter pw, Service intf, MessageDirection mc ) throws Exception
+	{
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "mc", mc );
+
+		readme_vm.merge( context, pw );
+	}
+
+	/**
+	 * Generate the template main program.
+	 *
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @param hasBaseClass
+	 * @throws Exception
+	 */
+	void generateMain( PrintWriter pw, Service intf, MessageDirection mc,
+		boolean hasBaseClass ) throws Exception
+	{
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "mc", mc );
+		context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
+		context.put( "hasBaseClass", hasBaseClass );
+		main_vm.merge( context, pw );
+	}
+
+	/**
+	 * Generates the base implementation of the interfaces, with each
+	 * method throwing an exception to the tune that it isn't implemented.
+	 * User's impl will extend this base implementation.
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @param hasBaseClass
+	 * @throws Exception
+	 */
+	void generateBase( PrintWriter pw, Service intf, MessageDirection mc,
+		boolean hasBaseClass ) throws Exception
+		{
+			VelocityContext context = new VelocityContext();
+			context.put( "now", new Date() );
+			context.put( "version", VERSION );
+			context.put( "helper", this );
+			context.put( "intf", intf );
+			context.put( "mc", mc );
+			context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
+			context.put( "hasBaseClass", hasBaseClass );
+			context.put( "methodList", new ArrayList<String>());
+			base_vm.merge( context, pw );
+		}
+
+	/**
+	 * Generate the template user implemention class which extends the base
+	 * implementation generated above. This class will only have the appropriate
+	 * constructor and reference to the appropriate remote, and a comment inviting
+	 * the user to override methods.
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @param hasBaseClass
+	 * @throws Exception
+	 */
+	void generateImpl( PrintWriter pw, Service intf, MessageDirection mc,
+		boolean hasBaseClass ) throws Exception
+	{
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "mc", mc );
+		context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
+		context.put( "hasBaseClass", hasBaseClass );
+		impl_vm.merge( context, pw );
+	}
+
+	private String getVfName( Service intf )
+	{
+		return "ValueFactory" + getIntfName( intf, MessageDirection.BOTH );
+	}
+
+	private String getIntfName( Service intf, MessageDirection mc )
+	{
+		String suffix = MsgDirHelper.getSuffix( mc );
+		return intf.name() + suffix;
+	}
+
+	private String getMainName( Service intf, MessageDirection mc )
+	{
+		if (mc == MessageDirection.SERVER)
+			return "Main" + intf.name() + "Listener";
+		return "Main" + getIntfName( intf, mc );
+	}
+
+	private String getImplName( Service intf, MessageDirection mc )
+	{
+		return "Impl" + getIntfName( intf, mc );
+	}
+
+	private String getRemoteName( Service intf, MessageDirection mc )
+	{
+		return "Remote" + getIntfName( intf, mc );
+	}
+
+	private String getStubName( Service intf, MessageDirection mc )
+	{
+		return "Stub" + getIntfName( intf, mc );
+	}
+
+	private String getHelperName( Service intf )
+	{
+		return intf.name() + "Helper";
+	}
+	
+	private String getBaseName( Service intf, MessageDirection mc )
+	{
+		return "Base" + getIntfName( intf, mc );
+	}
+
+	@Override
+	public String asyncReceiverPoolName( Message msg )
+	{
+		return msg.getAsyncReceiver().toString().toLowerCase();
+	}
+
+	@Override
+	public String getTypeValue( TypeRef type, Token value )
+	{
+		// System.out.println( "getTypeValue called with: "+type+": "+value );
+		Token t = type.type();
+		switch (t.kind)
+		{
+			case EtchGrammarConstants.LONG:
+				return value.image + "L";
+			case EtchGrammarConstants.FLOAT:
+				return value.image + "F";
+			case EtchGrammarConstants.DOUBLE:
+				return value.image + "D";
+			case EtchGrammarConstants.STRING:
+				return protectString( value.image );
+			default:
+				return value.image;
+		}
+	}
+
+	private String protectString( String s )
+	{
+		// System.out.println( "protectString called with: "+s );
+
+		StringBuffer sb = new StringBuffer();
+		sb.append( "\"" );
+		for (char c : s.toCharArray())
+		{
+			if (c == '\t')
+			{
+				sb.append( "\\t" );
+				continue;
+			}
+			if (c == '\r')
+			{
+				sb.append( "\\r" );
+				continue;
+			}
+			if (c == '\n')
+			{
+				sb.append( "\\n" );
+				continue;
+			}
+			if (c == '\"')
+			{
+				sb.append( "\\\"" );
+				continue;
+			}
+			if (c == '\\')
+			{
+				sb.append( "\\\\" );
+				continue;
+			}
+			if (c >= 32 && c < 127)
+			{
+				sb.append( c );
+				continue;
+			}
+			sb.append( String.format( "\\u%04x", (int) c ) );
+		}
+		sb.append( "\"" );
+		return sb.toString();
+	}
+
+	/**
+	 * @param type
+	 * @return type name appropriate for use as a structure element or exception
+	 * parameter or function parameter or result.
+	 */
+	@Override
+	public String getTypeName( TypeRef type )
+	{
+		if (type.dim() > 0)
+			return getNativeTypeName( type ) + dim2spec( type.dim() );
+		return getRefTypeName( type );
+	}
+
+	/**
+	 * @param type the etch type
+	 * @return the fundamental native type for java. so etch int -> csharp int,
+	 * while etch string -> csharp string.
+	 */
+	@Override
+	public String getNativeTypeName( TypeRef type )
+	{
+		Token t = type.type();
+		switch (t.kind)
+		{
+			case EtchGrammarConstants.VOID:
+				return "void";
+			case EtchGrammarConstants.BOOLEAN:
+				return "bool";
+			case EtchGrammarConstants.BYTE:
+				return "sbyte";
+			case EtchGrammarConstants.SHORT:
+				return "short";
+			case EtchGrammarConstants.INT:
+				return "int";
+			case EtchGrammarConstants.LONG:
+				return "long";
+			case EtchGrammarConstants.FLOAT:
+				return "float";
+			case EtchGrammarConstants.DOUBLE:
+				return "double";
+			case EtchGrammarConstants.STRING:
+				return "string";
+			case EtchGrammarConstants.OBJECT:
+				return "Object";
+			default:
+			{
+				// we have to use a fully qualified name here.
+				// find the actual type...
+				Named<?> n = type.intf().get( t.image );
+				if (n == null)
+					throw new IllegalArgumentException( String.format(
+						"undefined or ambiguous name at line %d: %s",
+						t.beginLine, t.image ) );
+				return n.efqname( this );
+			}
+		}
+	}
+
+	/**
+	 * @param type the etch type
+	 * @return the fundamental native reference type for java. so etch int ->
+	 * csharp int?, while etch string -> csharp string.
+	 */
+	private String getRefTypeName( TypeRef type )
+	{
+		Token t = type.type();
+		switch (t.kind)
+		{
+			case EtchGrammarConstants.VOID:
+				return "void";
+			case EtchGrammarConstants.BOOLEAN:
+				return "bool?";
+			case EtchGrammarConstants.BYTE:
+				return "sbyte?";
+			case EtchGrammarConstants.SHORT:
+				return "short?";
+			case EtchGrammarConstants.INT:
+				return "int?";
+			case EtchGrammarConstants.LONG:
+				return "long?";
+			case EtchGrammarConstants.FLOAT:
+				return "float?";
+			case EtchGrammarConstants.DOUBLE:
+				return "double?";
+			case EtchGrammarConstants.STRING:
+				return "string";
+			case EtchGrammarConstants.OBJECT:
+				return "Object";
+			default:
+			{
+				// we have to use a fully qualified name here.
+				// find the actual type...
+				Named<?> n = type.intf().get( t.image );
+				if (n == null)
+					throw new IllegalArgumentException( String.format(
+						"undefined or ambiguous name at line %d: %s",
+						t.beginLine, t.image ) );
+				if (n.isEnumx())
+					return n.efqname( this ) + "?";
+				return n.efqname( this );
+			}
+		}
+	}
+
+	private String dim2spec( int i )
+	{
+		String s = "";
+		while (i-- > 0)
+			s += "[]";
+		return s;
+	}
+
+	@Override
+	public String formatString( ParamList<Service> n, boolean isExcept )
+		throws ParseException, IOException
+	{
+		ToString ts = (ToString) n.getOpt( "ToString" );
+		List<FmtItem> list;
+		if (ts != null)
+		{
+			list = ts.getFormat();
+			n.checkFormatList( ts.lineno(), list );
+		}
+		else if (isExcept)
+		{
+			list = n.mkFormatList( true, ((Except)n).hasExtends() );
+			// Temp Fix :remove once Scott fixes the ParamList code
+			modifyFormatList(list,true);
+		}
+		else
+		{
+			list = n.mkFormatList( false, ((Struct)n).hasExtends() );
+//			 Temp Fix :remove once Scott fixes the ParamList code
+			modifyFormatList(list,false);
+		}
+
+
+		if (list.size() == 1)
+		{
+			return list.get( 0 ).value();
+		}
+
+		StringBuffer sb = new StringBuffer();
+		sb.append( "String.Format( " );
+		sb.append( "\"" );
+		int j = 0;
+		for (FmtItem i : list)
+		{
+			if (i instanceof FieldItem)
+			{
+				sb.append( "{" + j + "}" );
+				j++;
+			}
+			else
+			{
+				escape( sb, ((StringItem) i).value() );
+			}
+		}
+		j = 0;
+
+		sb.append( "\"" );
+		for (FmtItem i : list)
+		{
+			if (i instanceof FieldItem)
+			{
+				sb.append( ", " );
+				sb.append( ((FieldItem) i).value() );
+			}
+		}
+		sb.append( " )" );
+		return sb.toString();
+	}
+
+	private void escape( StringBuffer sb, String s ) throws IOException
+	{
+		StringReader rdr = new StringReader( s );
+		int c;
+		while ((c = rdr.read()) >= 0)
+		{
+			if (c == '"')
+				sb.append( "\\\"" );
+			else if (c == '\\')
+				sb.append( "\\\\" );
+			else if (c == '\t')
+				sb.append( "\\t" );
+			else if (c == '\r')
+				sb.append( "\\r" );
+			else if (c == '\n')
+				sb.append( "\\n" );
+			else
+				sb.append( (char) c );
+		}
+	}
+
+	@Override
+	public String mfvname( String vname )
+	{
+		return "_mf_" + vname;
+	}
+
+	@Override
+	public String mtvname( String vname )
+	{
+		return "_mt_" + vname;
+	}
+
+	@Override
+	public String getLang()
+	{
+		return "csharp";
+	}
+
+	@Override
+	public String enum_efqname( String fqname, String moduleName,
+		String serviceName, String enumName )
+	{
+
+//		return moduleName + "." + "Consts" + serviceName + "." + enumName;
+		return moduleName + "." + "types" + "." + serviceName + "." + enumName;
+
+	}
+
+	@Override
+	public String except_efqname( String fqname, String moduleName,
+		String serviceName, String exceptName )
+	{
+
+//		return moduleName + "." + "Consts" + serviceName + "." + exceptName;
+		return moduleName + "." + "types" + "." + serviceName + "." + exceptName;
+	}
+
+	@Override
+	public String struct_efqname( String fqname, String moduleName,
+		String serviceName, String structName )
+	{
+
+//		return moduleName + "." + "Consts" + serviceName + "." + structName;
+		return moduleName + "." + "types" + "." + serviceName + "." + structName;
+	}
+
+	@Override
+	public String qualifyParameterName( Token name )
+	{
+		return name.image;
+	}
+
+	@Override
+	public String qualifyConstantName( Service intf, Token name )
+	{
+		String moduleName = intf.parent().name().name;
+		String serviceName = intf.name().name;
+		return moduleName + "." + "types" + "." + serviceName + "." + "Consts" + serviceName + "." + name.image;
+	}
+
+	@Override
+	public String qualifyEnumName( Service intf, Token name )
+	{
+		String moduleName = intf.parent().name().name;
+		String serviceName = intf.name().name;
+		return moduleName + "." + "types" + "." + serviceName + "." +  name.image;
+	}
+
+	@Override
+	public String getValidator( Named<?> named )
+	{
+		if (named instanceof Parameter)
+		{
+			Parameter param = (Parameter) named;
+			TypeRef type = param.type();
+
+			if (type.isBuiltin())
+				return "Validator_" + type.type() + ".Get( " + type.dim()
+					+ " )";
+
+			Named<?> n = type.getNamed( type.intf() );
+
+			if (n.isBuiltin())
+			{
+				Builtin b = (Builtin) n;
+				String cn = b.className();
+				if (cn.endsWith( "?" ))
+					cn = cn.substring( 0, cn.length()-1 );
+				
+				return String.format( "Validator_custom.Get( typeof(%s), %d, %s )",
+					cn, type.dim(), b.allowSubclass() );
+			}
+
+			// Allow subclassing for etch defined structs and externs.
+
+			if (n.isStruct() || n.isExcept())
+				return String.format( "Validator_custom.Get( typeof(%s), %d, true )",
+					n.efqname( this ), type.dim() );
+
+			// Don't allow subclassing for externs or etch defined enums.
+
+			if (!(n.isExtern() || n.isEnumx()))
+				Assertion.check( n.isExtern() || n.isEnumx(),
+					"n.isExtern() || n.isEnumx(): "+n );
+
+			return "Validator_custom.Get( typeof ( "
+				+ n.efqname( this )  + " ), " + type.dim()
+				+ ", false )";
+		}
+
+		if (named instanceof Thrown)
+		{
+			Thrown thrown = (Thrown) named;
+			Except e = (Except) thrown.getNamed();
+			return "Validator_custom.Get( typeof ( " + e.efqname( this )
+				+ " ) , 0,true )";
+		}
+
+		if (named instanceof Item)
+			return "Validator_boolean.Get( 0 )";
+
+		return "null";
+	}
+
+	/**
+	 * @param name
+	 * @return the appropriate name for a getter method.
+	 */
+	public String getGetterName( Name name )
+	{
+		String s = name.name;
+		return "Get" + s.substring( 0, 1 ).toUpperCase()+s.substring( 1 );
+	}
+
+	/**
+	 * @param name
+	 * @return the appropriate name for a setter method.
+	 */
+	public String getSetterName( Name name )
+	{
+		String s = name.name;
+		return "Set" + s.substring( 0, 1 ).toUpperCase()+s.substring( 1 );
+	}
+
+	private void modifyFormatList(List<FmtItem> list,boolean isException) {
+		for(int i=0;i<list.size();i++) {
+			FmtItem item = list.get( i );
+
+			if (item.value().contains( "super.getMessage()" )) {
+				list.remove( i );
+				list.add(i, new FieldItem(  "base.GetMessage()" ) );
+			}
+			if (item.value().contains( "super.toString()" )) {
+				list.remove( i );
+				list.add(i, new FieldItem(  "base.ToString()" ) );
+			}
+		}
+	}
+
+	@Override
+	public void addDefaults( Service service ) throws ParseException
+	{
+		addBuiltin( service, newName( "List" ), "System.Collections.IList", true );
+		addBuiltin( service, newName( "Map" ), "System.Collections.IDictionary", true );
+		addBuiltin( service, newName( "Set" ), "System.Collections.Hashtable", true );
+		addBuiltin( service, newName( "Datetime" ), "System.DateTime?", false );
+	}
+}
diff --git a/binding-csharp/compiler/src/main/java/org/apache/etch/bindings/csharp/compiler/CompilerVersion.java b/binding-csharp/compiler/src/main/java/org/apache/etch/bindings/csharp/compiler/CompilerVersion.java
new file mode 100644
index 0000000..302b787
--- /dev/null
+++ b/binding-csharp/compiler/src/main/java/org/apache/etch/bindings/csharp/compiler/CompilerVersion.java
@@ -0,0 +1,33 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.csharp.compiler;
+
+/**
+ * The version info of this Etch backend (compiler).
+ */
+public interface CompilerVersion
+{
+	// This file is edited by the production build system to replace the value
+	// of VERSION below with whatever it wants the version string to actually be.
+	
+	/** The version of this Etch backend (compiler) */
+	public String VERSION = "csharp 1.1.0-incubating (LOCAL-0)";
+}
diff --git a/binding-csharp/compiler/src/main/java/org/apache/etch/bindings/csharp/compiler/CompilerVersion.java.tmpl b/binding-csharp/compiler/src/main/java/org/apache/etch/bindings/csharp/compiler/CompilerVersion.java.tmpl
new file mode 100644
index 0000000..95c17c5
--- /dev/null
+++ b/binding-csharp/compiler/src/main/java/org/apache/etch/bindings/csharp/compiler/CompilerVersion.java.tmpl
@@ -0,0 +1,30 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.csharp.compiler;
+
+/**
+ * The version info of this Etch backend (compiler).
+ */
+public interface CompilerVersion
+{
+	// This file is edited by the production build system to replace the value
+	// of VERSION below with whatever it wants the version string to actually be.
+	
+	/** The version of this Etch backend (compiler) */
+	public String VERSION = "csharp @EtchLongVersion@ (@EtchBuildTag@)";
+}
diff --git a/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/base.vm b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/base.vm
new file mode 100644
index 0000000..eb8e22e
--- /dev/null
+++ b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/base.vm
@@ -0,0 +1,276 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created and should not be edited!
+// Re-implement these methods by overriding them in Impl$intf.name()$suffix
+// or by making appropriate assignments to the delegates.
+#set($i = $intf.name())
+#set($vfname = "ValueFactory$i")
+#set($intfname = "$i$suffix")
+#set($clname = "Base$intfname")
+#if ($helper.isServer($mc))
+#set($peer = "client")
+#set($peerclass = "Remote${i}Client")
+#else
+#set($peer = "server")
+#set($peerclass = "Remote${i}Server")
+#end
+
+using System;
+
+#foreach( $n in $intf.iterator() )
+#if ($n.isExtern())
+#if ($n.hasImport( $helper ))
+using $n.getImport( $helper );
+#end
+#end
+#end
+using Org.Apache.Etch.Bindings.Csharp.Support;
+
+/// <summary>
+/// Base Implementation of $intfname, with default method implementations
+/// which throw NotSupportedException. Either implement the delegates or extend
+/// this class to provide implementations of messages from the $peer 
+/// </summary>
+
+namespace $intf.parent().name()
+{
+
+	///<summary>Call to message translator for $intfname.</summary>
+	public class $clname : $intfname, ObjSession
+	{	
+#set( $delegateTypeHeader = "_delegate_type_" )
+#set( $delegateVarHeader = "_delegate_" )
+#set( $sep = "" )
+#foreach ($mthd in $intf.iterator())
+#if ($mthd.isMsgDir($mc) || $mthd.isMsgDirBoth())
+#if (!$mthd.isHidden())
+#if(!$methodList.contains("$delegateVarHeader$mthd.name().name()"))
+#set ( $addMethodListStatus = $methodList.add("$delegateVarHeader$mthd.name().name()") )
+		/// <summary>
+    	/// Delegate Definition; Please do not modify
+    	/// </summary>
+		public delegate $helper.getTypeName( $mthd.type() ) $delegateTypeHeader$mthd.name()	(
+#set( $sep = "" )
+#foreach( $param in $mthd.iterator() )
+									$sep$helper.getTypeName( $param.type() ) $param.name()
+#set( $sep = ", " )
+#end
+									);
+		/// <summary>
+    	/// Add your implementation method to this variable
+    	/// </summary>							
+		public $delegateTypeHeader$mthd.name()  $delegateVarHeader$mthd.name();
+
+#end
+#end
+#end	
+#end
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+
+#foreach( $n in $z.messages( true ) )
+#if($n.isMsgDir($mc) || $n.isMsgDirBoth() )
+#if(!$n.isHidden())
+#if(!$methodList.contains("$delegateVarHeader$n.name().name()"))
+#set ( $addMethodListStatus = $methodList.add("$delegateVarHeader$n.name().name()") )
+#if($n.isOneway())
+		/// <summary>
+    	/// Delegate Definition; Please do not modify
+    	/// </summary>
+		public delegate $helper.getTypeName( $n.type() ) $delegateTypeHeader$n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+			$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+			);
+		
+		/// <summary>
+    	/// Add your implementation method to this variable
+    	/// </summary>							
+		public $delegateTypeHeader$n.name()  $delegateVarHeader$n.name();
+	
+#else
+		/// <summary>
+    	/// Delegate Definition; Please do not modify
+    	/// </summary>
+		public delegate $helper.getTypeName( $n.type() ) $delegateTypeHeader$n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+			$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+		);
+	
+		/// <summary>
+    	/// Add your implementation method to this variable
+    	/// </summary>							
+		public $delegateTypeHeader$n.name()  $delegateVarHeader$n.name();
+	
+#end
+#end
+#end
+#end
+#end
+#end
+#end
+
+	
+		///<summary>Constructs the $clname.</summary>
+		public $clname() 
+		{
+		}
+
+		public virtual object _SessionQuery(Object query)
+		{
+			throw new NotSupportedException( "unknown query: " + query);
+		}
+
+		public virtual void _SessionControl(Object control, Object value)
+		{
+			throw new NotSupportedException( "unknown control: " + control);
+		}
+
+		public virtual void _SessionNotify( Object eventObj)
+		{
+			if (eventObj is Exception)
+				Console.WriteLine((Exception) eventObj);
+		}  
+
+
+#foreach ($mthd in $intf.iterator())
+#if ($mthd.isMsgDir($mc) || $mthd.isMsgDirBoth())
+#if (!$mthd.isHidden())
+#if(!$methodList.contains($mthd.name().name()))
+#set ( $addMethodListStatus = $methodList.add($mthd.name().name()) )
+		public virtual $helper.getTypeName( $mthd.type() ) $mthd.name() (
+#set( $sep = "" )
+#foreach( $param in $mthd.iterator() )
+				$sep$helper.getTypeName( $param.type() ) $param.name()
+#set( $sep = ", " )
+#end
+		)
+		{
+		if ($delegateVarHeader$mthd.name() != null)
+		#if($helper.getTypeName( $mthd.type() ).equals("void"))
+				$delegateVarHeader$mthd.name()( 
+		#set( $sep = "" )
+			#foreach( $param in $mthd.iterator() )
+			$sep$param.name()
+		#set( $sep = "," )
+			#end
+			);
+		#else
+				return $delegateVarHeader$mthd.name()( 
+		#set( $sep = "" )
+			#foreach( $param in $mthd.iterator() )
+			$sep$param.name()
+		#set( $sep = "," )
+			#end
+			);
+		#end
+			else 
+				throw new NotSupportedException( "$mthd.name()" );
+		}
+#end
+#end
+#end
+#end
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+
+#foreach( $n in $z.messages( true ) )
+#if($n.isMsgDir($mc) || $n.isMsgDirBoth() )
+#if(!$n.isHidden())
+#if(!$methodList.contains($n.name().name()))
+#set ( $addMethodListStatus = $methodList.add($n.name().name()) )
+#if($n.isOneway())
+		public virtual $helper.getTypeName( $n.type() ) $n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+			$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+		)
+		{
+				if ($delegateVarHeader$n.name() != null)
+			#if($helper.getTypeName( $n.type() ).equals("void"))
+				$delegateVarHeader$n.name()( 
+		#set( $sep = "" )
+			#foreach( $p in $n.iterator() )
+			$sep$p.name()
+		#set( $sep = "," )
+			#end
+			);
+			#else
+				return $delegateVarHeader$n.name()( 
+		#set( $sep = "" )
+			#foreach( $p in $n.iterator() )
+			$sep$p.name()
+		#set( $sep = "," )
+			#end
+			);
+		#end
+			else 
+				throw new NotSupportedException( "$n.name()" );
+		
+	}
+#else
+		public virtual $helper.getTypeName( $n.type() ) $n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+			$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+		)
+		{
+			if ($delegateVarHeader$n.name() != null)
+		#if($helper.getTypeName( $n.type() ).equals("void"))
+		 	$delegateVarHeader$n.name()( 
+		#set( $sep = "" )
+			#foreach( $p in $n.iterator() )
+			$sep$p.name()
+		#set( $sep = "," )
+			#end
+			);
+		#else
+				return $delegateVarHeader$n.name()( 
+		#set( $sep = "" )
+			#foreach( $p in $n.iterator() )
+			$sep$p.name()
+		#set( $sep = "," )
+			#end
+			);
+		#end
+			else 
+				throw new NotSupportedException( "$n.name()" );
+		}
+#end
+#end
+#end
+#end
+#end
+#end
+#end
+	}
+}
\ No newline at end of file
diff --git a/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/csharpKeywords.kwd b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/csharpKeywords.kwd
new file mode 100644
index 0000000..1dd5eeb
--- /dev/null
+++ b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/csharpKeywords.kwd
@@ -0,0 +1,15 @@
+# $Id$
+# 
+# Copyright 2007-2008 Cisco Systems Inc.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy
+# of the License at
+#  
+#     http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
diff --git a/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/helper.vm b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/helper.vm
new file mode 100644
index 0000000..31f0b3d
--- /dev/null
+++ b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/helper.vm
@@ -0,0 +1,164 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created and should not be edited!
+#set($i = $intf.name())
+
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Transport;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+/// <summary>
+/// Transport helper for ${i}.
+/// </summary>
+namespace $intf.parent().name()
+{
+    public class ${i}Helper : TransportHelper
+    {
+#if ( $helper.isServer($mc) || $helper.isBoth($mc) )
+
+		/// <summary>Constructs a new server session listener per specifications
+		/// in uri and resources.</summary>
+		/// <param name="uri"> contains specifications for the server session
+		/// listener and for the server session transport stack.</param>
+		/// <param name="resources"> additional resources to aid in constructing
+		/// new server sessions.</param>
+		/// <param name="implFactory"> called upon accepting a new server session to
+		/// construct a new server implementation to handle messages
+		/// from the client during the session.</param>
+		/// <returns> an out-of-band source that may be used to control
+		/// the listener.</returns>
+
+		public static ServerFactory NewListener( string uri,		
+			Resources resources, ${i}ServerFactory implFactory )
+		{
+			Resources res = InitResources(resources);
+			Transport<ServerFactory> listener = TransportFactory.GetListener(uri, res);
+			return new MyServerFactory(listener, implFactory);
+		}
+		
+		public class MyServerFactory : DefaultServerFactory
+		{
+			public MyServerFactory(Transport<ServerFactory> listener, ${i}ServerFactory implFactory )
+				: base(listener, implFactory)
+			{
+				_listener = listener;
+				_implFactory = implFactory;
+			}
+
+		    private readonly Transport<ServerFactory> _listener;
+
+            private readonly ${i}ServerFactory _implFactory;
+
+            public override void NewServer(TransportMessage m, string uri, Resources resources)
+			{
+                ValueFactory vf = (ValueFactory)resources.Get(TransportConsts.VALUE_FACTORY);
+                MailboxManager r = new PlainMailboxManager(m, uri, resources);
+                DeliveryService d = new DefaultDeliveryService(r, uri, resources);
+				Remote${i}Client client = new Remote${i}Client(d, vf);
+				${i}Server server = _implFactory.New${i}Server(client);
+                Pool qp = (Pool)resources[QUEUED_POOL];
+                Pool fp = (Pool)resources[FREE_POOL];
+				new Stub${i}Server(d, server, qp, fp);
+				client._Start();
+			}
+
+            public override ValueFactory NewValueFactory(string uri)
+            {
+                return new ValueFactory${i}(uri);
+            }
+
+            public override string ToString()
+            {
+                return "${i}Helper.ServerFactory/" + _listener;
+            }
+		}
+		
+		/// <summary>
+		/// Factory for a Listener to use to create new instances of ${i}Server.
+		/// </summary>
+		
+		public interface ${i}ServerFactory
+		{
+			/// <param name="client"> an Remote${i}Client instance for server implementation
+			/// to use to call back to the client.</param>
+			/// <returns> an instance of ${i}Server (e.g., Impl${i}Server) to
+			/// handle messages which arrive from the client.</returns>
+			
+			${i}Server New${i}Server( Remote${i}Client client );
+		}		
+#end
+#if ( $helper.isClient($mc) || $helper.isBoth($mc) )
+
+		/// <summary>Constructs a new client session per specifications in uri
+		/// and resources.</summary>
+		/// <param name="uri"> contains specifications for the client session
+		/// transport stack.</param>
+		/// <param name="resources"> additional resources to aid in constructing
+		/// new sessions.</param>
+		/// <param name="implFactory">factory used to construct a new instance implementing
+		/// ${i}Client. The new instance will receive and process messages from the
+		///	server session.</param>
+		/// <returns> new remote server instance initialized by uri
+		/// and resources which may be used to send messages to the
+		/// server session.</returns>
+		
+		public static Remote${i}Server NewServer( string uri,
+			Resources resources, ${i}ClientFactory implFactory )
+		{
+			resources = InitResources(resources);
+			
+			ValueFactory${i} vf= new ValueFactory${i}(uri);
+			resources.Add( TransportConsts.VALUE_FACTORY, vf );
+			
+			URL u = new URL(uri);
+
+            TransportMessage m = TransportFactory.GetTransport(uri, resources);
+            MailboxManager r = new PlainMailboxManager(m, u, resources);
+            DeliveryService d = new DefaultDeliveryService(r, u, resources);
+			Remote${i}Server server = new Remote${i}Server(d, vf);
+			${i}Client client = implFactory.New${i}Client(server);			
+			new Stub${i}Client(d,
+					client,
+					(Pool) resources[QUEUED_POOL],
+					(Pool) resources[FREE_POOL]);
+	
+			return server;
+		}
+		
+		///<summary>
+		///Factory used by
+		///{@link ${i}Helper#new${i}Server(String, Resources, ${i}ClientFactory)}
+		///to construct a new instance implementing {@link ${i}Client}. The new
+		///instance will receive and process messages from the server session.
+		///</summary>
+		
+		public interface ${i}ClientFactory
+		{
+			///<summary>
+			///Constructs a new instance implementing ${i}Client. The new
+			///instance will receive and process messages from the server session.</summary>
+		 	///<param name=server> an instance of Remote${i}Server which may be used to
+			/// send messages to the server session. </param>
+			///<returns> new instance implementing ${i}Client (typically
+			///Impl${i}Client). </returns>
+			
+			${i}Client New${i}Client( Remote${i}Server server );			
+		}
+#end
+	}
+}
diff --git a/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/impl.vm b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/impl.vm
new file mode 100644
index 0000000..14a4ca5
--- /dev/null
+++ b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/impl.vm
@@ -0,0 +1,75 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created for your convenience and will not be
+// overwritten once it exists! Please edit this file as necessary to implement
+// your service logic.
+#set($i = $intf.name())
+#set($vfname = "ValueFactory$i")
+#set($intfname = "$i$suffix")
+#set($clname = "Impl$intfname")
+#set($baseclname = "Base$i$suffix")
+#if ($helper.isServer($mc))
+#set($peer = "client")
+#set($peerclass = "Remote${i}Client")
+#else
+#set($peer = "server")
+#set($peerclass = "Remote${i}Server")
+#end
+
+using System;
+
+#foreach( $n in $intf.iterator() )
+#if ($n.isExtern())
+#if ($n.hasImport( $helper ))
+using $n.getImport( $helper );
+#end
+#end
+#end
+
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+using ${m.name()}.types.$z.name();
+#end
+#end
+
+using ${intf.parent().name()}.types.${i};
+
+///<summary>Your custom implementation of $baseclname. Add methods here to provide
+///implementation of messages from the $peer. </summary>
+namespace $intf.parent().name()
+{
+	///<summary>Implementation for $clname</summary>
+	public class $clname : $baseclname
+	{
+		/// <summary>Constructs the $clname.</summary>
+ 		/// <param name="$peer">a connection to the $peer session. Use this to
+ 		/// send a message to the $peer.</param>
+		public $clname($peerclass $peer)
+		{
+			this.$peer = $peer;
+		}
+		
+		/// <summary>A connection to the $peer session. Use this to
+ 		/// send a message to the $peer.</summary>
+		private readonly $peerclass $peer;
+	
+		// TODO: Implement delegates or provide implementation of $intfname
+		// messages from the $peer	
+	}
+}
\ No newline at end of file
diff --git a/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/intf.vm b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/intf.vm
new file mode 100644
index 0000000..8868d87
--- /dev/null
+++ b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/intf.vm
@@ -0,0 +1,296 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created and should not be edited!
+
+using System;
+#foreach( $n in $intf.iterator() )
+#if ($n.isExtern())
+#if ($n.hasImport( $helper ))
+	using $n.getImport( $helper );
+#end
+#end
+#end
+
+namespace $intf.parent().name()
+{
+#if( $intf.hasDescr() )
+	///<summary>
+#foreach( $s in $intf.descr() )
+	///$s
+#end
+	///</summary>
+#end
+#set($sep = ":")
+#if ($hasBaseClass)
+	public interface $intf.name()$suffix $sep $intf.name()
+#set ($sep = ",")
+#else
+	public interface $intf.name()$suffix
+#end
+#foreach( $n in $intf.iterator() )
+#if ($n.isMixin())
+	$sep $n.fqname()$suffix
+#set($sep = ",")
+#end
+#end
+	{
+#foreach( $n in $intf.iterator() )
+#if ($n.isMessage())
+#if ($n.isMsgDir($mc))
+#if (!$n.isHidden())
+#if ($n.hasDescr())
+		///<summary>
+#foreach($s in $n.descr())
+		///$s
+#end
+		///</summary>
+#end
+#foreach( $p in $n.iterator() )
+#set($first = true)
+#set ($count = 0)
+#foreach( $s in $p.descr() )
+#if ($first)
+#set($count = $count + 1)
+#set($first = false)
+		///<param name="$p.name()">$s
+#else
+		///$s
+#end
+#end
+#if ($count > 0)
+		///</param>
+#end		
+#end
+#if ($n.hasReturn())
+#set($first = true)
+#foreach( $s in $n.returnDescr() )
+#if ($first)
+#set($first = false)
+		///<returns>$s
+#else
+		///$s
+#end
+#end
+		///</returns>
+#end
+#if ($n.hasThrown())
+#if ($n.hasDescr())
+#foreach($t in $n.thrown().iterator())
+		///<Exception cref="$t.name().name()"> throws $t.name().name()</Exception>
+#end
+#end
+#end
+		$helper.getTypeName( $n.type() ) $n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+			$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+			);
+#end
+#end
+#elseif ($n.isConstant())
+#elseif ($n.isEnumx())
+#elseif ($n.isStruct() || $n.isExcept())
+#elseif ($n.isExtern())
+## ignore extern
+#elseif ($n.isMixin())
+## ignore mixin
+#else
+
+#end
+#end
+	}
+#if (!$hasBaseClass)
+	namespace types 
+	{
+		namespace $intf.name()$suffix
+		{
+			public static class Consts$intf.name()$suffix 
+			{
+#foreach( $n in $intf.iterator() )
+#if ($n.isConstant())
+#if ($n.hasDescr())
+				///<summary>
+#foreach( $s in $n.descr() )
+				///$s
+#end
+				///</summary>
+#end
+				public static $helper.getNativeTypeName( $n.type() ) $n.name() = $helper.getTypeValue( $n.type(), $n.value() );
+#end
+#end
+			}
+#foreach( $n in $intf.iterator() )
+#if ($n.isEnumx())
+#if (!$hasBaseClass)
+#if ($n.hasDescr())
+			///<summary>
+#foreach( $s in $n.descr() )
+			///$s
+#end
+			///</summary>
+#end
+			public enum $n.name()
+			{
+#set( $sep = "" )						
+#foreach( $i in $n.iterator() )
+#if ($i.hasDescr())
+				///<summary>
+#foreach( $s in $i.descr() )
+				///$s
+#end
+				///</summary>
+#end
+				$sep$i.name()
+#set( $sep = ", " )
+#end
+			}	
+#end
+#elseif ($n.isStruct() || $n.isExcept())
+#if (!$hasBaseClass)
+#if ($n.hasDescr())
+			///<summary>
+#foreach( $s in $n.descr() )
+			///$s
+#end
+			///</summary>
+#end
+#if( $n.hasExtends() )
+			public class $n.name()	: $n.getExtends().name()
+#else
+#if( $n.isExcept() )
+#if( $n.isUnchecked() )
+			public class $n.name() : Exception
+#else
+			public class $n.name() : Exception
+#end
+#else
+			[Serializable]
+			public class $n.name()
+#end
+#end
+			{
+			
+				/// <summary>Constructs the $n.name(). Don't init anything.</summary>
+				public $n.name()()
+				{
+					// don't init anything.
+				}
+
+#if ($n.hasAnyParameters())
+				///<summary>Constructs the $n.name().</summary>
+#foreach( $i in $n.getAllParameters() )
+#if ($i.hasDescr())
+				///<param name="$i.name()">
+#foreach( $s in $i.descr() )
+				///$s
+#end
+				///</param>
+#end
+#end
+				public $n.name()
+				(
+#set( $sep = "" )
+#foreach( $i in $n.getAllParameters() )
+					$sep$helper.getTypeName( $i.type() ) $i.name()
+#set( $sep = ", " )
+#end
+				)		
+#if( $n.hasExtends() )
+			 	: base(
+#set( $sep = "" )
+#foreach( $i in $n.getExtends().getAllParameters() )
+				$sep$i.name()
+#set( $sep = ", " )
+#end
+				)
+				{
+#else
+				{
+#end
+#foreach( $i in $n.getParameters() )
+					this.$i.name() = $i.name();
+#end
+				}
+#end
+
+#if( $n.isExcept() )
+#if ($n.hasExtends())
+				public new String GetMessage()
+#else
+				public String GetMessage()
+#end
+				{
+					return $helper.formatString( $n, true );
+				}
+#else
+				public override String ToString()
+				{
+					return $helper.formatString( $n, false );
+				}
+#end
+	
+#foreach( $i in $n.iterator() )
+#if ($i.hasDescr())
+				///<summary>
+#foreach( $s in $i.descr() )
+				///$s
+#end
+				///</summary>
+#end
+				public $helper.getTypeName( $i.type() ) $i.name();
+#if ($i.hasDescr())				
+				///<summary>Gets
+#foreach( $s in $i.descr() )
+		 		///$s
+#end
+				///</summary>
+#else
+				///<summary>Gets Value</summary>
+#end
+				/// <returns>return the value.</returns>
+		 		public $helper.getTypeName( $i.type() ) $helper.getGetterName( $i.name() )()
+				{					
+						return $i.name();
+				}
+#if ($i.hasDescr())					
+				///<summary>Sets
+#foreach( $s in $i.descr() )
+		 		///$s
+#end
+				///</summary>
+#else
+				///<summary>Sets Value</summary>
+#end
+				///<param name="value">the value</param>
+				public void $helper.getSetterName( $i.name() )( $helper.getTypeName( $i.type() ) value )
+				{
+					this.$i.name() = value;
+				}
+#end
+			}	
+#end
+#elseif ($n.isBuiltin())
+## nothing to do.
+#else	
+#end
+#end
+		}
+	}
+#end
+}
\ No newline at end of file
diff --git a/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/main.vm b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/main.vm
new file mode 100644
index 0000000..ae1bb66
--- /dev/null
+++ b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/main.vm
@@ -0,0 +1,104 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created for your convenience and will not be
+// overwritten once it exists! Please edit this file as necessary to implement
+// your service logic.
+#set($i = $intf.name())
+#set($intfname = "$i$suffix")
+#set($baseclname = "Base$intfname")
+#set($clname = "Impl$intfname")
+#if ($helper.isServer($mc))
+#set($peer = "client")
+#set($peerclass = "Remote${i}Client")
+#else
+#set($peer = "server")
+#set($peerclass = "Remote${i}Server")
+#end
+
+using System;
+#if ($helper.isServer($mc))
+
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+using ${intf.parent().name()}.types.${i};
+#else
+
+using ${intf.parent().name()}.types.${i};
+#end 
+
+namespace $intf.parent().name()
+{
+#if ($helper.isServer($mc))
+	///<summary>Main implementation for ${i}Listener.</summary>
+#else
+	///<summary>Main implementation for $i$suffix.</summary>
+#end
+#if ($helper.isServer($mc))
+	public class Main${i}Listener : ${i}Helper.${i}ServerFactory
+#else
+	public class Main${i}Client : ${i}Helper.${i}ClientFactory
+#end
+	{
+#if ($helper.isServer($mc))
+ 		///<summary>Main for ${i}Listener.</summary>
+#else
+		///<summary>Main for ${i}Client</summary>
+#end
+		///<param name="args">Command Line Arguments</param>
+		public static void Main(String[] args)
+		{
+			// TODO: Change to correct URI
+			string uri = "tcp://localhost:4001";
+			
+#if ($helper.isServer($mc))
+			ServerFactory listener = ${i}Helper.NewListener( uri, null, new Main${i}Listener());
+			
+			// Start the Listener
+			listener.TransportControl( TransportConsts.START_AND_WAIT_UP, 4000 );
+#else
+			Remote${i}Server server = ${i}Helper.NewServer( uri, null, new Main${i}Client());
+		
+			// Connect to the service
+			server._StartAndWaitUp( 4000 );
+
+			// TODO: Insert Your Code Here
+
+			// Disconnect from the service
+			server._StopAndWaitDown( 4000 );			
+#end
+		}
+
+#if ($helper.isServer($mc))
+		///<summary>Return a new instance of ${i}Server.</summary>
+		///<param name="client">Reference to remote service</param>
+		///<returns>Server Implementation</returns>
+		public ${i}Server New${i}Server( Remote${i}Client client )
+		{
+			return new Impl${i}Server( client );
+		}
+#else
+		///<summary>Return a new instance of ${i}Client.</summary>
+		///<param name="server">Reference to remote service</param>
+		///<returns>Client Implementation</returns>
+		public ${i}Client New${i}Client( Remote${i}Server server )
+		{
+			return new Impl${i}Client( server );
+		}
+#end
+	}
+}
\ No newline at end of file
diff --git a/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/readme.vm b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/readme.vm
new file mode 100644
index 0000000..196dced
--- /dev/null
+++ b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/readme.vm
@@ -0,0 +1,140 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created and should not be edited!
+
+This is a description of the etch-generated files for your service.
+
+----------------
+- How To Build -
+----------------
+
+In the directory where the etch file is located, execute the following command:
+
+etch -q -d . -I . -b csharp -w all Blah.etch
+
+This would compile the service description Blah.etch, generating all csharp files,
+into csharp namespaces rooted in the current directory (-d .), resolving includes
+and mixins from the current directory (-I .) and being quiet about it (-q).
+
+Assuming the Blah.etch specified a module of "demo" and a service of "Blah",
+the csharp files would be generated into a sub-directory demo of the current
+directory. you may now change to that directory and compile the resulting files:
+
+cd demo
+csc "/reference:%ETCH_HOME%\lib\Etch4CS.dll" /main:demo.MainBlahListener *.cs
+csc "/reference:%ETCH_HOME%\lib\Etch4CS.dll" /main:demo.MainBlahClient *.cs
+
+(Assuming windows; for unix, read the mono directions.)
+
+Depending upon how etch was installed, you may need to install the Etch4CS.dll
+into the system global assembly cache. This command will do the trick:
+
+copy /y "%ETCH_HOME%\lib\Etch4CS.dll" %windir%\assembly
+
+You only need to do this once after each installation of etch. And once the
+installer is fixed, you won't need to do it at all.
+
+To run the service (which initially won't do anything but make a connection and
+then close it, use the following two commands in separate shells (again, from
+the demo directory):
+
+MainBlahListener
+
+MainBlahClient
+
+The first command (MainBlahListener) starts the service listener which accepts
+connections. The second command (MainBlahClient) runs a sample client, which
+makes a connection to the running listener and then closes it again.
+
+Once you've compiled the service and tested the result, you may implement your
+service by adding content to the etch file, adding implementation details to the
+Impl*.cs and Main*.cs files, and recompiling using the above steps. You may also
+load these files into an IDE such as visual studio, or use a build management
+system such as msbuild or nant. Remember, whenever you change the etch file, you
+must re-etch the service description and then re-csc all the cs
+files.
+
+-------------------
+- Generated Files -
+-------------------
+
+Here is a description of the generated files for a service named Blah.
+
+Blah.cs
+BlahClient.cs
+BlahServer.cs
+
+These three files are the generated interface classes. Service defined constants
+and types are in Blah.cs, as well as direction "both" messages, which are
+messages which are shared between client and server. BlahClient.cs and
+BlahServer.cs are respectively the messages for just the direction client or
+server. You should not edit these files.
+
+RemoteBlah.cs
+RemoteBlahClient.cs
+RemoteBlahServer.cs
+
+RemoteBlah*.cs are the generated classes which implement the interfaces,
+with message implementations which encode the message type and arguments for
+transport to the connection peer and then receive and decode any response. You
+should not edit these files.
+
+StubBlah.cs
+StubBlahClient.cs
+StubBlahServer.cs
+
+StubBlah*.cs are the generated classes which receive messages encoded by
+RemoteBlah*.cs and decode them, calling the appropriate message implementation
+and then encoding and sending any result. You should not edit these files.
+
+ValueFactoryBlah.cs
+
+ValueFactoryBlah.cs is a generated class which contains helper code to
+serialize service defined types and also the meta data which describes the
+messages and fields, field types, timeouts, etc. You should not edit this file.
+
+BaseBlah.cs
+BaseBlahClient.cs
+BaseBlahServer.cs
+
+BaseBlah*.cs are generated classes which implement the interfaces, with
+message implementations which do nothing but throw UnsupportedOperationException.
+They can be used to supply an implementation when you don't want to immediately
+implement all the messages. You should not edit these files.
+
+ImplBlahClient.cs
+ImplBlahServer.cs
+
+ImplBlah*.cs are the generated sample client and server implementation
+classes. They extend the generated base classes. These are used by the sample
+main programs to provide implementations of the client or server messages. Edit
+these files as you wish to implement your service (overriding the default
+implementations from the generated base classes).
+
+BlahHelper.cs
+
+BlahHelper.cs is a generated class which includes static methods to help
+construct transports for client and listener. You should not edit this file.
+
+MainBlahClient.cs
+MainBlahListener.cs
+
+MainBlah*.cs are the generated sample client and server main programs.
+They show how to setup a transport and start it and how to create a session.
+Edit these files as you wish to implement your service, or just copy the code
+into your own application.
+
diff --git a/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/remote.vm b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/remote.vm
new file mode 100644
index 0000000..89b417c
--- /dev/null
+++ b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/remote.vm
@@ -0,0 +1,451 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created and should not be edited!
+#set($i = $intf.name())
+#set($vfname = "ValueFactory$i")
+#set($intfname = "$i$suffix")
+#set($clname = "Remote$intfname")
+
+using System;
+
+namespace $intf.parent().name()
+{
+
+#if (!$hasBaseClass)
+#end
+#foreach( $n in $intf.iterator() )
+#if ($n.isExtern())
+#if ($n.hasImport( $helper ))
+	using $n.getImport( $helper );
+#end
+#end
+#end
+	///<summary>Call to message translator for $intfname.</summary>
+#if ($hasBaseClass)
+	public class $clname : Remote$i, $intfname
+#else
+	public class $clname : Org.Apache.Etch.Bindings.Csharp.Support.RemoteBase, $intfname
+#end
+	{
+#if ($hasBaseClass)
+		///<summary>Class Instance used to hide synchronous message 
+		///implementation. Use this to invoke the asynchronous message
+		///implementation</summary> 
+		public new readonly _Async _async;
+		
+		///<summary>Deprecated.</summary>
+		public new readonly _Async _inner;
+#else
+		///<summary>Class Instance used to hide synchronous message 
+		///implementation. Use this to invoke the asynchronous message
+		///implementation</summary> 
+		public readonly _Async _async;
+		
+		///<summary>Deprecated.</summary>
+		public readonly _Async _inner;
+#end
+
+		/// <summary>Constructs the $clname.</summary>
+		/// <param name="svc"></param>
+		/// <param name="vf"></param>
+		public $clname( Org.Apache.Etch.Bindings.Csharp.Support.DeliveryService svc,
+				Org.Apache.Etch.Bindings.Csharp.Msg.ValueFactory vf )
+			: base( svc, vf )
+		{
+			_async = new _Async(this);
+			_inner = _async;
+#set( $k = 0 )
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+#set( $k = $k + 1 )
+#set( $v = "_mixin$k" )
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+			$v = new ${m.name()}.Remote$z.name()${suffix}( svc, vf );
+#end
+#end
+		}
+
+#foreach ($n in $intf.iterator())
+#if ($n.isMsgDir($mc))
+#if (!$n.isHidden())
+#if(!$methodList.contains($n.name().name()))
+#set ( $addMethodListStatus = $methodList.add($n.name().name()))
+#if ($n.isOneway())
+#if ($n.hasDescr())
+		///<summary>
+#foreach($s in $n.descr())
+		///$s
+#end
+		///</summary>
+#end
+#foreach( $p in $n.iterator() )
+#set($first = true)
+#set ($count = 0)
+#if ($p.hasDescr())
+#foreach( $s in $p.descr() )
+#if ($first)
+#set($count = $count + 1)
+#set($first = false)
+		///<param name="$p.name()">$s
+#else
+		///$s
+#end
+#end
+#if ($count > 0)
+		///</param>
+#end
+#end
+#end
+#if ($n.hasReturn())
+#set($first = true)
+#set ($retCount = 0)
+#if ($n.hasDescr())
+#foreach( $s in $n.returnDescr() )
+#if ($first)
+#set($retCount = $retCount + 1)
+#set($first = false)
+		///<returns>$s
+#else
+		///$s
+#end
+#end
+#if ($retCount > 0)
+		///</returns>
+#end
+#end
+#end
+#if ($n.hasThrown())
+#if ($n.hasDescr())
+#foreach($t in $n.thrown().iterator())
+		///<Exception cref="$t.name().name()"> throws $t.name().name()</Exception>
+#end
+#end
+#end
+		public $helper.getTypeName( $n.type() ) $n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+			$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+		)
+		{
+			Org.Apache.Etch.Bindings.Csharp.Msg.Message _msg = _NewMessage( $vfname.$n.vname( $helper ) );
+#foreach( $p in $n.iterator() )
+			_msg.Add( $vfname.$p.vname( $helper ), $p.name() );
+#end
+			try
+			{
+				_Send( _msg );
+			}
+			catch ( Exception _e )
+			{
+				throw new Exception( "unexpected", _e );
+			}
+		}
+#else
+#if($n.hasDescr())
+		///<summary>
+#foreach($s in $n.descr())
+		///$s
+#end
+		///</summary>
+#end
+#foreach( $p in $n.iterator() )
+#set($first = true)
+#if ($p.hasDescr())
+#foreach( $s in $p.descr() )
+#if ($first)
+#set($first = false)
+		///<param name="$p.name()">$s
+#else
+		///$s
+#end
+#end
+		///</param>
+#end
+#end
+#if ($n.hasReturn())
+#set($first = true)
+#set($retCount = 0)
+#if ($n.hasDescr())
+#foreach( $s in $n.returnDescr() )
+#if ($first)
+#set($first = false)
+#set($retCount = $retCount + 1)
+		///<returns>$s
+#else
+		///$s
+#end
+#end
+#if ($retCount > 0)
+		///</returns>
+#end
+#end
+#end
+#if ($n.hasThrown())
+#if ($n.hasDescr())
+#foreach($t in $n.thrown().iterator())
+		///<Exception cref="$t.name().name()"> throws $t.name().name()</Exception>
+#end
+#end
+#end
+		public $helper.getTypeName( $n.type() ) $n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+			$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+		)
+		{
+#if ($n.hasReturn())
+			return
+#end
+			_async._end_${n.name()}( _async._begin_${n.name()}(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+				$sep$p.name()
+#set( $sep = ", " )
+#end
+			) );
+		}
+		
+#end
+#end
+#end
+#end
+#end
+#set( $k = 0 )
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+
+		// ----- mixin $x.name() ----- //
+#set( $k = $k + 1 )
+#set( $v = "_mixin$k" )
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+		private ${m.name()}.Remote$z.name()$suffix $v;
+		
+#foreach( $n in $z.messages( true ) )
+#if($n.isMsgDir($mc))
+#if(!$n.isHidden())
+#if(!$methodList.contains($n.name().name()))
+#set ( $addMethodListStatus = $methodList.add($n.name().name()) )
+		// --- generated methods for $n.name() --- //
+#if($n.isOneway())
+		public $helper.getTypeName( $n.type() ) $n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+			$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+		)
+		{
+			${v}.$n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+				$sep$p.name()
+#set( $sep = ", " )
+#end
+			);
+		}
+#else
+		public $helper.getTypeName( $n.type() ) $n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+			$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+		)
+		{
+#if($n.hasReturn())
+			return
+#end
+			${v}.$n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+				$sep$p.name()
+#set( $sep = ", " )
+#end
+			);
+		}
+		
+#end
+#end
+#end
+#end
+#end
+#end
+#end
+
+		///<summary>Asynchronous Implementation of service methods</summary>
+#if ($hasBaseClass)
+		public new class _Async : Remote${i}._Async
+#else
+		public class _Async
+#end
+		{
+#if ($hasBaseClass)
+			public new $clname _parent;
+#else
+			public $clname _parent;
+#end
+			
+			public _Async()
+			{
+			}
+
+			public _Async($clname parent)
+			{
+				_parent = parent;
+			}
+			
+#foreach ($n in $intf.iterator())
+#if ($n.isMsgDir($mc))
+#if (!$n.isHidden())
+#if(!$methodList.contains("_begin_end_$n.name().name()"))
+#set ( $addMethodListStatus = $methodList.add("_begin_end_$n.name().name()") )
+#if (!$n.isOneway())
+			///<summary>Begins the call to ${n.name()}.</summary>
+#foreach( $p in $n.iterator() )
+#if ($p.hasDescr())
+#set($first = true)
+#foreach( $s in $p.descr() )
+#if ($first)
+#set($first = false)
+			///<param name = $p.name()>$s
+#else
+			///$s
+#end
+#end
+			///</param>
+#end
+#end
+			///<returns>mailbox to use to retrieve the result using _end_${n.name()}.</returns>			
+			public Org.Apache.Etch.Bindings.Csharp.Support.Mailbox _begin_${n.name()}(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+				$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+			)
+			{
+				Org.Apache.Etch.Bindings.Csharp.Msg.Message _msg = _parent._NewMessage( $vfname.$n.vname( $helper ) );
+#foreach( $p in $n.iterator() )
+				_msg.Add( $vfname.$p.vname( $helper ), $p.name() );
+#end
+				return _parent._BeginCall( _msg );
+			}
+	 
+			/// <summary>Waits for the call to end and returns the result.</summary>
+			/// <param name="_mb">mailbox returned by _begin_${n.name()}.</param>
+			public $helper.getTypeName( $n.type() ) _end_${n.name()}( Org.Apache.Etch.Bindings.Csharp.Support.Mailbox _mb )
+			{
+#if ($n.hasReturn())
+				return
+				($helper.getTypeName( $n.type() ))
+#if ($n.type().dim() > 0)
+					// ValueFactory${i}.to_$n.type().type()(
+					//	typeof( ${helper.getTypeName( $n.type() )} ),
+#end
+					_parent._EndCall( _mb,
+						$vfname.$n.getResultMessage().vname( $helper ) )
+#if ($n.type().dim() > 0)
+					//)
+#end
+				;
+#else
+			
+				_parent._EndCall( _mb,
+				$vfname.$n.getResultMessage().vname( $helper ) );
+#end
+
+			}
+
+#end
+#end
+#end
+#end
+#end
+#set( $k = 0 )
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+#set( $k = $k + 1 )
+#set( $v = "_mixin$k" )
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+	
+#foreach( $n in $z.messages( true ) )
+#if($n.isMsgDir($mc))
+#if(!$n.isHidden())
+#if(!$methodList.contains("_begin_end_$n.name().name()"))
+#set ( $addMethodListStatus = $methodList.add("_begin_end_$n.name().name()") )
+			// --- generated methods for $n.name() --- //
+
+#if(! $n.isOneway())
+			///<summary>Begins a call to ${n.name()}.</summary>
+#foreach( $p in $n.iterator() )
+#if ($p.hasDescr())
+#set($first = true)
+#foreach( $s in $p.descr() )
+#if ($first)
+#set($first = false)
+			///<param name = $p.name()>$s
+#else
+			///$s
+#end
+#end
+			///</param>
+#end
+#end
+
+			public Org.Apache.Etch.Bindings.Csharp.Support.Mailbox _begin_${n.name()}(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+				$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+			)
+			{
+				return _parent.${v}._async._begin_${n.name()}(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+					$sep$p.name()
+#set( $sep = ", " )
+#end
+				);
+			}
+			
+			///<summary>Ends a call to ${n.name()}</summary>
+			///<param name = mb> mailbox returned by _begin_${n.name()}. </param>
+			public $helper.getTypeName( $n.type() ) _end_${n.name()}( Org.Apache.Etch.Bindings.Csharp.Support.Mailbox _mb )
+			{
+#if($n.hasReturn())
+				return
+#end
+				_parent.${v}._async._end_${n.name()}( _mb );
+			}
+#end
+#end
+#end
+#end
+#end
+#end
+#end	
+		}
+	}
+}
diff --git a/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/stub.vm b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/stub.vm
new file mode 100644
index 0000000..dc2fedd
--- /dev/null
+++ b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/stub.vm
@@ -0,0 +1,154 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created and should not be edited!
+#set($i = $intf.name())
+
+using System;
+	
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace $intf.parent().name()
+{	
+#foreach( $n in $intf.iterator() )
+#if ($n.isExtern())
+#if ($n.hasImport( $helper ))
+#set($x = $n.getImport( $helper ))
+#if (!$x.equals("Etch.Util"))
+	using $x;
+#end
+#end
+#end
+#end
+
+	///<summary> Message to call translator for $i$suffix. </summary>
+	
+#if ($hasBaseClass)
+	public class Stub$i$suffix : Stub$i
+#else
+	public class Stub$i$suffix : StubBase
+#end
+	{
+		/// <summary>Stub for $i$suffix.</summary>
+		/// <param name="src">the delivery service to use.</param>
+		/// <param name="obj"> the implementation of $i$suffix responsive to requests.</param>
+		/// <param name="queued"> thread pool used to run AsyncReceiverMode.QUEUED methods.</param>
+		/// <param name="free"> thread pool used to run AsyncReceiverMode.FREE methods.</param>		
+		public Stub$i$suffix( DeliveryService src, object obj, Pool queued, Pool free )
+			: base( src, obj, queued, free )
+		{	
+			// nothing to do.
+		}
+		
+#if (!$hasBaseClass)
+		public static void init()
+#else
+		public static new void init()
+#end
+		{
+			// nothing to do.
+		}
+
+		static Stub$i$suffix()
+		{
+#foreach( $n in $intf.iterator() )
+#if( $n.isMixin() )
+#set( $m = $n.getModule() )
+#set( $z = $m.iterator().next() )
+			${m.name()}.Stub${z.name()}${suffix}.init();
+#end
+#end
+#set( $stubHelperCount=0 )
+#foreach( $mthd in $intf.iterator() )
+#if ($mthd.isMsgDir($mc))
+#if (!$mthd.isHidden())
+#set($stubHelperCount = $stubHelperCount + 1)
+			StubHelperRun helper$stubHelperCount = delegate( DeliveryService _src, object _obj, Who _sender, Message _msg ) 
+				{
+					try {
+#foreach ($param in $mthd.iterator())
+							$helper.getTypeName( $param.type() ) $param.name() = 
+								($helper.getTypeName( $param.type() ))
+								_msg.Get( ValueFactory$i.$param.vname( $helper ) );
+#end
+
+#if ($mthd.hasAuth())
+#set( $auth = $mthd.getAuth() )
+#if ($auth.isMethodFalse())
+							if (true)
+#else
+							if ((bool)!(($i$suffix)_obj).${auth.method()}(
+#set( $sep = "" )
+#foreach($arg in $auth.args())
+#if ($arg.isLiteralConstant())
+								($helper.getNativeTypeName( $arg.type() )) $sep$helper.getTypeValue( $arg.type(), $arg.value() )
+#elseif ($arg.isParameter( $mthd ))
+								$sep$helper.qualifyParameterName( $arg.value() )
+#elseif ($arg.isConstant( $intf ))
+								$sep$helper.qualifyConstantName( $intf, $arg.value() )
+#elseif ($arg.isEnum( $intf ))
+								$sep$helper.qualifyEnumName( $intf, $arg.value() )
+#else
+								${sep}null
+#end
+#set( $sep = ", " )
+#end
+							)) 
+#end
+							throw new _Etch_AuthException( "$mthd.name()" );
+#end
+
+#if ($mthd.hasReturn())
+							Object _result =
+#end
+								(($i$suffix)_obj).$mthd.name()(
+#set( $sep = "" )
+#foreach ($param in $mthd.iterator())
+								$sep$param.name()
+#set( $sep = ", " )
+#end
+								);
+								
+#if (!$mthd.isOneway())
+							Message _rmsg = _msg.Reply();
+#if ($mthd.hasReturn())
+							_rmsg.Add( ValueFactory$i._mf_result, _result );
+#end
+							_src.TransportMessage( _sender, _rmsg );
+#end
+						}
+						catch ( Exception e )
+						{
+#if (!$mthd.isOneway())
+							Message _rmsg = _msg.Reply();
+#else
+							Message _rmsg = _msg.Reply( _msg.Vf.get_mt__exception() );
+#end
+							_rmsg.Add( ValueFactory$i._mf_result, e );
+							_src.TransportMessage( _sender, _rmsg );
+						}
+					};
+			ValueFactory$i.${mthd.vname( $helper )}.SetStubHelper( helper$stubHelperCount);		
+#end
+#end
+#end
+		}
+	}
+}
+
+	
\ No newline at end of file
diff --git a/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/vf.vm b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/vf.vm
new file mode 100644
index 0000000..85d9ade
--- /dev/null
+++ b/binding-csharp/compiler/src/main/resources/org/apache/etch/bindings/csharp/compiler/vf.vm
@@ -0,0 +1,282 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created and should not be edited!
+
+using System;
+using System.Collections.Generic;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+#foreach( $n in $intf.iterator() )
+#if ($n.isExtern())
+#if ($n.hasImport( $helper ))
+using $n.getImport( $helper );
+#end
+#if ($n.hasSerializerImport( $helper ))
+using $n.getSerializerImport( $helper );
+#end
+#end
+#end
+#set( $i = $intf.name() )
+#set( $vf = "ValueFactory$i" )
+
+namespace $intf.parent().name()
+{
+
+///<summary>ValueFactory for $i.</summary>
+public class ${vf} : DefaultValueFactory
+{
+	private readonly static TypeMap types = new TypeMap();
+    
+	private readonly static Class2TypeMap class2type = new Class2TypeMap();
+	 
+	///<summary>Constructs ${vf}.</summary>
+	public ${vf}(string uri) : base(uri, types, class2type)
+	{
+#foreach ( $n in $intf.iterator() )
+#if ($n.isMixin())
+#set( $m = $n.getModule() )
+#set( $s = $m.iterator().next() )
+		addMixin( new ${m.name()}.ValueFactory${s.name()}(uri) );
+#end
+#end		
+	}
+	
+	private static void InitTypes()
+	{
+#foreach ( $n in $intf.iterator() )
+#if ($n.isEnumx() || $n.isStruct() || $n.isExtern() || $n.isExcept() || $n.isMessage())
+		$n.vname( $helper ) =  types.Get( "$n.fqname()" );
+#end
+#end
+	}
+	
+	private static void InitResults() 
+	{
+#foreach ( $n in $intf.iterator() )
+#if ($n.isMessage())
+		${n.vname( $helper )}.SetDirection( Direction.$n.msgDir() );
+#if (!$n.isHidden())
+#if ($n.isQueuedAsyncReceiver())
+		${n.vname( $helper )}.SetAsyncMode( AsyncMode.QUEUED );
+#elseif ($n.isFreeAsyncReceiver())
+		${n.vname( $helper )}.SetAsyncMode( AsyncMode.FREE );
+#else
+		${n.vname( $helper )}.SetAsyncMode( AsyncMode.NONE );
+#end
+#if (!$n.isOneway())
+#set($r = $n.getResultMessage())
+		${n.vname( $helper )}.SetResult( $r.vname( $helper ) );
+		${r.vname( $helper )}.Timeout = $n.getTimeout();
+#end
+#end
+#end
+#end	
+	}
+	
+	private static void InitFields()
+	{
+#set( $x = $params.clear() )
+## standard params from DefaultValueFactory
+#set( $x = $params.add( "msg" ) )
+#set( $x = $params.add( "result" ) )
+#foreach( $n in $intf.iterator() )
+#if ($n.isEnumx() || $n.isStruct() || $n.isExcept() || $n.isMessage())
+#foreach( $param in $n.iterator() )
+#if (!$params.contains($param.name().name()))
+#set( $x = $params.add($param.name().name()) )
+		$param.vname( $helper ) = new Field( "$param.name().name()" );
+#end
+#end
+#end
+#end
+#foreach ( $n in $intf.iterator() )
+#if ($n.isMessage())
+#if (!$n.isHidden())
+#if (!$n.isOneway())
+#set( $r = $n.getResultMessage() )
+		${r.vname( $helper )}.ResponseField = _mf_result;
+#end
+#end
+#end
+#end	
+	}
+	
+	private static void InitParams()
+	{
+#foreach( $n in $intf.iterator() )
+#if ($n.isEnumx() || $n.isStruct() || $n.isExcept() || $n.isMessage())
+#if ($n.isStruct() || $n.isExcept())
+#foreach( $param in $n.getAllParameters() )
+		${n.vname( $helper )}.PutValidator( $param.vname( $helper ), $helper.getValidator( $param ) );
+#end
+#else
+		// params for $n.name()
+#foreach( $param in $n.iterator() )
+		${n.vname( $helper )}.PutValidator( $param.vname( $helper ), $helper.getValidator( $param ) );
+#end
+#end
+#if ($n.isMessage())
+		${n.vname( $helper )}.PutValidator( _mf__messageId, Validator_long.Get( 0 ) );
+#if ($n.isHidden())
+#set( $param = $n.getResultParam() )
+#set( $reqMsg = $n.getRequestMessage() )
+#foreach( $t in $reqMsg.thrown().iterator() )
+		${n.vname( $helper )}.PutValidator( $param.vname( $helper ), $helper.getValidator( $t ) ); // thrown $t.name()
+#end
+		${n.vname( $helper )}.PutValidator( $param.vname( $helper ), Validator_RuntimeException.Get() ); // thrown RuntimeException
+		${n.vname( $helper )}.PutValidator( _mf__inReplyTo, Validator_long.Get( 0 ) );
+#end
+#end
+#end
+#end
+	}
+	
+	
+	static ${vf}()
+	{
+		DefaultValueFactory.Init( types, class2type );
+		InitTypes();		
+		InitResults();
+		InitFields();
+		InitParams();
+
+## --- import/export ----
+
+#foreach ( $n in $intf.iterator() )
+#if ($n.isStruct() || $n.isExcept())
+#set( $tname = $n.efqname( $helper ) )
+
+		class2type.Add( typeof( ${tname} ), ${n.vname( $helper )} );
+		${n.vname( $helper )}.SetComponentType( typeof( ${tname} ) );
+		#if ($n.hasExtends())
+			${n.vname( $helper )}.SetSuperType( $n.getExtends().vname( $helper ) );
+		#end
+		${n.vname( $helper )}.SetImportExportHelper
+			( 
+				new ImportExportHelper(
+					delegate( ValueFactory vf, Object value ) 
+					{
+						StructValue sv = new StructValue( ${n.vname( $helper )}, vf );
+						$tname v = ($tname) value;
+#foreach( $p in $n.getAllParameters()  )
+						sv.Add( $p.vname( $helper ), v.$p.name() );
+#end
+						return sv;
+					}, 
+					delegate( StructValue sv ) 
+					{
+						$tname v = new ${tname}();
+						#foreach ($p in $n.getAllParameters())
+						v.$p.name() = ($helper.getTypeName( $p.type() )) sv.Get( $p.vname( $helper ) );
+						#end
+						return v;
+						
+					} 
+				)
+			);
+
+#elseif ($n.isExtern())
+#set( $tname = $n.efqname( $helper ) )
+#elseif ($n.isEnumx())
+#set( $tname = $n.efqname( $helper ) )
+
+		class2type.Add( typeof( ${tname} ), ${n.vname( $helper )} );
+		${n.vname( $helper )}.SetComponentType( typeof( ${tname} ) );
+		${n.vname( $helper )}.SetImportExportHelper
+			( 
+				new ImportExportHelper( 
+					
+					delegate( ValueFactory vf, Object value ) 
+					{
+						StructValue sv = new StructValue( ${n.vname( $helper )}, vf );
+						${tname} v = (${tname}) value;
+						switch (v)
+						{
+#foreach ($p in $n.iterator())
+							case ${tname}.$p.name(): sv.Add( $p.vname( $helper ), true ); break;
+#end
+						}
+						return sv;
+					}, 
+					delegate( StructValue sv ) 
+					{
+						// there should only be a single key, so take the first
+						// one. if there is no key, means they sent null or the
+						// key they sent was unknown.
+						Field key = null;
+						IEnumerator<Field> myEnum = sv.Keys.GetEnumerator();
+						if (myEnum.MoveNext())
+							key = myEnum.Current;
+						else
+							return null;
+						
+#foreach ($p in $n.iterator())
+						if (key == $p.vname( $helper )) return ${tname}.$p.name();
+#end
+						
+						return null;
+					} 
+				)
+			);
+
+#end
+#end
+
+		// initialize the extern serializers:
+#foreach( $n in $intf.iterator() )
+#if ($n.isExtern())
+		${n.sname( $helper )}.Init( ${n.vname( $helper )}, class2type );
+#end
+#end
+
+		// done updating types and fields, lock them.
+		types.Lock();
+		foreach(XType t in types.Values())
+			t.Lock();
+		class2type.Lock();
+
+
+	
+	} // end of static constructor
+
+	
+	
+#foreach ( $n in $intf.iterator() )
+#if ($n.isEnumx() || $n.isStruct() || $n.isExtern() || $n.isExcept() || $n.isMessage())
+	/// Type for $n.fqname() 
+	public static XType $n.vname( $helper );
+#end
+#end
+## ---------------------------------------------------------------------------
+	
+		
+#set( $x = $params.clear() )
+## standard params from DefaultValueFactory
+#set( $x = $params.add( "msg" ) )
+#set( $x = $params.add( "result" ) )
+#foreach( $n in $intf.iterator() )
+#if ($n.isEnumx() || $n.isStruct() || $n.isExcept() || $n.isMessage())
+#foreach( $param in $n.iterator() )
+#if (!$params.contains($param.name().name()))
+#set( $x = $params.add($param.name().name()) )
+	public static Field $param.vname( $helper );
+#end
+#end
+#end
+#end
+	}
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/build.xml b/binding-csharp/runtime/build.xml
new file mode 100644
index 0000000..ae4b205
--- /dev/null
+++ b/binding-csharp/runtime/build.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+-->
+<project name="etch-csharp-runtime" basedir="." default="help">
+    <description>Etch-to-Csharp runtime binding implementation</description>
+    <property name="Etch.basedir" location="${basedir}/../.." />
+    <import file="${Etch.basedir}/build-support/etch.includes.xml" />
+
+    <taskdef resource="org/apache/ant/dotnet/antlib.xml" classpath="${Etch.dependency.ant-dotnet-1.0.jar}" />
+
+    <!-- Static properties of the sub-project -->
+    <property name="proj"                 location="${Etch.basedir}/binding-csharp/runtime" />
+    <property name="target"               location="${proj}/target" />
+    <property name="src"                  location="${proj}/src" />
+    <property name="rawNUnitResults"      location="${target}/nunit-results" />
+    <property name="testResultsDirectory" location="${target}/test-results"  />
+
+    <!-- INIT TARGET -->
+    <!-- Modify this target to define project specific properties that can only be set at runtime -->
+    <target name="do-init">
+        <delete dir="${target}" failonerror="false" quiet="true" />
+
+        <mkdir dir="${target}" />
+        <mkdir dir="${rawNUnitResults}" />
+        <mkdir dir="${testResultsDirectory}" />
+    </target>
+
+    <!-- CLEAN TARGET -->
+    <target name="do-clean">
+        <delete dir="${target}" />
+        <delete dir="${src}/main/csharp/bin" />
+        <delete dir="${src}/main/csharp/obj" />
+        <delete dir="${src}/test/csharp/bin" />
+        <delete dir="${src}/test/csharp/obj" />
+    </target>
+
+    <!-- BUILD TARGET -->
+
+    <target name="generate-sources" >
+        <!-- Generate version info -->
+        <update-tokens filename="${src}/main/csharp/Properties/AssemblyInfo.cs" />
+    </target>
+
+    <target name="build-main-with-mono" if="USE.mono" >
+        <echo message="TODO: build w/ mono" />
+        <mdtool dir="${src}/main/csharp" project="EtchProj.csproj" />
+    </target>
+
+    <target name="build-main-with-dotnet" if="USE.dotnet" >
+        <!-- Build runtime -->
+        <msbuild buildfile="${src}/main/csharp/EtchProj.csproj">
+            <property name="Configuration" value="${Etch.build.target}" />
+        </msbuild>
+    </target>
+
+    <target name="build-main-csharp" depends="build-main-with-mono,build-main-with-dotnet" />
+
+    <target name="do-build" depends="generate-sources,build-main-csharp" if="BUILD.csharp" >
+
+        <mkdir dir="${Etch.dist}/lib" />
+        <mkdir dir="${Etch.clover-dist}/lib" />
+
+        <copy todir="${Etch.clover-dist}/lib" >
+            <fileset dir="${src}/main/csharp/bin/${Etch.build.target}">
+                <include name="*.pdb" />
+                <include name="*.dll" />
+            </fileset>
+        </copy>
+
+        <copy todir="${Etch.dist}/lib" >
+            <fileset dir="${src}/main/csharp/bin/${Etch.build.target}">
+                <include name="*.pdb" />
+                <include name="*.dll" />
+            </fileset>
+        </copy>
+    </target>
+
+    <!-- TEST TARGET -->
+    <target name="build-test-with-mono" if="USE.mono" >
+        <echo message="TODO: build w/ mono" />
+        <mdtool dir="${src}/test/csharp" project="EtchTestProj.csproj" />
+    </target>
+
+    <target name="build-test-with-dotnet" if="USE.dotnet" >
+        <msbuild buildfile="${src}/test/csharp/EtchTestProj.csproj" >
+            <property name="Configuration" value="${Etch.build.target}" />
+        </msbuild>
+    </target>
+
+    <target name="build-test-csharp" depends="build-test-with-mono,build-test-with-dotnet" />
+
+    <target name="do-test" depends="build-test-csharp" if="USE.dotnet" >
+        <mkdir dir="${rawNUnitResults}" />
+
+        <nunit xmlout="${rawNUnitResults}/NUnitResults.xml">
+            <testassembly name="${src}/test/csharp/bin/${Etch.build.target}/EtchTest.dll" />
+        </nunit>
+
+        <xslt style="${Etch.buildSupportDirectory}/NUnitToJUnit.xsl"
+                in="${rawNUnitResults}/NUnitResults.xml" out="${testResultsDirectory}/TEST-NUnitResults.xml" />
+    </target>
+
+    <!-- POSTBUILD TARGET -->
+    <target name="do-postbuild">
+    </target>
+
+    <target name="do-publish" if="build.tests.fail">
+        <!-- Set flag file if any tests failed -->
+        <touch file="${Etch.runtime.tests.fail}"/>
+    </target>
+
+</project>
diff --git a/binding-csharp/runtime/src/main/csharp/EtchProj.csproj b/binding-csharp/runtime/src/main/csharp/EtchProj.csproj
new file mode 100644
index 0000000..f5ee56c
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/EtchProj.csproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Etch</RootNamespace>
+    <AssemblyName>Etch</AssemblyName>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>etch.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Msg\AsyncMode.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Msg\ComboValidator.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Msg\Direction.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Msg\Field.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Msg\FieldMap.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Msg\IdName.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Msg\IdNameMap.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Msg\ImportExportHelper.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Msg\Message.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Msg\StructValue.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Msg\TypeMap.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Msg\Validator.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Msg\ValueFactory.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Msg\XType.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\AuthExceptionSerializer.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Class2TypeMap.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\DefaultServerFactory.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\DefaultValueFactory.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\DeliveryService.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\DummyValueFactory.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\FreePool.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Mailbox.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\NullPool.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\ObjSession.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Pool.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\QueuedPool.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\RemoteBase.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\RuntimeExceptionSerializer.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\ServerFactory.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\StubBase.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\StubHelper.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\TransportFactory.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\TransportHelper.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\TypeValidator.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Validator_boolean.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Validator_byte.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Validator_custom.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Validator_double.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Validator_float.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Validator_int.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Validator_long.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Validator_object.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Validator_RuntimeException.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Validator_short.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Validator_string.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Validator_StructValue.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\Validator_void.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\_Etch_AuthException.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Support\_Etch_RuntimeException.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\ArrayValue.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\DefaultDeliveryService.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\Filter\AbstractMessageFilter.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\Filter\KeepAlive.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\Filter\Logger.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\Filter\PwAuth.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\Fmt\Binary\BinaryTaggedData.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\Fmt\Binary\BinaryTaggedDataFormatFactory.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\Fmt\Binary\BinaryTaggedDataInput.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\Fmt\Binary\BinaryTaggedDataOutput.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\Fmt\Binary\Validator_none.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\Fmt\ByteToSbyteConverter.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\Fmt\TaggedData.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\Fmt\TypeCode.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\FormatFactory.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\MailboxManager.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\Messagizer.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\PlainMailbox.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\PlainMailboxManager.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\SessionMessage.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\TaggedDataInput.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\TaggedDataOutput.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\TcpTransportFactory.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\TransportMessage.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Transport\UnwantedMessage.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\AbstractStartable.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\AlarmListener.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\AlarmManager.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\ArrayIterator.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\Assertion.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\CharIterator.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\CircularQueue.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\Connection.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\DateSerializer.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\EmptyIterator.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\EqualsHelper.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\FlexBuffer.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\HPTimer.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\IdGenerator.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\InputStream.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\IntCounter.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\Integer.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\ListSerializer.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\MapSerializer.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\Monitor.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\OutputStream.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\Packetizer.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\PerfTest.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\Resources.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\Runner.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\RunnerHandler.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\Session.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\SessionConsts.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\SessionData.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\SessionListener.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\SessionPacket.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\SingleIterator.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\Startable.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\StringTokenizer.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\StringUtil.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\StrIntHashMap.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\StrIntHashMapSerializer.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\StrStrHashMap.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\StrStrHashMapSerializer.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\TcpConnection.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\TcpListener.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\TcpOptions.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\TcpTransport.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\Timer.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\TlsConnection.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\Todo.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\TodoDelegateImpl.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\TodoManager.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\Transport.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\TransportConsts.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\TransportData.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\TransportPacket.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\URL.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\URLSerializer.cs" />
+    <Compile Include="Org.Apache.Etch.Bindings.Csharp\Util\Who.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="etch.snk" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/AsyncMode.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/AsyncMode.cs
new file mode 100644
index 0000000..b1ad49e
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/AsyncMode.cs
@@ -0,0 +1,40 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+    ///
+    /// The asynchronous receiver mode of this helper.
+    ///
+    public enum AsyncMode
+    {
+        /// <summary>
+        /// synchronous mode
+        /// </summary>
+        NONE,
+        /// <summary>
+        ///  the operation is queued to a thread pool for execution 
+        /// </summary>
+        QUEUED,
+        /// <summary>
+        ///  the operation is executed by a newly allocated thread 
+        /// </summary>
+        FREE
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/ComboValidator.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/ComboValidator.cs
new file mode 100644
index 0000000..ec070da
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/ComboValidator.cs
@@ -0,0 +1,113 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+    /// <summary>
+    /// Validates values using one of two validators
+    /// </summary>
+    public class ComboValidator : Validator
+    {
+        /// <summary>
+        /// Constructs the combo validator
+        /// </summary>
+        /// <param name="a"></param>
+        /// <param name="b"></param>
+        public ComboValidator( Validator a, Validator b )
+        {
+            this.a = a;
+            this.b = b;
+        }
+
+        private readonly Validator a;
+        private readonly Validator b;
+
+        public override string ToString()
+        {
+            return String.Format( "({0} OR {1})", a, b );
+        }
+
+        public override Validator ElementValidator()
+        {
+            Validator na;
+
+            try
+            {
+                na = a.ElementValidator();
+            }
+            catch ( Exception )
+            {
+                na = null;
+            }
+
+            Validator nb;
+            try
+            {
+                nb = b.ElementValidator();
+            }
+            catch ( Exception )
+            {
+                nb = null;
+            }
+
+            if ( na == null && nb == null )
+                throw new ArgumentException( "na == null and nb == null" );
+
+            if ( na == null )
+                return nb;
+
+            if ( nb == null )
+                return na;
+
+            return new ComboValidator( na, nb );
+
+        }
+
+        public override bool Validate( object value )
+        {
+            return a.Validate( value ) || b.Validate( value );
+        }
+
+      
+
+        public override object ValidateValue(object value)
+        {
+            try
+            {
+                return a.ValidateValue(value);
+            }
+            catch (Exception)
+            {
+                return b.ValidateValue(value);
+            }
+        }
+
+        public Validator A()
+        {
+            return a;
+        }
+
+        public Validator B()
+        {
+            return b;
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/Direction.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/Direction.cs
new file mode 100644
index 0000000..57d152b
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/Direction.cs
@@ -0,0 +1,40 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+    /// <summary>
+    /// The direction of a message.
+    /// </summary>
+    public enum Direction
+    {
+        /// <summary>
+        /// Message is both toward client and toward server.
+        /// </summary>
+        BOTH,
+        /// <summary>
+        /// Message is toward server.
+        /// </summary>
+        SERVER,
+        /// <summary>
+        /// Message is toward client.
+        /// </summary>
+        CLIENT
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/Field.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/Field.cs
new file mode 100644
index 0000000..70f75f1
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/Field.cs
@@ -0,0 +1,38 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+
+   /// <summary>Field is an IdName which denotes a field of a struct or message (i.e., a key for a value).</summary>
+    public class Field : IdName
+    {
+        ///<summary>Constructs the Field.</summary>
+        ///<param name="id">id the id of the field.</param>
+        ///<param name="name">name the name of the field.</param>
+        public Field(int id, string name)
+            : base(id, name)
+        { }
+
+        ///<param name="name">name the name of the field.</param>
+        public Field(string name)
+            : base(name)
+        { }
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/FieldMap.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/FieldMap.cs
new file mode 100644
index 0000000..fa68786
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/FieldMap.cs
@@ -0,0 +1,32 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+    /// <summary>
+    /// FieldMap is an IdNameMap for Field
+    /// </summary>
+    public class FieldMap : IdNameMap<Field>
+    {
+        public override Field MakeNew( string name )
+        {
+            return new Field( name );
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/IdName.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/IdName.cs
new file mode 100644
index 0000000..1a96ab8
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/IdName.cs
@@ -0,0 +1,122 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+    /// <summary>An IdName is a base class for Field or Type. It is used
+    /// to bind together a type or field name with the associated id. The id
+    /// is used for certain operations, such as the key in a Map, comparisons,
+    /// and binary encoding on the wire, while the name is used for display.
+    /// <see cref=""/> Field
+    /// <see cref=""/> Type</summary>
+    public class IdName
+    {
+        /// <summary>Constructs the IdName.
+        /// <param name="id">id for the name (normally computed using</param> 
+        /// <param name="name"></param>
+        /// {<link>#hash(String)})</link></summary>
+        public IdName(int id, String name)
+        {
+            this.id = id;
+            this.name = name;
+        }
+
+        /// <summary>Constructs the IdName by computing the appropriate id given the name.
+        /// <param name="name"> name the name of the item.</param>
+        /// <see cref=""/> #hash(String)
+        /// </summary>
+        public IdName(string name)
+            : this(Hash(name), name)
+        { }
+
+        private readonly int id;
+
+        private readonly string name;
+
+        /// <returns>the id of the item. </returns> 
+        public int Id
+        {
+            get
+            {
+                return id;
+            }
+        }
+
+        /// <returns> the name of the item.</returns>
+        public string Name
+        {
+            get
+            {
+                return name;
+            }
+        }
+
+        /// Override 
+        public override string ToString() 
+        {
+            return String.Format( "{0}({1})", name, id );
+        }
+
+        /// Override 
+        public override bool Equals(object obj) 
+        {
+            if(obj == this)
+                return true;
+
+            if(obj == null)
+                return false;
+
+            if(this.GetType() != obj.GetType())
+                return false;
+
+            IdName other = (IdName) obj;
+
+            return id.Equals( other.Id ) && name.Equals( other.Name );
+        }
+
+        /// Override
+        public override int GetHashCode() 
+        {
+            return id.GetHashCode() ^ name.GetHashCode();
+        }
+
+        /// <summary>Computes the hash value of the name to be used as the id when
+        /// constructing an IdName.</summary>
+        /// <param name="name"> name the name of the type or field. </param>
+        /// <returns>a hash of name in the unicode character encoding which is
+        /// very likely to be unique over reasonable name spaces. Collisions
+        /// should be very unlikely as they will force the user to change the
+        /// name.</returns>
+        public static int Hash(String name)
+        {
+            // combination of djb2 and sdbm hash algorithm:
+            int hash = 5381;
+            int n = name.Length;
+            for(int i = 0; i < n; i++)
+            {
+                char c = name[i]; 
+                int h6 = hash << 6;
+                hash = (h6 << 10) + h6 - hash + c;
+            }
+            return hash;
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/IdNameMap.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/IdNameMap.cs
new file mode 100644
index 0000000..6acf093
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/IdNameMap.cs
@@ -0,0 +1,184 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+
+    /// <summary>Map by id and name of IdNames (or subclasses thereof).</summary>
+    /// <typeparam name="T">the specific subclass of IdName that is in the map.</typeparam>
+    public abstract class IdNameMap<T> where T : IdName
+    {
+
+        public IdNameMap()
+        {
+            // nothing to do
+        }
+
+        /// <summary>Constructs the IdNameMap.</summary>
+        /// <param name="maxAutoCount">maxAutoCount the maximum number of automatically declared IdNames 
+        /// allowed. Set to 0 if you don't want any, but this may prevent working with a slightly different
+        /// version of a service.</param>
+        public IdNameMap( int maxAutoCount )
+        {
+            this.maxAutoCount = maxAutoCount;
+        }
+    	
+        private int maxAutoCount;
+    	
+        /// <summary>Gets the IdName subclass which corresponds to the specified id, or creates it if it isn't found 
+        /// and if autoCount less than maxAutoCount. If created, the IdName is given the name which is 
+        /// id.toString().</summary>
+        /// <param name="id">id the id of an IdName.</param>
+        /// <returns>the IdName subclass found or created.</returns>
+        public T Get( int id ) 
+        {
+            T t;
+
+            if (byId.TryGetValue(id, out t))
+                return t;
+
+            return null;
+        }
+
+       public T GetById( int id )
+       {
+           T t;
+
+           if (byId.TryGetValue(id, out t))
+               return t;
+
+           return null;
+       }
+
+        /// <summary>Gets the IdName subclass which corresponds to the specified name, or creates it if it isn't 
+        /// found and if autoCount maxAutoCount. If created, the IdName is given the id which is 
+        /// IdName.hash( name ).</summary>
+        /// <param name="name">name the name of an IdName.</param>
+        /// <returns>the IdName subclass found or created.</returns>
+        public T Get( String name )
+        {
+            T t;
+
+            if (byName.TryGetValue(name, out t))
+                return t;
+
+            if (!locked)
+                return Add( MakeNew( name ) );
+
+            return null;
+        }
+
+        public T GetByName(String name)
+        {
+            T t;
+
+            if (byName.TryGetValue(name, out t))
+                return t;
+
+            if (!locked)
+                return Add(MakeNew(name));
+
+            return null;
+        }
+    	
+        /// <summary>
+        /// Adds the IdName subclass to the map. 
+        /// </summary>
+        /// <param name="t">the IdName subclass to add.</param>
+        /// <returns>the IdName from the map</returns>
+        /// Exception:
+        ///             throws Exception (state) if there is a collision with id or name, or a collision with 
+        ///             id and name where they are not associated with the same object.
+        public T Add( T t ) 
+        {
+            if ( locked )
+                throw new Exception( "state exception -- locked" );
+
+            if ( byId.ContainsKey( t.Id ) )
+            {
+                if ( ( t.Name == "msg" ) || ( t.Name == "result" ) )
+                    return t;
+
+                throw new ArgumentException( "id collision" );
+            }
+
+            if ( byName.ContainsKey( t.Name ) )
+            {
+                if ( ( t.Name == "msg" ) || ( t.Name == "result" ) )
+                    return t;
+            
+                throw new ArgumentException( "name collision" );
+            }
+            byId.Add ( t.Id, t);  
+            byName.Add(t.Name, t);
+            return t;
+        }
+
+        /// <summary>
+        /// Adds all the IdNames to this IdNameMap
+        /// </summary>
+        /// <param name="ts"></param>
+        public void AddAll( IdNameMap<T> ts )
+        {
+            if ( locked )
+                throw new Exception( "locked" );
+
+            foreach ( T t in ts.byId.Values )
+                Add( t );
+        }
+
+        /// <summary></summary>
+        /// <returns>a snapshot collection of all the values.</returns>
+        public List<T> Values() 
+        {
+            return new List<T>( byId.Values );
+        }
+
+        /// <summary>
+        /// Locks the map, preventing further changes
+        /// </summary>
+        public void Lock()
+        {
+            locked = true;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the number of values in the map</returns>
+        public int Size()
+        {
+            return byId.Count;
+        }
+
+        /// <summary>Makes a new subclass of IdName to put in this map.</summary>
+        /// <param name="name">name the name of the new subclass of IdName.</param>
+        /// <returns>a newly constructed subclass of IdName to put in this map.</returns>
+        abstract public T MakeNew( String name );
+
+        private Dictionary<int, T> byId = new Dictionary<int, T>();
+
+        private Dictionary<String, T> byName = new Dictionary<String, T>();
+
+        private Boolean locked;
+}
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/ImportExportHelper.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/ImportExportHelper.cs
new file mode 100644
index 0000000..c2478b8
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/ImportExportHelper.cs
@@ -0,0 +1,94 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+    /// <summary>
+    /// class used to implement ValueFactory based import / export code
+    /// for service defined types.
+    /// </summary>
+    public class ImportExportHelper
+    {
+        protected ImportExportHelper()
+        {
+            ev = delegate(ValueFactory vf, Object value)
+            {
+                throw new NotImplementedException("must override ExportValue method");
+            };
+            iv = delegate(StructValue sv)
+            {
+                throw new NotImplementedException("must override ImportValue method");
+            };
+        }
+
+        public ImportExportHelper( ExportValueDelegate ev, ImportValueDelegate iv )
+        {
+            if (ev == null)
+                throw new ArgumentNullException("ev == null");
+
+            if (iv == null)
+                throw new ArgumentNullException("iv == null");
+
+            this.ev = ev;
+            this.iv = iv;
+        }
+
+        private readonly ExportValueDelegate ev;
+
+        private readonly ImportValueDelegate iv;
+
+        /// <summary>
+        /// Exports a value by creating an equivalent StructValue.
+        /// </summary>
+        /// <param name="vf">the value factory used to export.</param>
+        /// <param name="value">a service defined type to export.</param>
+        /// <returns>a StructValue representing the exported value.</returns>
+        public virtual StructValue ExportValue( ValueFactory vf, Object value )
+        {
+            return ev( vf, value );
+        }
+
+        /// <summary>
+        /// Imports a value from an equivalent StructValue.
+        /// </summary>
+        /// <param name="sv">a StructValue representing the exported value.</param>
+        /// <returns>a service defined type.</returns>
+        public virtual Object ImportValue( StructValue sv )
+        {
+            return iv( sv );
+        }
+
+        /// <summary>
+        /// Exports a value by creating an equivalent StructValue.
+        /// </summary>
+        /// <param name="vf">the value factory to use for export.</param>
+        /// <param name="value">a service defined type to export.</param>
+        /// <returns>a StructValue representing the exported value.</returns>
+        public delegate StructValue ExportValueDelegate(ValueFactory vf, Object value);
+
+        /// <summary>
+        /// Imports a value from an equivalent StructValue.
+        /// </summary>
+        /// <param name="sv">a StructValue representing the exported value.</param>
+        /// <returns>a service defined type.</returns>
+        public delegate Object ImportValueDelegate( StructValue sv );
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/Message.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/Message.cs
new file mode 100644
index 0000000..4525b9a
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/Message.cs
@@ -0,0 +1,106 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+    ///<summary> A message is modeled as a command and some argments. The command is an arbitrary
+    /// integer value, and the arguments are key / value pairs, where the key is an arbitrary integer 
+    /// value and the value is any one of the standard C# objects, an ArrayValue, a StructValue, or any type
+    /// which may be serialized by the ValueFactory.</summary>
+    public sealed class Message : StructValue
+    {
+        ///<summary>Constructs the Message.</summary>
+        ///<param name="type">type of the message (command).</param> 
+        ///<param name="vf"> vf the value factory.</param>
+        public Message(XType type, ValueFactory vf)
+            : this(type, vf, 0)
+        {
+            // nothing to do.
+        }
+
+        ///<summary>Constructs the Message.</summary>
+        ///<param name="type">type of the message (command).</param> 
+        ///<param name="vf">vf the value factory.</param>
+        ///<param name="length"> the expected number of name/value pairs</param>
+        public Message(XType type, ValueFactory vf, int length)
+            : base(type, vf, length)
+        {
+            this.vf = vf;
+        }
+
+        private readonly ValueFactory vf;
+
+        ///<returns>the value factory.</returns>     
+        public ValueFactory Vf
+        {
+            get
+            {
+                return vf;
+            }
+        }
+
+   
+       /// <summary>Creates a message which is a reply to the current message. The current message's value 
+       /// factory is copied to the new message. The message-id of the current message (if any) is copied into 
+       /// the in-reply-to field of the new message.</summary>
+       /// <param name="rType"> rType the type of the reply.</param>
+       /// <returns> a reply message.</returns>       
+        public Message Reply( XType rType )
+        {
+            Message rmsg = new Message( rType, vf );
+            rmsg.InReplyTo = MessageId; //rmsg.InReplyTo(GetMessageId()); changed
+            return rmsg;
+        }
+
+        public Message Reply()
+        {
+            Message rmsg = new Message( GetXType.GetResult(), vf );
+            rmsg.InReplyTo = MessageId;
+            return rmsg;
+        }
+
+        /// <returns>the connection specific unique identifier of this message, or null if there was no 
+        /// such identifier.</returns>
+        public long? MessageId
+        {
+            get
+            {
+                return vf.GetMessageId(this);
+            }
+            set
+            {
+                vf.SetMessageId(this, value);
+            }
+        }
+
+       /// <returns>the message-id of the message that this is a response to. Null if this is an original message 
+       /// or if the original message did not have a message-id.</returns>
+        public long? InReplyTo
+        {
+            get
+            {
+                return vf.GetInReplyTo(this);
+            }
+            set
+            {
+                vf.SetInReplyTo(this, value);
+            }
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/StructValue.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/StructValue.cs
new file mode 100644
index 0000000..9953e10
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/StructValue.cs
@@ -0,0 +1,223 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+
+    ///A typed map of key/value pairs, where the type is a Type, each key is a Field, 
+    ///and each value is of arbitrary type chosen from the basic java types boolean, byte, 
+    ///short, int, long, float, double, String, an array of those, the extended types ArrayValue 
+    ///and StructValue, and specific types supported by ValueFactory. 
+    ///StructValue is not protected against concurrent access.
+    public class StructValue 
+    {
+        ///<summary>Constructs the StructValue with default length.</summary>
+        ///<param name="type">the type of the struct (or the action or event if
+        ///this is a message).</param>
+        ///<param name="vf">the value factory for this struct</param>
+        public StructValue(XType type, ValueFactory vf)
+            : this(type, vf, 0)
+        {
+            // nothing to do.
+        }
+
+        ///<summary>Constructs the StructValue.</summary>
+        ///<param name="type">the type of the struct (or the action or event if
+        ///this is a message).</param>
+        ///<param name="length">the expected number of name/value pairs.</param>
+        public StructValue(XType type, ValueFactory vf, int length)
+        {
+            if (type == null)
+                throw new ArgumentNullException("type == null");
+
+            if (vf == null)
+                throw new ArgumentNullException("vf == null");
+
+            this.type = type;
+            this.fields = new Dictionary<Field, Object>(length > 0 ? (length * 4 + 2) / 3 : DEFAULT_SIZE);
+            this.level = vf.GetLevel();
+        }
+
+        private const int DEFAULT_SIZE = 8;
+
+        private readonly XType type;
+
+        private readonly Dictionary<Field, Object> fields;
+
+        private readonly Validator.Level level;
+
+        /// <summary>
+        /// The struct type, or message action or event.
+        /// </summary>
+        public XType GetXType
+        {
+            get
+            {
+                return type;
+            }
+        }
+
+        /// <summary>
+        /// The validation level.
+        /// </summary>
+        public Validator.Level Level
+        {
+            get
+            {
+                return level;
+            }
+        }
+
+        /// <summary>Compares the type of this struct to another type.</summary>
+        /// <param name="otherType">otherType the type to compare this type to.</param>
+        /// <returns>true if this struct is of the specified type.</returns>
+        public bool IsType(XType otherType)
+        {
+            return type.Equals(otherType);
+        }
+
+        /// <summary>Checks a struct for having the expected type.</summary>
+        /// <param name="expectedType">expectedType the expected type of this struct.</param>
+        /// Exception:
+        ///         throws IllegalArgumentException if the type is not as expected.
+        public void CheckType(XType expectedType)
+        {
+            if(!IsType(expectedType))
+                throw new ArgumentException();
+        }
+
+        public Dictionary<Field, Object>.Enumerator GetEnumerator()
+        {
+            return fields.GetEnumerator();
+        }
+
+        public Dictionary<Field, Object>.KeyCollection Keys
+        {
+            get
+            {
+                return fields.Keys;
+            }
+        }
+
+        public bool ContainsKey(Field key)
+        {
+            return fields.ContainsKey(key);
+        }
+
+        /// <summary>Defined to get the Object return type</summary>
+        /// <param name="key"></param>
+        /// <returns></returns>
+        public Object Get(Field key)
+        {
+            object value;
+            return fields.TryGetValue(key, out value) ? value : null;
+        }
+      
+        /// <summary>
+        /// Overriding Dictionary's Add(key, value) function
+        /// </summary>
+        /// <param name="key"></param>
+        /// <param name="value"></param>
+        public void Add(Field key, Object value)
+        {
+            if (value == null)
+            {
+                fields.Remove(key);
+                return;
+            }
+
+            if (level != Validator.Level.NONE)
+            {
+                Validator v = type.GetValidator(key);
+
+                if (v == null && level == Validator.Level.FULL)
+                    throw new ArgumentException(String.Format(
+                        "validator missing for type {0} field {1}", type, key));
+
+                if (v != null && !v.Validate(value))
+                    throw new ArgumentException(String.Format(
+                        "validator {0} failed for type {1} field {2} : value {3}",
+                        v, type, key, value));
+            }
+
+            fields[key] = value;
+        }
+
+        public Object this[Field key]
+        {
+            get
+            {
+                return Get(key);
+            }
+            set
+            {
+                Add(key, value);
+            }
+        }
+
+        public void Remove(Field key)
+        {
+            fields.Remove(key);
+        }
+
+        public int Count
+        {
+            get
+            {
+                return fields.Count;
+            }
+        }
+
+        /// Override
+        public override string ToString()
+        {
+            return string.Format( "{0}: {1}", type, PrintElementsOfMap() );
+        }
+
+        /// <summary>
+        /// Utility function to print the elements of a 
+        /// map like the way Java does (for hashmap). 
+        /// </summary>
+        /// <returns></returns>
+        private string PrintElementsOfMap()
+        {
+            StringBuilder sb = new StringBuilder();
+            sb.Append( "{" );
+            int i = 0;
+            foreach ( KeyValuePair<Field, Object> me in this )
+            {
+                if ( i != 0 )
+                    sb.Append( ", " );
+                sb.Append( me.Key );
+                sb.Append( "=" );
+                sb.Append( me.Value );
+                i++;
+            }
+
+            sb.Append( "}" );
+
+            return sb.ToString();
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/TypeMap.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/TypeMap.cs
new file mode 100644
index 0000000..0d77445
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/TypeMap.cs
@@ -0,0 +1,32 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+    /// <summary>
+    /// TypeMap is an IdNameMap for Type
+    /// </summary>
+    public class TypeMap : IdNameMap<XType>
+    {
+        public override XType MakeNew( string name )
+        {
+            return new XType( name );
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/Validator.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/Validator.cs
new file mode 100644
index 0000000..63fe985
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/Validator.cs
@@ -0,0 +1,85 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+    /// <summary>
+    /// Validate values put into messages
+    /// </summary>
+    abstract public class Validator
+    {
+        /// <summary>
+        /// The validation level.
+        /// </summary>
+        public enum Level
+        {
+            /// <summary>
+            /// No validation on put or output.
+            /// </summary>
+            NONE,
+            /// <summary>
+            /// Validation on put or output if validator defined.
+            /// </summary>
+            MISSING_OK,
+            /// <summary>
+            /// Like MISSING_OK, but fail if no validator defined.
+            /// </summary>
+            FULL
+        }
+
+        /// <summary>
+        /// The maximum number of dimensions for arrays
+        /// </summary>
+        public const int MAX_NDIMS = 9;
+
+        /// <summary>
+        /// The maximum number of validators to cache per type.
+        /// </summary>
+        protected const int MAX_CACHED = 4;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>for an array type, return a validator for an element of
+        /// the array (which might be a scalar or another array element).</returns>
+        abstract public Validator ElementValidator();
+
+        /// <summary>
+        /// Checks the value for being valid. If the value is valid
+        /// by this validator, return true.
+        /// </summary>
+        /// <param name="value">the value to be validated.</param>
+        /// <returns>true if the value is valid by any validator in the
+        /// chain, or false if all reject it.</returns>
+        abstract public bool Validate( Object value );
+
+       
+
+        /// <summary>
+        /// </summary>
+        /// <param name="value"></param>
+	    /// <returns> return the appropriate value given the input value and this
+	    /// validator's sensibility about what it should be really (e.g.,
+	    /// input Byte but output Long. </returns>
+	 
+        abstract public Object ValidateValue(Object value);
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/ValueFactory.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/ValueFactory.cs
new file mode 100644
index 0000000..681cc2c
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/ValueFactory.cs
@@ -0,0 +1,170 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{ 
+    /// <summary>Interface which defines the value factory which helps
+    ///  the idl compiler serialize and deserialize messages, convert values, etc.</summary>
+    public interface ValueFactory 
+    {
+        //////////
+        // XType //
+        //////////
+
+        /// <summary>Translates a type id into the appropriate XType object.
+        /// If the type does not exist, and if dynamic typing is enabled,
+        /// adds it to the dynamic types.</summary>
+        ///<param> id a type id.</param>
+        /// <returns> id translated into the appropriate XType.</returns>  
+        XType GetType(int id);
+
+        /// <summary>Translates a type name into the appropriate XType object.
+        /// If the type does not exist, and if dynamic typing is enabled,
+        /// adds it to the dynamic types.</summary>
+        /// <param>name a type name.</param>
+        /// <returns> name translated into the appropriate XType.</returns>
+        
+        XType GetType(string name);
+
+        /// <summary>
+        /// Adds the type if it doesn't already exist. Use this to dynamically add
+        /// types to a ValueFactory. The type is per instance of the ValueFactory,
+        /// not global. Not available if dynamic typing is locked.
+        /// </summary>
+        /// <param name="type"></param>
+        void AddType(XType type);
+
+        /// <summary>
+        /// Locks the dynamic typing so that no new types may be created by addType
+        /// or getType.
+        /// </summary>
+        void LockDynamicTypes();
+
+        /// <summary>
+        /// Unlocks the dynamic typing so that new types may be created by addType
+        /// or getType.
+        /// </summary>
+        void UnlockDynamicTypes();
+
+        /// <returns> a collection of all the types.</returns>
+        ICollection<XType> GetTypes();
+
+        /////////////////////
+        // STRING ENCODING //
+        /////////////////////
+
+        ///<returns> the encoding to use for strings.
+        Encoding GetStringEncoding();
+
+        ////////////////
+        // MESSAGE ID //
+        ////////////////
+
+        /// <param name="msg">msg the message whose well-known message-id field is to be returned.</param>
+        /// <returns>the value of the well-known message-id field. This is a unique identifier 
+        /// for this message on a particular transport during a particular session. If there is no well-known 
+        /// message-id field defined, or if the message-id field has not been set, then return null.</returns>
+
+        long? GetMessageId(Message msg);
+        
+        /// <summary> Sets the value of the well-known message-id field. This is a unique identifier 
+        /// for this message on a particular transport during a particular session. If there is no 
+        /// well-known message-id field defined then nothing is done. If msgid is null, then the field is cleared.
+        /// </summary>
+        /// <param>msg the message whose well-known message-id field is to be set.</param> 
+        /// <param>msgid the value of the well-known message-id field.</param> 
+        
+        void SetMessageId(Message msg, long? msgid);
+
+        /// <summary>
+        /// Gets well-known message field for message id.
+        /// </summary>
+        /// <returns>well-known message field for message id.</returns>
+        Field Get_mf__messageId();
+
+        /////////////////
+        // IN REPLY TO //
+        /////////////////
+
+        /// <returns>the value of the in-reply-to field, or null if there is none or if there is no such field defined.
+        /// </returns>
+        ///<param> msg the message whose well-known in-reply-to field is to be returned.</param>
+
+        long? GetInReplyTo(Message msg);
+
+        /// <param>msg the message whose well-known in-reply-to field is to be set.</param>
+        /// <param>msgid the value of the well-known in-reply-to field. If there is no well-known 
+        /// in-reply-to field defined then nothing is done. If msgid is null, then the field is cleared.</param>
+        /// </summary> 
+        
+        void SetInReplyTo(Message msg, long? msgid);
+
+        /// <summary>
+        /// Gets well-known message field for in reply to.
+        /// </summary>
+        /// <returns>well-known message field for in reply to.</returns>
+        Field Get_mf__inReplyTo();
+
+        //////////////////////
+        // VALUE CONVERSION //
+        //////////////////////
+
+        /// <summary>Converts a value to a struct value representation to be exported to a tagged data output.</summary>
+        /// <param>value a custom type defined by a service, or a well-known standard type (e.g., date).</param> 
+        /// <returns> a struct value representing the value.</returns>
+        /// <throws>UnsupportedOperationException if the type cannot be exported.</throws> 
+        
+        StructValue ExportCustomValue(object value);
+
+        /// <summary>Converts a struct value imported from a tagged data input to a normal type.</summary>
+        /// <param>sv a struct value representation of a custom type, or a well known standard type.</param> 
+        /// <returns> a custom type, or a well known standard type.</returns>
+        /// <throws> UnsupportedOperationException if the type cannot be imported.</throws>
+        
+        Object ImportCustomValue(StructValue sv);
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="c">the class of a custom value.</param>
+        /// <returns>the struct type of a custom value class.</returns>
+        XType GetCustomStructType( Type c );
+
+        ///<summary></summary>
+        /// <returns>well-known message type for exception thrown by one-way message</returns>	
+        XType get_mt__exception();
+
+        /// <summary>
+        /// Gets the put / write validation level.
+        /// </summary>
+        /// <returns>the put / write validation level</returns>
+        Validator.Level GetLevel();
+
+        /// <summary>
+        /// Sets the put / write validation level.
+        /// </summary>
+        /// <param name="level">the new put / write validation level</param>
+        /// <returns>the old put / write validation level</returns>
+        Validator.Level SetLevel(Validator.Level level);
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/XType.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/XType.cs
new file mode 100644
index 0000000..da026fc
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Msg/XType.cs
@@ -0,0 +1,341 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+    /// <summary>
+    /// Type denotes the type of a struct or message. When used with a
+    /// message it typically denotes an action or event.
+    /// </summary>
+    public class XType : IdName
+    {
+        /// <summary>Constructs the Type.</summary>
+        /// <param name="id">id of the type.</param>
+        /// <param name="name">name of the type.</param>
+        public XType( int id, String name )
+            : base( id, name )
+        {
+            // nothing else.
+        }
+
+        /// <summary>Constructs the Type, computing the appropriate value for the id.</summary>
+        /// <param name="name">name the name of the type.</param>
+        public XType( String name )
+            : base( name )
+        {
+            // nothing else.
+        }
+
+        public Validator GetValidator( Field key )
+        {
+            Validator v;
+            return validators.TryGetValue(key, out v) ? v : null;
+        }
+
+        private readonly FieldMap fieldMap = new FieldMap();
+
+        /// <summary>
+        /// Adds the validator to the chain for this key.
+        /// </summary>
+        /// <param name="key"></param>
+        /// <param name="vldtr"></param>
+        public void PutValidator( Field key, Validator vldtr )
+        {
+            CheckNotLocked();
+
+            if ( vldtr == null )
+                return;
+
+            if ( fieldMap.Get( key.Id ) == null )
+                AddField( key );
+
+            Validator v;
+            if (validators.TryGetValue(key, out v))
+                validators[key] = new ComboValidator(v, vldtr);
+            else
+                validators[key] = vldtr;
+        }
+
+        /// <summary>
+        /// Removes the validator chain for this key
+        /// </summary>
+        /// <param name="key"></param>
+        public void ClearValidator( Field key )
+        {
+            CheckNotLocked();
+            validators.Remove( key );
+        }
+
+        public Dictionary<Field, Validator> validators = new Dictionary<Field, Validator>();
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the result type of this message type</returns>
+        public XType GetResult()
+        {
+            return rType;
+        }
+
+        public void SetResult( XType rType )
+        {
+            CheckNotLocked();
+            this.rType = rType;
+        }
+
+        private XType rType;
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the associated import / export helper</returns>
+        public ImportExportHelper GetImportExportHelper()
+        {
+            return helper;
+        }
+
+        /// <summary>
+        /// Sets the associated import / export helper.
+        /// </summary>
+        /// <param name="helper"></param>
+        public void SetImportExportHelper( ImportExportHelper helper )
+        {
+            CheckNotLocked();
+            this.helper = helper;
+        }
+
+        private ImportExportHelper helper;
+
+       /// <summary>
+       /// 
+       /// </summary>
+        /// <returns>the associated component type for an array of this type</returns>
+
+        public Type GetComponentType()
+	    {
+            return componentType;
+	    }
+
+        /// <summary>
+        /// Sets the associated component type for an array of this type.
+	    /// This type is not used when de-serializing the array components,
+	    /// just when allocating the array itself.
+        /// </summary>
+        /// <param name="type"></param>
+
+        public void SetComponentType(Type type)
+        {
+            CheckNotLocked();
+            this.componentType = type;
+        }
+
+        private Type componentType;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>an object to help dispatch the received message</returns>
+        public Object GetStubHelper()
+        {
+            return stubHelper;
+        }
+
+        /// <summary>
+        /// Sets an object to help the stub dispatch the received message
+        /// </summary>
+        /// <param name="stubHelper"></param>
+        public void SetStubHelper( Object stubHelper )
+        {
+            // CheckNotLocked(); called from stub and not from value factory.
+            if (this.stubHelper != null)
+                throw new Exception("this.stubHelper != null");
+            this.stubHelper = stubHelper;
+        }
+
+        private Object stubHelper;
+
+
+        ///<summary>Locks the fields for this type.</summary>
+        public void Lock()
+        {
+            locked = true;
+            fieldMap.Lock();
+        }
+
+        private void CheckNotLocked()
+        {
+            if (locked)
+                throw new Exception("locked");
+        }
+
+        private bool locked;
+
+        
+        ///<summary>Adds a field to the set of fields.</summary>
+        ///<param name="field"> A field to all </param>
+        ///<returns>Returns the argument. If there is a collision with
+        /// an id and name, both associated with the same field,
+        /// then that field is returned instead of the argument </returns>
+        /// <Exception cref="ArgumentException">hrows IllegalArgumentException if there is a
+        /// collision in the id or name, or both id and name when not associated 
+        /// with the same field.</Exception>
+        public Field AddField( Field field )
+        {
+            return fieldMap.Add( field );
+        }
+
+        ///<summary>Translates a field id into the appropriate Field object.</summary>
+        ///<param name="id">field id</param>
+        ///<returns>id translated into the appropriate Field.</returns>
+        public Field GetField( int id )
+        {
+            return fieldMap.Get( id );
+        }
+
+       
+        ///<summary>Translates a field name into the appropriate Field.</summary>
+        ///<param name="name">A field name</param>
+        ///<returns>name translated into the appropriate Field.</returns>
+        public Field GetField( string name )
+        {
+            return fieldMap.Get( name );
+        }
+
+        ///<returns>a set of all the fields.</returns>
+        public List<Field> GetFields()
+        {
+            return fieldMap.Values();
+        }
+
+        /// <summary>
+        /// Every type ( => message) carries a timeout
+        /// </summary>
+        private int timeout;
+
+        public int Timeout
+        {
+            get
+            {
+                return timeout;
+            }
+            set
+            {
+                CheckNotLocked();
+                timeout = value;
+            }
+        }
+
+        /// <summary>
+        /// Field containing result value
+        /// </summary>
+        private Field responseField;
+
+        public Field ResponseField
+        {
+            get
+            {
+                return responseField;
+            }
+            set
+            {
+                CheckNotLocked();
+                responseField = value;
+            }
+        }
+
+        ///<summary>Checks whether this type is assignment compatible with other. This
+        ///means that other is a subclass of this.</summary>
+        ///<param name="other"></param>
+        ///<returns>true if this type is assignable from other</returns>
+        
+        public bool IsAssignableFrom( XType other )
+        {
+            return other != null && ( this.Equals( other ) || IsAssignableFrom( other.SuperType() ) );
+        }
+
+        public void CheckIsAssignableFrom( XType other )
+        {
+            if ( !IsAssignableFrom( other ) )
+                throw new ArgumentOutOfRangeException();
+        }
+
+        public XType SuperType()
+        {
+            return superType;
+        }
+
+        ///<summary>Sets the super type of this type. If struct A extends B, then
+        ///B is the super type of A.</summary>
+        ///<param name="superType"></param>
+        public void SetSuperType( XType superType )
+        {
+            CheckNotLocked();
+            this.superType = superType;
+        }
+
+        private XType superType;
+
+       /// <summary>
+       /// Gets AsyncMode for this Type
+       /// </summary>
+       /// <returns>AsyncMode</returns>
+        public AsyncMode GetAsyncMode()
+        {
+            return asyncMode;
+        }
+
+        /// <summary>
+        /// Sets the AysncMode
+        /// </summary>
+        /// <param name="mode"></param>
+        public void SetAsyncMode(AsyncMode mode)
+        {
+            CheckNotLocked();
+            asyncMode = mode;
+        }
+
+        private AsyncMode asyncMode;
+
+        /// <summary>
+        /// Gets the message direction.
+        /// </summary>
+        /// <returns>the message direction</returns>
+        public Direction GetDirection()
+        {
+            return direction;
+        }
+
+        /// <summary>
+        /// Sets the message direction.
+        /// </summary>
+        /// <param name="direction"></param>
+        public void SetDirection(Direction direction)
+        {
+            CheckNotLocked();
+            this.direction = direction;
+        }
+
+        private Direction direction;
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/AuthExceptionSerializer.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/AuthExceptionSerializer.cs
new file mode 100644
index 0000000..9f29b88
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/AuthExceptionSerializer.cs
@@ -0,0 +1,62 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    public class AuthExceptionSerializer : ImportExportHelper
+    {
+        private const String FIELD_NAME = "msg";
+
+        public static void Init(XType type, Class2TypeMap class2type)
+        {
+            Field field = type.GetField(FIELD_NAME);
+            class2type.Add(typeof(_Etch_AuthException), type);
+            type.SetComponentType(typeof(_Etch_AuthException));
+            type.SetImportExportHelper(new AuthExceptionSerializer(type, field));
+            type.PutValidator(field, Validator_string.Get(0));
+            type.Lock();
+        }
+
+        public AuthExceptionSerializer(XType type, Field field)
+        {
+            this.type = type;
+            this.field = field;
+        }
+
+        private readonly XType type;
+
+        private readonly Field field;
+
+        public override StructValue ExportValue(ValueFactory vf, Object value)
+        {
+            StructValue sv = new StructValue(type, vf);
+            sv.Add(field, value.ToString());
+            return sv;
+        }
+
+        public override Object ImportValue(StructValue sv)
+        {
+            sv.CheckType(type);
+            return new _Etch_AuthException((String)sv.Get(field));
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Class2TypeMap.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Class2TypeMap.cs
new file mode 100644
index 0000000..3f142b0
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Class2TypeMap.cs
@@ -0,0 +1,101 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    public class Class2TypeMap
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="c"></param>
+        /// <returns>the Type for the specified class, or null</returns>
+        public XType Get( Type c )
+        {
+            try
+            {
+                return c2t[ c ];
+            }
+            catch ( KeyNotFoundException )
+            {
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// Adds a map entry from c to t
+        /// </summary>
+        /// <param name="c"></param>
+        /// <param name="t"></param>
+        public void Add( Type c, XType t )
+        {
+            if ( locked )
+                throw new Exception( "locked" );
+
+            XType x;
+            try
+            {
+                x = c2t[ c ];
+            }
+            catch ( KeyNotFoundException )
+            {
+                x = null;
+            }
+
+            if ( x != null )
+            {
+                if ( !x.Equals( t ) )
+                    throw new ArgumentException( String.Format( "type {0} : class {1} is already mapped to type {2}", t, c, x ) );
+                return;
+            }
+            c2t.Add( c, t );
+        }
+
+        /// <summary>
+        /// Adds all the mappings from other to this
+        /// </summary>
+        /// <param name="other"></param>
+        public void AddAll( Class2TypeMap other )
+        {
+            if ( locked )
+                throw new Exception( "locked" );
+
+            foreach ( KeyValuePair<Type, XType> me in other.c2t )
+            {
+                Add( me.Key, me.Value );
+            }
+        }
+
+        /// <summary>
+        /// Locks the map, disallowing any more changes
+        /// </summary>
+        public void Lock()
+        {
+            locked = true;
+        }
+
+        private readonly Dictionary<Type, XType> c2t = new Dictionary<Type, XType>();
+
+        private Boolean locked;
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/DefaultServerFactory.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/DefaultServerFactory.cs
new file mode 100644
index 0000000..dbfdbda
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/DefaultServerFactory.cs
@@ -0,0 +1,103 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Transport;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    abstract public class DefaultServerFactory : ServerFactory
+    {
+        protected DefaultServerFactory(Transport<ServerFactory> listener, object implFactory)
+        {
+            this.listener = listener;
+            if (implFactory is Session)
+                SetSession((Session)implFactory);
+            listener.SetSession(this);
+        }
+
+        private readonly Transport<ServerFactory> listener;
+
+        public Object SessionQuery(Object query)
+        {
+            if (session != null)
+                return session.SessionQuery(query);
+
+            throw new NotSupportedException("unknown query " + query);
+        }
+
+        public void SessionControl(Object control, Object value)
+        {
+            if (session != null)
+            {
+                session.SessionControl(control, value);
+                return;
+            }
+
+            throw new NotSupportedException("unknown control " + control);
+        }
+
+        public void SessionNotify(Object evnt)
+        {
+            if (session != null)
+                session.SessionNotify(evnt);
+        }
+
+        #region Transport Members
+
+        public Session GetSession()
+        {
+            return session;
+        }
+
+        public void SetSession(Session session)
+        {
+            this.session = session;
+        }
+
+        private Session session;
+
+        public object TransportQuery(object query)
+        {
+            return listener.TransportQuery(query);
+        }
+
+        public void TransportControl(object control, object value)
+        {
+            listener.TransportControl(control, value);
+        }
+
+        public void TransportNotify(object eventObj)
+        {
+            listener.TransportNotify(eventObj);
+        }
+
+        #endregion
+
+        #region ServerFactory Members
+
+        abstract public void NewServer(TransportMessage transport, string uri, Resources resources);
+
+        abstract public ValueFactory NewValueFactory(string uri);
+
+        #endregion
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/DefaultValueFactory.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/DefaultValueFactory.cs
new file mode 100644
index 0000000..6d08ec2
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/DefaultValueFactory.cs
@@ -0,0 +1,395 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+
+    /// <summary>Default implementation of ValueFactory which provides some dynamic type and field support, as well 
+    /// as standard value conversions and import and export.</summary>
+    public class DefaultValueFactory : ValueFactory
+    {
+        private const String ETCH_RUNTIME_EXCEPTION_TYPE_NAME = "_Etch_RuntimeException";
+
+        private const String ETCH_LIST_TYPE_NAME = "_Etch_List";
+
+	    private const String ETCH_MAP_TYPE_NAME = "_Etch_Map";
+
+	    private const String ETCH_SET_TYPE_NAME = "_Etch_Set";
+
+	    private const String ETCH_DATETIME_TYPE_NAME = "_Etch_Datetime";
+
+	    private const String ETCH_AUTH_EXCEPTION_TYPE_NAME = "_Etch_AuthException";
+
+	    private const String ETCH_EXCEPTION_MESSAGE_NAME = "_exception";
+
+	    private const String MSG_FIELD_NAME = "msg";
+
+	    private const String MESSAGE_ID_FIELD_NAME = "_messageId";
+
+	    private const String IN_REPLY_TO_FIELD_NAME = "_inReplyTo";
+
+        private const String RESULT_FIELD_NAME = "result";
+     
+
+        public static void Init( TypeMap types, Class2TypeMap class2type )
+        {
+            RuntimeExceptionSerializer.Init(
+             types.Get(ETCH_RUNTIME_EXCEPTION_TYPE_NAME), class2type);
+
+            ListSerializer.Init(
+                types.Get(ETCH_LIST_TYPE_NAME), class2type);
+
+            MapSerializer.Init(
+                types.Get(ETCH_MAP_TYPE_NAME), class2type);
+
+        /*    SetSerializer.Init(
+                types.Get(ETCH_SET_TYPE_NAME), class2type); */
+
+            DateSerializer.Init(
+                types.Get(ETCH_DATETIME_TYPE_NAME), class2type);
+
+            AuthExceptionSerializer.Init(
+                types.Get(ETCH_AUTH_EXCEPTION_TYPE_NAME), class2type);
+         
+            XType t3 = types.Get(ETCH_EXCEPTION_MESSAGE_NAME);
+            t3.PutValidator(_mf_result, Validator_RuntimeException.Get());
+            t3.PutValidator(_mf__messageId, Validator_long.Get(0));
+            t3.PutValidator(_mf__inReplyTo, Validator_long.Get(0));
+        }
+
+        /// <summary>The msg field of the standard unchecked exception.</summary>
+        public readonly static Field _mf_msg = new Field(MSG_FIELD_NAME);
+
+        /// <summary>The well-known _messageId field.</summary>
+        public readonly static Field _mf__messageId = new Field(MESSAGE_ID_FIELD_NAME);
+
+        /// <summary>The well-known _inReplyTo field. </summary>
+        public readonly static Field _mf__inReplyTo = new Field(IN_REPLY_TO_FIELD_NAME);
+
+        /// <summary> The well-known result field </summary>
+        public readonly static Field _mf_result = new Field(RESULT_FIELD_NAME);
+
+        private readonly TypeMap types;
+
+        private readonly TypeMap dynamicTypes = new TypeMap();
+
+	    private readonly Class2TypeMap class2type;
+	
+	    private readonly XType _mt__Etch_RuntimeException;
+	
+	    private readonly XType _mt__Etch_AuthException;
+	
+	    private readonly XType _mt__exception;
+
+        private readonly XType _mt__Etch_List;
+	
+	    private readonly XType _mt__Etch_Map;
+	
+	    private readonly XType _mt__Etch_Set;
+	
+	    private readonly XType _mt__Etch_Datetime;
+	
+
+       /// <summary>
+        /// Constructs the DefaultValueFactory.
+       /// </summary>
+       /// <param name="uri"></param>
+       /// <param name="types"></param>
+       /// <param name="class2type"></param>
+        public DefaultValueFactory(String uri, TypeMap types, Class2TypeMap class2type)
+        {
+            URL u = new URL(uri);
+            
+            String s = u.GetTerm("DefaultValueFactory.level", "FULL");
+            level = (Validator.Level) Enum.Parse(typeof(Validator.Level), s);
+
+            this.types = types;
+            this.class2type = class2type;
+
+            _mt__Etch_RuntimeException = types.Get(ETCH_RUNTIME_EXCEPTION_TYPE_NAME);
+            _mt__Etch_AuthException = types.Get(ETCH_AUTH_EXCEPTION_TYPE_NAME);
+            _mt__exception = types.Get(ETCH_EXCEPTION_MESSAGE_NAME);
+            _mt__Etch_List = types.Get(ETCH_LIST_TYPE_NAME);
+            _mt__Etch_Map = types.Get(ETCH_MAP_TYPE_NAME);
+            _mt__Etch_Set = types.Get(ETCH_SET_TYPE_NAME);
+            _mt__Etch_Datetime = types.Get(ETCH_DATETIME_TYPE_NAME);
+        }
+
+        public XType get_mt__Etch_RuntimeException()
+	    {
+		    return _mt__Etch_RuntimeException;
+	    }
+	
+	    public XType get_mt__Etch_AuthException()
+	    {
+		    return _mt__Etch_AuthException;
+	    }
+	
+	    public  XType get_mt__exception()
+	    {
+		    return _mt__exception;
+	    }
+
+        public XType Get_mt__Etch_List()
+	    {
+		    return _mt__Etch_List;
+	    }
+	
+	    public XType Get_mt__Etch_Map()
+	    {
+		    return _mt__Etch_Map;
+	    }
+	
+	    public XType Get_mt__Etch_Set()
+	    {
+		    return _mt__Etch_Set;
+	    }
+	
+	    public XType Get_mt__Etch_Datetime()
+	    {
+	    	return _mt__Etch_Datetime;
+	    }
+
+        protected void addMixin(ValueFactory vf)
+        {
+            ValueFactory[] newMixins = new ValueFactory[mixins.Length + 1];
+            System.Array.Copy(mixins,newMixins,mixins.Length);
+            newMixins[mixins.Length] = vf;
+            mixins = newMixins;
+        }
+
+        private ValueFactory[] mixins = { };
+
+     
+
+        /////////////////////
+        // STRING ENCODING //
+        /////////////////////
+
+        public Encoding GetStringEncoding()
+        {
+            return Encoding.UTF8;
+        }
+
+        ////////////////
+        // MESSAGE ID //
+        ////////////////
+
+        public long? GetMessageId(Message msg)
+        {
+            return (long?)(msg.Get(_mf__messageId));
+        }
+
+        public void SetMessageId(Message msg, long? msgid)
+        {
+            msg[_mf__messageId] = msgid;
+        }
+
+        public Field Get_mf__messageId()
+        {
+            return _mf__messageId;
+        }
+
+        /////////////////
+        // IN REPLY TO //
+        /////////////////
+
+        public long? GetInReplyTo(Message msg)
+        {
+            return (long?)(msg.Get(_mf__inReplyTo));
+        }
+
+        public void SetInReplyTo(Message msg, long? msgid)
+        {
+            msg[_mf__inReplyTo] = msgid;
+        }
+
+        public Field Get_mf__inReplyTo()
+        {
+            return _mf__inReplyTo;
+        }
+
+        //////////////////////
+        // VALUE CONVERSION //
+        //////////////////////
+
+       
+
+        public Object ImportCustomValue( StructValue sv )
+        {
+            ImportExportHelper helper = sv.GetXType.GetImportExportHelper();
+
+            if ( helper == null )
+                return null;
+
+            return helper.ImportValue( sv );
+        }
+
+       
+
+        #region ValueFactory members
+
+        public StructValue ExportCustomValue( Object value )
+        {
+            Type clss = value.GetType();
+            XType type;
+            try
+            {
+                type = GetCustomStructType(value.GetType());
+            }
+            catch (KeyNotFoundException)
+            {
+                type = null;
+            }
+
+            if (type == null && clss == typeof(StructValue) )
+		    {
+			    StructValue struct1 = (StructValue) value;
+		        type = struct1.GetXType;
+		    }
+
+            if (type == null)
+                //       if (value is Exception)
+                if (typeof(Exception).IsAssignableFrom(clss))
+                    type = _mt__Etch_RuntimeException;
+                else if (typeof(IList).IsAssignableFrom(clss))
+                    type = _mt__Etch_List;
+                else if (typeof(IDictionary).IsAssignableFrom(clss))
+                    type = _mt__Etch_Map;
+                // Need to add set, but in 2.0 there is no set so just use keys of IDictionary, 
+                else
+                    return null;
+		
+		    ImportExportHelper helper = type.GetImportExportHelper();
+		
+		    if (helper == null)
+			    return null;
+		
+		    return helper.ExportValue( this, value );
+        }
+
+        public XType GetCustomStructType( Type t )
+        {
+            XType type = class2type.Get( t );
+		    if (type != null)
+			    return type;
+		
+		    foreach (ValueFactory vf in mixins)
+			    if ((type = vf.GetCustomStructType( t )) != null)
+				    return type;
+		
+		    return null;
+           
+        }
+
+        public XType GetType( int id )
+        {
+            XType type = types.Get(id);
+            if (type != null)
+                return type;
+
+            foreach (ValueFactory vf in mixins)
+                if ((type = vf.GetType(id)) != null)
+                    return type;
+
+            lock (dynamicTypes)
+            {
+                return dynamicTypes.Get(id);
+            }
+        }
+
+        public XType GetType( string name )
+        {
+            XType type = types.Get(name);
+            if (type != null)
+                return type;
+
+            foreach (ValueFactory vf in mixins)
+                if ((type = vf.GetType(name)) != null)
+                    return type;
+
+            lock (dynamicTypes)
+            {
+                return dynamicTypes.Get(name);
+            }
+        }
+
+        public void AddType(XType type)
+        {
+            lock (dynamicTypes)
+            {
+                dynamicTypes.Add(type);
+            }
+        }
+
+        public  ICollection<XType> GetTypes()
+        {
+            ICollection<XType> values = types.Values();
+
+            foreach (ValueFactory vf in mixins)
+                foreach (XType x in vf.GetTypes())
+                    if (!values.Contains(x))
+                        values.Add(x);
+
+            lock (dynamicTypes)
+            {
+                foreach (XType x in dynamicTypes.Values())
+                    if (!values.Contains(x))
+                        values.Add(x);
+            }
+
+            return values;
+        }
+
+        #endregion
+
+
+        public void LockDynamicTypes()
+        {
+            dynamicTypes.Lock();
+        }
+
+        public void UnlockDynamicTypes()
+        {
+            // TODO dynamicTypes.Unlock();
+            throw new NotSupportedException("The method or operation is not implemented.");
+        }
+
+        public Validator.Level GetLevel()
+        {
+            return level;
+        }
+
+        public Validator.Level SetLevel(Validator.Level level)
+        {
+            Validator.Level oldLevel = this.level;
+            this.level = level;
+            return oldLevel;
+        }
+
+        private Validator.Level level = Validator.Level.FULL;
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/DeliveryService.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/DeliveryService.cs
new file mode 100644
index 0000000..3983e8e
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/DeliveryService.cs
@@ -0,0 +1,51 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Transport;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support{
+
+    ///<summary>Adapter between remote and message source.</summary>
+    public interface DeliveryService : TransportMessage,SessionMessage
+    {
+	
+        
+
+        /// <summary>
+        /// Sends the message which begins a call sequence.
+        /// </summary>
+        /// <param name="msg">the message to send.</param>
+        /// <returns>a mailbox which can be used to read response</returns>
+        Mailbox BeginCall( Message msg );
+
+        /// <summary>Finishes a call sequence by waiting for the response message.</summary>
+        /// <param name="mb"></param>
+        /// <param name="responseType">responseType the type of the expected response.</param>
+        /// which would contain any result value or thrown exception.</param>
+	    /// <returns>the value of the response field if it isn't an exception.</returns>
+        /// Exception:
+        ///             throws Exception if there is a problem sending or a timeout waiting or if the result 
+        ///             value was an exception.
+        Object EndCall(Mailbox mb, XType responseType );
+
+       
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/DummyValueFactory.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/DummyValueFactory.cs
new file mode 100644
index 0000000..edba23a
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/DummyValueFactory.cs
@@ -0,0 +1,128 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    public class DummyValueFactory : ValueFactory
+    {
+        #region ValueFactory Members
+
+        public XType GetType(int id)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public XType GetType(string name)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public void AddType(XType type)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public void LockDynamicTypes()
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public void UnlockDynamicTypes()
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public ICollection<XType> GetTypes()
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public Encoding GetStringEncoding()
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public long? GetMessageId(Message msg)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public void SetMessageId(Message msg, long? msgid)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public Field Get_mf__messageId()
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public long? GetInReplyTo(Message msg)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public void SetInReplyTo(Message msg, long? msgid)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public Field Get_mf__inReplyTo()
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public StructValue ExportCustomValue(object value)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public object ImportCustomValue(StructValue sv)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public XType GetCustomStructType(Type c)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public XType get_mt__exception()
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public Validator.Level GetLevel()
+        {
+            return Validator.Level.FULL;
+        }
+
+        public Validator.Level SetLevel(Validator.Level level)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        #endregion
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/FreePool.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/FreePool.cs
new file mode 100644
index 0000000..81e9e09
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/FreePool.cs
@@ -0,0 +1,137 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Threading;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// A free implementation of pool
+    /// </summary>
+    public class FreePool : Pool
+    {
+        /// <summary>
+        /// Constructs a FreePool with specified maxSize.
+        /// </summary>
+        /// <param name="maxSize">maximum number of free threads at one time
+        /// after which reject requests. </param>
+        public FreePool( int maxSize )
+        {
+            this.maxSize = maxSize;
+        }
+
+        /// <summary>
+        /// Constructs a FreePool with maxSize 50
+        /// </summary>
+        public FreePool()
+            : this( 50 )
+        { }
+
+        private readonly int maxSize;
+
+        private readonly Dictionary<Thread, Thread> group = new Dictionary<Thread, Thread>();
+
+        private Boolean open = true;
+
+        /// <summary>
+        /// Closes the pool. This just marks the pool as being closed, it doesn't
+        /// actually do anything to the currently running thread. But no more
+        /// threads are allowed to start.
+        /// </summary>
+        public void Close()
+        {
+            open = false;
+        }
+
+        /// <summary>
+        /// Joins each of the threads in this pool until there
+        /// are none left. The pool will be closed first.
+        /// Exception:
+        ///     throws ThreadInterruptedException
+        /// </summary>
+        public void Join()
+        {
+            Close();
+            while (true)
+            {
+                Thread x;
+                lock (group)
+                {
+                    Dictionary<Thread, Thread>.Enumerator e = group.GetEnumerator();
+                    if (!e.MoveNext())
+                        break;
+                    
+                    x = e.Current.Key;
+                    group.Remove(x);
+                }
+                x.Join();
+            }
+        }
+
+        /// <summary>
+        /// Finds the number of active threads in this pool
+        /// </summary>
+        /// <returns>the number of active threads</returns>
+        public int ActiveCount()
+        {
+            return group.Count;
+        }
+
+        #region Pool Members
+
+        [MethodImpl( MethodImplOptions.Synchronized )]
+        public void Run( RunDelegate d1, ExceptionDelegate d2 )
+        {
+            if (!open || ActiveCount() >= maxSize)
+                throw new Exception("free pool thread count exceeded or pool closed");
+
+            Thread t = new Thread(
+                delegate()
+                {
+                    try
+                    {
+                        d1();
+                    }
+                    catch (Exception e)
+                    {
+                        d2(e);
+                    }
+                    finally
+                    {
+                        lock (group)
+                        {
+                            group.Remove(Thread.CurrentThread);
+                        }
+                    }
+                });
+
+            lock (group)
+            {
+                group.Add(t, t);
+            }
+
+            t.Start();
+        }
+
+        #endregion
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Mailbox.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Mailbox.cs
new file mode 100644
index 0000000..9f26adc
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Mailbox.cs
@@ -0,0 +1,113 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>An interface used to deliver responses to a message. Support for the mechanism is somewhat 
+    /// dependent upon properties of the transport and message format.</summary>
+    /// 
+    public interface Mailbox 
+    {
+        /// <returns>the message id of this mailbox.</returns>
+        long GetMessageId();
+
+        /// <returns>the next message to be read from the mailbox, or null if the mailbox is empty and closed. 
+        /// Wait forever for such a message to be delivered.</returns>
+        /// Exception: 
+        ///             throws InterruptedException thread interrupt.
+        Element Read();
+
+       /// <param name="maxDelay">maxDelay the maximum amount of time in milliseconds to wait to read a message 
+       /// from an empty mailbox. 0 means wait forever, -1 means don't wait at all.</param>
+       /// <returns>the message read from the mailbox, or null if the mailbox is empty and closed, or if the time 
+       /// limit was exceeeded.</returns>
+       /// Exception:
+       ///              throws InterruptedException thread interrupt.
+       Element Read(int maxDelay);
+
+       /// <summary>Closes the mailbox so that no more messages can be delivered. Queued messages remain to be read. 
+       /// Reading an empty closed mailbox returns null.</summary>
+       /// <returns> true if this call closed the mailbox (that is, if action was taken), false if the mailbox was already closed. </returns>
+       bool CloseDelivery();
+
+       /// <summary>Closes the mailbox so that no more messages will be delivered or read. Any remaining queued 
+       /// messages are delivered to a default handler.</summary>
+       /// throws Exception 
+       bool CloseRead();
+
+       ///<summary>Registers a Notify interface implementation to receive a callback
+	   ///when a mailbox's status is changed.</summary>
+	   ///<param> newNotify a Notify interface implementation to report the
+	   ///delivery status to. </param>
+	   ///<param> state a state value to pass thru to the Notify interface
+	   /// implementation. </param>
+	   ///<param> maxDelay the maximum amount of time in milliseconds to
+	   ///wait for delivery of a message to the mailbox. 0 means wait
+	   ///forever. The mailbox is closed upon timeout.<param>
+    	
+	   void RegisterNotify( Notify newNotify, Object state, int maxDelay );
+	
+	
+	   /// <summary>Unregisters a Notify interface implementation from receiving a callback
+	   /// when a mailbox's status is changed. Cancels any timeout. </summary>
+       ///<param> oldNotify a Notify interface implementation which was previously
+	   ///registered. </param>    	
+	   void UnregisterNotify( Notify oldNotify );
+
+
+        bool Message(Who sender, Message msg);
+    }
+    
+        ///<summary>The message as queued, including src and sender.</summary>
+        public class Element : Who
+        {
+            /// <param name="sender">sender the message sender.</param>
+            /// <param name="msg">msg the message.</param>
+            public Element(Who sender, Message msg)
+            {
+                this.sender = sender;
+                this.msg = msg;
+            }
+
+            /// <summary>The message sender.</summary>
+            public Who sender;
+
+            /// <summary>the message.</summary>
+            public Message msg;
+        }
+
+        public interface Notify
+        {
+
+		    /// <summary>Notifies of mailbox status change.</summary>
+		    ///<param> mb the mailbox whose status has changed.</param>
+		    ///<param> state the state object passed in the register
+		    /// method.</param>
+		    /// <param> closed true if the mailbox timeout has expired and
+		    ///the mailbox is now closed to delivery, false if a message
+		    /// has arrived.</param>
+		 
+            void mailboxStatus(Mailbox mb, Object state, bool closed);
+            
+        }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/NullPool.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/NullPool.cs
new file mode 100644
index 0000000..06d9469
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/NullPool.cs
@@ -0,0 +1,50 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Threading;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// A pool which runs runnable directly
+    /// </summary>
+    public class NullPool : Pool
+    {
+        #region Pool Members
+
+        public void Run( RunDelegate d1, ExceptionDelegate d2 )
+        {
+            new Thread(
+                new ThreadStart( delegate()
+                                {
+                                    try
+                                    {
+                                        d1();
+                                    }
+                                    catch ( Exception e )
+                                    {
+                                        d2( e );
+                                    }
+                                } ) ).Start();
+        }
+
+        #endregion
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/ObjSession.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/ObjSession.cs
new file mode 100644
index 0000000..9dfc6f9
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/ObjSession.cs
@@ -0,0 +1,81 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Out-of-band query, control, and notification interface for sessions.
+    /// This is exactly the same as etch.bindings.java.transport.Session except
+    /// the names are changed to prevent collisions with service defined names.
+    /// </summary>
+    public interface ObjSession
+    {
+        /// <summary>
+        /// Gets a configuration or operational value from the handler. The
+        /// request is passed up the chain of sessions until some session
+        /// recognises the query, whereupon it returns the requested value.
+        /// </summary>
+        /// <param name="query">an object representing a query, which could be as
+        /// simple as a string, integer, or enum, or more complex such as
+        /// a class with instance variables for query terms.</param>
+        /// <returns>the requested value, or null if not defined.</returns>
+        /// Exception: 
+        ///     UnsupportedOperationException if the query is not recognised
+        ///     by any session (which is to say, if the last session in the session
+        ///     chain does not recognise it, it should throw this exception). Typically
+        ///     this would be a service's client or server implementation.
+        ///     
+        Object _SessionQuery( Object query );
+
+        /// <summary>
+        /// Sets a configuration or operational value in the session. The
+        /// request is passed up the chain of sessions until some session
+        /// recognises the control, whereupon it stores the specified value
+        /// and returns.
+        /// </summary>
+        /// <param name="control">an object representing a control, which could be as
+        /// simple as a string, integer, or enum, or more complex such as
+        /// a class with instance variables for control terms.</param>
+        /// <param name="value">the value to set.</param>
+        /// Exception:
+        ///     ArgumentException if the value is not the right
+        ///     type or if the value is inappropriate.
+        ///     
+        ///     UnsupportedOperationException if the control is not recognised
+        ///     by any session (which is to say, if the last session in the session
+        ///     chain does not recognise it, it should throw this exception). Typically
+        ///     this would be a service's client or server implementation.
+        ///
+        void _SessionControl( Object control, Object value );
+
+        /// <summary>
+        /// Notifies the chain of sessions of the specified event. Unlike query
+        /// and control operations above, events are always passed up to the
+        /// top to allow all sessions to notice them.
+        /// </summary>
+        /// <param name="eventObj">event a class which represents the event, possibly with
+        /// parameters. The simplest event could be a string, integer,
+        /// or enum, but any class instance will do (as long as some session
+        /// in the chain expects it).</param>
+        void _SessionNotify( Object eventObj );
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Pool.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Pool.cs
new file mode 100644
index 0000000..93cc317
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Pool.cs
@@ -0,0 +1,42 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Interface to a queued or free thread pool.
+    /// </summary>
+    public interface Pool
+    {
+        void Run( RunDelegate d1, ExceptionDelegate d2 );
+    }
+
+    /// <summary>
+    /// Delegate for what to run
+    /// </summary>
+    public delegate void RunDelegate();
+
+    /// <summary>
+    /// Delegate that can throw an exception
+    /// </summary>
+    /// <param name="e"></param>
+    public delegate void ExceptionDelegate( Exception e );
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/QueuedPool.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/QueuedPool.cs
new file mode 100644
index 0000000..85d3dc1
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/QueuedPool.cs
@@ -0,0 +1,81 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// A queued implementation of pool
+    /// </summary>
+    public class QueuedPool : Pool
+    {
+        /// <summary>
+        /// Constructs the queued pool with a specified todo manager.
+        /// </summary>
+        /// <param name="mgr"></param>
+        public QueuedPool( TodoManager mgr )
+        {
+            this.mgr = mgr;
+        }
+
+        /// <summary>
+        /// Constructs the queued pool with a default todo manager.
+        /// </summary>
+        /// Exception: 
+        ///     throws Exception
+        ///     
+        public QueuedPool() : this( TodoManager.GetTodoManager() )
+        {}
+
+        private TodoManager mgr;
+
+        public void Run( RunDelegate d1, ExceptionDelegate d2 )
+        {
+            MyTodo inst = new MyTodo ( d1, d2 );
+            mgr.Add( inst );
+        }
+
+        /// <summary>
+        /// Implementation of Todo
+        /// </summary>
+        public class MyTodo : Todo
+        {
+            public MyTodo ( RunDelegate d1, ExceptionDelegate d2 )
+            {
+                this.d1 = d1;
+                this.d2 = d2;
+            }
+
+            public void Doit( TodoManager mgr )
+            {
+                d1();
+            }
+
+            public void Exception( TodoManager mgr, Exception e ) 
+            {
+                d2( e );
+            }
+
+            private RunDelegate d1;
+            private ExceptionDelegate d2;
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/RemoteBase.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/RemoteBase.cs
new file mode 100644
index 0000000..2383fcf
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/RemoteBase.cs
@@ -0,0 +1,206 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    public class RemoteBase
+    {
+        /// <summary>Constructs the RemoteBase.</summary>
+        /// <param name="svc">svc</param>
+        /// <param name="vf">vf </param>
+        public RemoteBase(DeliveryService svc, ValueFactory vf)
+        {
+            this._svc = svc;
+            this._vf = vf;
+        }
+
+       
+        private DeliveryService _svc;
+
+        /// <summary>The value factory used to create messages and encode/decode types.</summary>
+        public ValueFactory _vf;
+
+        public override string ToString()
+        {
+            return String.Format("{0}/{1}", GetType(), _svc);
+        }
+
+        /// <summary> Constructs a new message to send using _send(Message) or _beginCall(Message)</summary>
+        /// <param name="type">type</param>
+        /// <returns>a new message</returns>
+        public Message _NewMessage(XType type)
+        {
+            return new Message(type, _vf);
+        }
+
+        	
+	    ///<summary>Sends the message to the recipient, but does not wait for any response.</summary>
+	    ///<param name = msg> the message to send </param>
+	    ///<throws> Exception if there is a problem sending </throws>
+	    public void _Send( Message msg )
+	    {
+		    _svc.TransportMessage(null,msg);
+	    }
+	
+	
+        ///<summary>Sends the message which begins a call sequence.</summary>
+        ///<param name = msg> the message to send </param>
+        ///<returns>A mailbox which can be used to read the response, using _EndCall</returns>
+	    public Mailbox _BeginCall( Message msg )
+	    {
+		    return _svc.BeginCall( msg );
+	    }
+
+       
+	    ///<summary>Finishes a call sequence by waiting for the response message.</summary>
+	    ///<param name = mb>a mailbox which will be used to read the response, returned by
+	    /// _BeginCall(Message) </param>
+	    ///<param name = responseType> the type of the expected response </param>
+	    ///<returns>the value of the response field if it isn't an exception.</returns>
+	    ///<throws> Exception if there is a problem sending or a timeout waiting or
+	    /// if the result value was an exception.</throws>
+	    public Object _EndCall( Mailbox mb, XType responseType ) 
+	    {
+		    return _svc.EndCall( mb, responseType );
+	    }
+
+
+        /// <summary>
+        /// Gets a configuration or operational value from the source. The
+        /// request is passed down the chain of sources until some source
+        /// recognises the query, whereupon it returns the requested value.
+        /// </summary>
+        /// 
+        /// <param name="query">an object representing a query, which could be as
+        /// simple as a string, integer, or enum, or more complex such as
+        /// a class with instance variables for query terms.</param>
+        /// <returns>the requested value, or null if not defined.</returns>
+        /// 
+        /// Exception:
+        ///     throws Exception if the query is not recognised
+        ///     by any source (which is to say, if the last source in the source
+        ///     chain does not recognise it, it should throw this exception).
+        ///     
+        public object _TransportQuery( object query )
+        {
+            return _svc.TransportQuery( query );
+        }
+
+        /// <summary>
+        /// Sets a configuration or operational value in the source. The
+        /// request is passed down the chain of sources until some source
+        /// recognises the control, whereupon it stores the specified value
+        /// and returns.
+        /// </summary>
+        /// 
+        /// <param name="control">an object representing a control, which could be as
+        /// simple as a string, integer, or enum, or more complex such as
+        /// a class with instance variables for control terms.</param>
+        /// 
+        /// <param name="value">the value to set.</param>
+        /// 
+        /// Exception: 
+        ///     throws ArgumentException if the value is not the right
+        ///     type or if the value is inappropriate.
+        ///     
+        ///     throws Exception if the control is not recognised
+        ///     by any source (which is to say, if the last source in the source
+        ///     chain does not recognise it, it should throw this exception).
+        /// 
+        public void _TransportControl( object control, object value )
+        {
+            _svc.TransportControl( control, value );
+        }
+
+        /// <summary>
+        /// Notifies the chain of sources of the specified event. Unlike query
+        /// and control operations above, events are always passed down to the
+        /// bottom to allow all sources to notice them.
+        /// </summary>
+        /// 
+        /// <param name="eventObj">a class which represents the event, possibly with
+        /// parameters. The simplest event could be a string, integer,
+        /// or enum, but any class instance will do (as long as some source
+        /// in the chain expects it).</param>
+        /// 
+        public void _TransportNotify( object eventObj )
+        {
+            _svc.TransportNotify( eventObj );
+        }
+
+        /// <summary>
+        /// Start the transport
+        /// </summary>
+        public void _Start()
+        {
+            _svc.TransportControl( TransportConsts.START, null );
+        }
+
+        /// <summary>
+        /// Waits for the transport to come up.
+        /// </summary>
+        /// <param name="maxDelay"></param>
+        public void _WaitUp( int maxDelay )
+        {
+            _svc.TransportQuery( new TransportConsts.WaitUp( maxDelay ) );
+        }
+
+        /// <summary>
+        /// Starts the transport and waits for it to come up.
+        /// </summary>
+        /// <param name="maxDelay"></param>
+        public void _StartAndWaitUp( int maxDelay )
+        {
+           _Start();
+            _WaitUp(maxDelay);
+        }
+
+        /// <summary>
+        /// Stops the transport.
+        /// </summary>
+        public void _Stop()
+        {
+            _svc.TransportControl( TransportConsts.STOP, null );
+        }
+
+        /// <summary>
+        /// Waits for the transport to go down.
+        /// </summary>
+        /// <param name="maxDelay"></param>
+        public void _WaitDown( int maxDelay )
+        {
+            _svc.TransportQuery( new TransportConsts.WaitDown( maxDelay ) );
+        }
+
+        /// <summary>
+        /// Stops the transport and waits for it to go down.
+        /// </summary>
+        /// <param name="maxDelay">maxdelay in milliseconds</param>
+        public void _StopAndWaitDown( int maxDelay )
+        {
+            _Stop();
+            _WaitDown(maxDelay);
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/RuntimeExceptionSerializer.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/RuntimeExceptionSerializer.cs
new file mode 100644
index 0000000..0cd8bac
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/RuntimeExceptionSerializer.cs
@@ -0,0 +1,62 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    public class RuntimeExceptionSerializer : ImportExportHelper
+    {
+        private const String FIELD_NAME = "msg";
+
+        public static void Init(XType type, Class2TypeMap class2type)
+        {
+            Field field = type.GetField(FIELD_NAME);
+            class2type.Add(typeof(_Etch_RuntimeException), type);
+            type.SetComponentType(typeof(_Etch_RuntimeException));
+            type.SetImportExportHelper(new RuntimeExceptionSerializer(type, field));
+            type.PutValidator(field, Validator_string.Get(0));
+            type.Lock();
+        }
+
+        public RuntimeExceptionSerializer(XType type, Field field)
+        {
+            this.type = type;
+            this.field = field;
+        }
+
+        private readonly XType type;
+
+        private readonly Field field;
+
+        public override StructValue ExportValue(ValueFactory vf, Object value)
+        {
+            StructValue sv = new StructValue(type, vf);
+            sv.Add(field, value.ToString());
+            return sv;
+        }
+
+        public override Object ImportValue(StructValue sv)
+        {
+            sv.CheckType(type);
+            return new _Etch_RuntimeException((String)sv.Get(field));
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/ServerFactory.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/ServerFactory.cs
new file mode 100644
index 0000000..b3d2587
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/ServerFactory.cs
@@ -0,0 +1,47 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Transport;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Interface to use for constructing new server instances by 
+    /// TransportHelper
+    /// </summary>
+    public interface ServerFactory : Session, Transport<Session>
+    {
+        /// <summary>
+        /// Constructs a new server session.
+        /// </summary>
+        /// <param name="transport">the TransportMessage to use with the new server instance.</param>
+        /// <param name="uri">the uri to use to configure the new server instance.</param>
+        /// <param name="resources">the resources to use for the new server instance.</param>
+        void NewServer(TransportMessage transport, string uri, Resources resources);
+
+        /// <summary>
+        /// Constructs a new instance of value factory for this session.
+        /// </summary>
+        /// <param name="uri">the uri to use to configure the new value factory.</param>
+        /// <returns>a new instance of value factory for this session.</returns>
+        ValueFactory NewValueFactory(string uri);
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/StubBase.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/StubBase.cs
new file mode 100644
index 0000000..5f7a75c
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/StubBase.cs
@@ -0,0 +1,162 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Transport;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+
+    /// <summary>
+    /// Base class of stub implementations
+    /// </summary>
+    public class StubBase : SessionMessage
+    {
+        /// <summary>Constructs the StubBase.</summary>
+        /// <param name="src">the message source</param>
+        /// <param name="obj">the target of decoded messages</param>
+        /// <param name="queued">thread pool used to run AsyncReceiverMode.QUEUED methods.</param>
+        /// <param name="free">thread pool used to run AsyncReceiverMode.FREE methods.</param>
+        public StubBase(DeliveryService src, object obj, Pool queued, Pool free)
+        {
+            _src = src;
+            _obj = obj;
+            _queued = queued;
+            _free = free;
+            src.SetSession(this);
+        }
+
+        /// <summary>
+        /// The message source.
+        /// </summary>
+        protected readonly DeliveryService _src;
+
+        /// <summary>
+        /// The target of decoded messages.
+        /// </summary>
+        protected readonly object _obj;
+
+        /// <summary>
+        /// Thread pool used to run AsyncReceiverMode.QUEUED methods.
+        /// </summary>
+        protected readonly Pool _queued;
+
+        /// <summary>
+        /// Thread pool used to run AsyncReceiverMode.FREE methods.
+        /// </summary>
+        protected readonly Pool _free;
+
+        
+
+        public Object SessionQuery(Object query)
+        {
+            if (_obj is ObjSession)
+                return ((ObjSession)_obj)._SessionQuery(query);
+            throw new NotSupportedException("unknown query: " + query);
+        }
+
+        public void SessionControl(Object control, Object value)
+        {
+            if (_obj is ObjSession)
+                ((ObjSession)_obj)._SessionControl(control, value);
+            else
+                throw new NotSupportedException("unknown control: " + control);
+        }
+
+        public void SessionNotify(Object eventObj)
+        {
+            SessionNotify(_obj, eventObj);
+        }
+
+        public static void SessionNotify( object obj, object eventObj )
+        {
+            if (obj is ObjSession)
+                ((ObjSession)obj)._SessionNotify(eventObj);
+            else if (eventObj is Exception)
+                Console.WriteLine(eventObj);
+        }
+
+        /// <summary>
+        /// Delegate that helps the stub dispatch the received message
+        /// </summary>
+        /// <param name="_src"></param>
+        /// <param name="_obj"></param>
+        /// <param name="sender"></param>
+        /// <param name="msg"></param> 
+        public delegate void StubHelperRun(DeliveryService _src, Object _obj, Who sender, Message msg);
+
+
+        #region SessionMessage Members
+
+        public bool SessionMessage(Who sender, Message msg)
+        {
+            XType type = msg.GetXType;
+
+            StubHelperRun helper = (StubHelperRun) type.GetStubHelper();
+            if (helper == null)
+                return false;
+
+            switch (type.GetAsyncMode())
+            {
+                case AsyncMode.QUEUED:
+                    try
+                    {
+                        _queued.Run(
+                            delegate { helper(_src, _obj, sender, msg); },
+                            delegate(Exception e) { SessionNotify(_obj, e); });
+                    }
+                    catch (Exception e)
+                    {
+                        SessionNotify(_obj, e);
+                    }
+                    break;
+                case AsyncMode.FREE:
+                    try
+                    {
+                        _free.Run(
+                            delegate { helper(_src, _obj, sender, msg); },
+                            delegate(Exception e) { SessionNotify(_obj, e); });
+                    }
+                    catch (Exception e)
+                    {
+                        SessionNotify(_obj, e);
+                    }
+                    break;
+                case AsyncMode.NONE:
+                    try
+                    {
+                        helper(_src, _obj, sender, msg);
+                    }
+                    catch (Exception e)
+                    {
+                        SessionNotify(_obj, e);
+                    }
+                    break;
+                default:
+                    throw new ArgumentException("unknown async mode "+type.GetAsyncMode());
+            }
+
+            return true;
+        }
+
+        #endregion
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/StubHelper.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/StubHelper.cs
new file mode 100644
index 0000000..64c9143
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/StubHelper.cs
@@ -0,0 +1,68 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    public class StubHelper
+    {
+        public StubHelper(Delegate del, AsyncMode mode)
+        {
+            this.mode = mode;
+            this.del = del;
+        }
+
+        /// <summary>Constructs a StubHelper which uses synchronous mode to dispatch
+        /// method from message.</summary>
+        public StubHelper() : this(AsyncMode.NONE)
+        {
+        }
+
+
+        ///<summary>Constructs a StubHelper which uses specified mode to
+        ///dispatch method from message.</summary>
+        ///<param name="mode">param mode</param>
+        public StubHelper(AsyncMode mode)
+        {
+            this.mode = mode;
+        }
+
+        private AsyncMode mode;
+        private Delegate del;
+
+        ///<returns>true if the mode is AsyncMode.QUEUED.</returns>
+        public bool IsQueued()
+        {
+            return mode == AsyncMode.QUEUED;
+        }
+
+        ///<returns>true if the mode is AsyncMode.FREE.</returns>
+        public bool IsFree()
+        {
+            return mode == AsyncMode.FREE;
+        }
+
+        public Delegate GetDelegate()
+        {
+            return del;
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/TransportFactory.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/TransportFactory.cs
new file mode 100644
index 0000000..9523583
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/TransportFactory.cs
@@ -0,0 +1,235 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using Org.Apache.Etch.Bindings.Csharp.Transport;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Interface to transport factory
+    /// </summary>
+	public abstract class TransportFactory
+	{
+        /// <summary>
+        /// Constructs a new Transport stack topped by a TransportMessage
+        /// which is used by the remote service implementations to send
+        /// messages.
+        /// </summary>
+        /// <param name="uri">transport configuration parameters.</param>
+        /// <param name="resources">additional resources needed by the stack.</param>
+        /// <returns>the TransportMessage topping the transport stack.</returns>
+        protected abstract TransportMessage NewTransport(string uri, Resources resources);
+
+        /// <summary>
+        /// Constructs a new Transport stack topped by a TransportMessage
+        /// which is used by the remote service implementations to send
+        /// messages.
+        /// </summary>
+        /// <param name="uri">transport configuration parameters.</param>
+        /// <param name="resources">additional resources needed by the stack.</param>
+        /// <returns>the TransportMessage topping the transport stack.</returns>
+        public static TransportMessage GetTransport(string uri, Resources resources) 
+	    {
+            URL u = new URL(uri);
+            TransportFactory f = GetTransportFactory(u.Scheme);
+            return f.NewTransport(uri, resources);
+	    }
+
+        /// <summary>
+        /// Constructs a new Transport Listener which is used to construct
+        /// server sessions.
+        /// </summary>
+        /// <param name="uri">listener configuration parameters.</param>
+        /// <param name="resources">additional resources needed by the listener.</param>
+        /// <returns>an out-of-band source which may be used to control the listener.</returns>
+        protected abstract Transport<ServerFactory> NewListener(string uri, Resources resources);
+
+        /// <summary>
+        /// Constructs a new Transport Listener which is used to construct
+        /// server sessions.
+        /// </summary>
+        /// <param name="uri">listener configuration parameters.</param>
+        /// <param name="resources">additional resources needed by the listener.</param>
+        /// <returns>an out-of-band source which may be used to control the listener.</returns>
+        public static Transport<ServerFactory> GetListener(string uri, Resources resources) 
+	    {
+            URL u = new URL(uri);
+            TransportFactory f = GetTransportFactory(u.Scheme);
+            return f.NewListener(uri, resources);
+	    }
+
+        /// <summary>
+        /// Adds any message filters specified on the uri. They are added in order
+        /// from transport to session. The first filter is the session for Messagizer,
+        /// the second is the session for the first, etc. The last filter added is
+        /// returned, and becomes the TransportMessage for what follows.
+        /// </summary>
+        /// <param name="transport"></param>
+        /// <param name="uri"></param>
+        /// <param name="resources"></param>
+        /// <returns>the most recently added filter</returns>
+        protected TransportMessage AddFilters(TransportMessage transport, URL uri, Resources resources)
+        {
+            string s = uri.GetTerm(FILTER);
+            if (s == null || s.Length == 0)
+                return transport;
+
+            StringTokenizer st = new StringTokenizer(s, ",:;| \t\r\n");
+            while (st.HasMoreTokens())
+            {
+                string t = st.NextToken();
+                transport = AddFilter(transport, t, uri, resources);
+            }
+
+            return transport;
+        }
+
+        /// <summary>
+        /// Query term on the transport uri which defines a set of filters which
+        /// process messages as they move up and down the transport stack. Filter
+        /// names are separated by one or more of these characters: ",:;| \t\r\n".
+        /// 
+        /// Usage example: tcp://host:port?filter=KeepAlive,PwAuth
+        /// </summary>
+        public const string FILTER = "filter";
+
+        private TransportMessage AddFilter(TransportMessage transport, string name,
+            URL uri, Resources resources)
+        {
+            string typeName = GetFilter(name);
+
+            if (typeName == null)
+                throw new ArgumentException(
+                    string.Format( "Class '{0}' for filter name '{1}' not defined", typeName, name ) );
+
+            Type type = Type.GetType(typeName);
+
+            ConstructorInfo c = type.GetConstructor(FILTER_PARAMS);
+
+            return (TransportMessage) c.Invoke(new object[] { transport, uri, resources });
+        }
+
+        private readonly static Type[] FILTER_PARAMS = { typeof(TransportMessage), typeof(URL), typeof(Resources) };
+
+        /// <summary>
+        /// Gets the fully qualified type name of the filter.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns>the fully qualified type name of the filter.</returns>
+        public static string GetFilter(string name)
+        {
+            lock (filters)
+            {
+                string value;
+                return filters.TryGetValue(name, out value) ? value : null;
+            }
+        }
+
+        /// <summary>
+        /// Sets the fully qualified type name of the filter.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="typeName"></param>
+        public static void DefineFilter(string name, string typeName)
+        {
+            lock (filters)
+            {
+                filters.Add(name, typeName);
+            }
+        }
+
+        private static readonly Dictionary<string, string> filters =
+            new Dictionary<string, string>();
+
+        /// <summary>
+        /// Gets the named transport factory.
+        /// </summary>
+        /// <param name="name">the name of a configured transport factory.</param>
+        /// <returns>the named transport factory.</returns>
+        private static TransportFactory GetTransportFactory( string name )
+        {
+            object tfspec = Get(name);
+
+            if (tfspec == null)
+                throw new IOException("transport factory scheme '" + name + "' unknown");
+
+            if (tfspec is string)
+                tfspec = Type.GetType((string)tfspec);
+
+            if (tfspec is Type)
+            {
+                ConstructorInfo c = ((Type)tfspec).GetConstructor(FACTORY_PARAMS);
+                tfspec = c.Invoke(FACTORY_ARGS);
+            }
+
+            if (tfspec is TransportFactory)
+                return (TransportFactory)tfspec;
+
+            throw new ArgumentException(String.Format(
+                "Cannot create an instance of TransportFactory from transport factory name '{0}'", name));
+        }
+
+        private readonly static Type[] FACTORY_PARAMS = { };
+
+        private readonly static object[] FACTORY_ARGS = { };
+
+        public static object Get(string name)
+        {
+            lock (transportFactories)
+            {
+                object value;
+                return transportFactories.TryGetValue(name, out value) ? value : null;
+            }
+        }
+
+
+        /// <summary>
+        /// Puts a named transport factory.
+        /// </summary>
+        /// <param name="name">the uri scheme of this transport factory.</param>
+        /// <param name="tfspec">the transport factory spec to associate with the
+        /// name. This can be an instance of TransportFactory or the name of a subclass
+        /// of TransportFactory to instantiate.</param>
+        public static void Define( string name, object tfspec )
+        {
+            lock (transportFactories)
+            {
+                transportFactories.Add(name, tfspec);
+            }
+        }
+
+        private readonly static Dictionary<string, object> transportFactories =
+            new Dictionary<string, object>();
+
+        static TransportFactory()
+        {
+            Define("tcp", new TcpTransportFactory(false));
+            Define("tls", new TcpTransportFactory(true));
+
+            DefineFilter("KeepAlive", "Org.Apache.Etch.Bindings.Csharp.Transport.Filter.KeepAlive");
+            DefineFilter("PwAuth", "Org.Apache.Etch.Bindings.Csharp.Transport.Filter.PwAuth");
+            DefineFilter("Logger", "Org.Apache.Etch.Bindings.Csharp.Transport.Filter.Logger");
+        }
+	}
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/TransportHelper.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/TransportHelper.cs
new file mode 100644
index 0000000..c68249c
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/TransportHelper.cs
@@ -0,0 +1,80 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Class to help construct transport stacks.
+    /// </summary>
+    public class TransportHelper
+    {
+        #region RESOURCES
+
+        /// <summary>
+        /// The Pool to use to execute queued async receiver messages. */
+	    /// </summary>
+        public const String QUEUED_POOL = "QUEUED_POOL";
+    	
+	    /// <summary>
+	    /// The Pool to use to execute free async receiver messages.
+	    /// </summary>
+ 	    public const String FREE_POOL = "FREE_POOL";
+    	
+	    /// <summary>
+	    /// Binary transport format
+	    /// </summary>
+	    public const String BINARY = "binary";
+    	
+	    /// <summary>
+        /// Xml transport format
+	    /// </summary>
+	    public const String XML = "xml";
+
+        #endregion
+
+        #region UTILITIES
+
+        /// <summary>
+        /// Initializes standard resources.
+        /// </summary>
+        /// <param name="resources">some initial values for resources. May be null to accept
+        /// all the defaults.</param>
+        /// <returns>copy of resources initialized with default values for standard items</returns>
+        public static Resources InitResources( Resources resources )
+        {
+            if ( resources == null )
+                resources = new Resources();
+            else
+                resources = new Resources(resources);
+
+            if ( !resources.ContainsKey( QUEUED_POOL ) )
+                resources.Add( QUEUED_POOL, new QueuedPool() );
+
+            if ( !resources.ContainsKey( FREE_POOL ) )
+                resources.Add( FREE_POOL, new FreePool() );
+
+            return resources;
+        }
+
+        #endregion
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/TypeValidator.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/TypeValidator.cs
new file mode 100644
index 0000000..d0609cb
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/TypeValidator.cs
@@ -0,0 +1,142 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Base class of validators which validate based on exact type.
+    /// </summary>
+    abstract public class TypeValidator : Validator
+    {
+        
+        /// <summary>
+        /// Constructs the TypeValidator.
+        /// </summary>
+        /// <param name="scalarClass">class to use if nDims == 0</param>
+        /// <param name="arrayClass">class to use if nDims > 0</param>
+        /// <param name="nDims">the number of dimensions. 0 for a scalar.</param>
+        /// <param name="descr"></param>
+        public TypeValidator( Type scalarClass, Type arrayClass, int nDims,
+            String descr)
+            : this(scalarClass, arrayClass, nDims, descr, false)
+        {
+          
+        }
+
+        /// <summary>
+        /// Constructs the TypeValidator.
+        /// </summary>
+        /// <param name="scalarClass">class to use if nDims == 0</param>
+        /// <param name="arrayClass">class to use if nDims > 0</param>
+        /// <param name="nDims">the number of dimensions. 0 for a scalar.</param>
+        /// <param name="descr"></param>
+        /// <param name="subclassOk">true of a subclass of the expected class is ok</param>
+        public TypeValidator(Type scalarClass, Type arrayClass, int nDims,
+            String descr, bool subclassOk)
+        {
+            CheckDims(nDims);
+
+            this.expectedClass = MkExpectedClass(scalarClass, arrayClass, nDims);
+            this.nDims = nDims;
+            this.descr = descr;
+            this.subclassOk = subclassOk;
+        }
+
+        /// <summary>
+        /// Checks the number of dimensions for standard validators.
+        /// </summary>
+        /// <param name="nDims"></param>
+        public static void CheckDims( int nDims )
+        {
+            if ( nDims < 0 || nDims > MAX_NDIMS )
+                throw new ArgumentOutOfRangeException( "nDims < 0 || nDims > MAX_NDIMS" );
+        }
+
+        private Type expectedClass;
+
+        /// <summary>
+        /// number of dimensions if this is an array
+        /// </summary>
+        protected int nDims;
+
+        protected bool subclassOk;
+
+        public int GetNDims()
+        {
+            return nDims;
+        }
+
+        private String descr;
+
+        public Type GetExpectedClass()
+        {
+            return expectedClass;
+        }
+
+        public override string ToString()
+        {
+            return descr;
+        }
+
+        public override bool Validate( object value )
+        {
+            if (value == null)
+                return false;
+            Type clss = value.GetType();
+          
+            if (clss == expectedClass)
+                return true;
+     
+            return subclassOk && expectedClass.IsAssignableFrom(clss);
+        }
+
+        public override object ValidateValue(object value)
+        {
+            if (Validate(value))
+                return value;
+
+            throw new Exception("value not appropriate for " + descr + ": " + value);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="scalarClass">class to use if nDims == 0</param>
+        /// <param name="arrayClass">class to use if nDims > 0</param>
+        /// <param name="nDims">number of dimensions, 0 for scalar</param>
+        /// <returns>an appropriate class given nDims.</returns>
+        /// 
+        private static Type MkExpectedClass( Type scalarClass, Type arrayClass, int nDims )
+        {
+            if ( nDims == 0 )
+                return scalarClass;
+
+            Array tempArray = Array.CreateInstance( arrayClass, 1 );
+            // Note: About C# jagged arrays
+            // 
+            for ( int i = 0; i < ( nDims - 1 ); i++ )
+                tempArray =  Array.CreateInstance( tempArray.GetType(), 1 );
+
+            return tempArray.GetType();
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_RuntimeException.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_RuntimeException.cs
new file mode 100644
index 0000000..06b01b6
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_RuntimeException.cs
@@ -0,0 +1,65 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Validator for Runtime Exceptions
+    /// </summary>
+    public class Validator_RuntimeException : Validator
+    {
+        /// <summary></summary>
+        /// <returns>an instance of the validator</returns>
+        public static Validator_RuntimeException Get()
+        {
+            if ( validator == null )
+                validator = new Validator_RuntimeException();
+
+            return validator;
+        }
+
+        private static Validator_RuntimeException validator;
+
+        public Validator_RuntimeException()
+        {
+            // nothing to do
+        }
+
+        public override Validator ElementValidator()
+        {
+            throw new Exception( "not an array" );
+        }
+
+        public override bool Validate( object value )
+        {
+            return ( value is Exception );
+        }
+
+        public override object ValidateValue(object value)
+        {
+            if (Validate(value))
+                return value;
+
+            throw new Exception("value not appropriate for RuntimeException: " + value);
+        }      
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_StructValue.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_StructValue.cs
new file mode 100644
index 0000000..d1ef4a0
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_StructValue.cs
@@ -0,0 +1,63 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Validator for structvalue
+    /// </summary>
+    public class Validator_StructValue : TypeValidator
+    {
+        public static Validator_StructValue Get(XType type, int nDims)
+        {
+            CheckDims(nDims);          
+            return new Validator_StructValue(type,nDims);
+        }
+
+       
+
+        private Validator_StructValue(XType type, int nDims)
+            : base( typeof( StructValue ), typeof( StructValue ), nDims, string.Format("StructValue[{0},{1}]",type,nDims) )
+        {
+            this.type = type;
+        }
+
+        private XType type;
+
+        public XType GetXType()
+        {
+            return type;
+        }
+
+        public override Validator ElementValidator()
+        {
+            return Get(type, nDims - 1);
+        }
+
+        public override bool Validate( object value )
+        {
+            return
+                base.Validate(value) &&
+                (value.GetType() != typeof (StructValue) || type.IsAssignableFrom(((StructValue) value).GetXType));
+ 
+        }     
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_boolean.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_boolean.cs
new file mode 100644
index 0000000..f60b541
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_boolean.cs
@@ -0,0 +1,68 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Validator for Boolean
+    /// </summary>
+    public class Validator_boolean : TypeValidator
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="nDims">number of dimensions. 0 for a scalar.</param>
+        /// <returns>an instance of the validator</returns>
+        public static Validator_boolean Get( int nDims )
+        {
+            CheckDims( nDims );
+
+            if ( nDims >= validators.Length )
+                return new Validator_boolean( nDims );
+
+            Validator_boolean v = validators[ nDims ];
+
+            if ( v == null )
+                v = validators[ nDims ] = new Validator_boolean( nDims );
+
+            return v;
+        }
+
+        private static Validator_boolean[] validators = new Validator_boolean[ MAX_CACHED ];
+
+        /// <summary>
+        /// Constructs the validator.
+        /// </summary>
+        /// <param name="nDims"></param>
+        private Validator_boolean( int nDims )
+            : base( typeof( bool ), typeof( bool ), nDims, "boolean["+nDims+"]" )
+        { 
+        }
+
+
+        public override Validator ElementValidator()
+        {
+            return Get( nDims - 1 );
+        }
+
+       
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_byte.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_byte.cs
new file mode 100644
index 0000000..532b386
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_byte.cs
@@ -0,0 +1,109 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Validator for byte
+    /// </summary>
+    public class Validator_byte : TypeValidator
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="nDims">number of dimensions. 0 for scalar.</param>
+        /// <returns>an instance of the validator</returns>
+        public static Validator_byte Get( int nDims )
+        {
+            CheckDims( nDims );
+
+            if ( nDims >= validators.Length )
+                return new Validator_byte( nDims );
+
+            Validator_byte v = validators[ nDims ];
+
+            if ( v == null )
+                v = validators[ nDims ] = new Validator_byte( nDims );
+
+            return v;
+        }
+
+        private static Validator_byte[] validators = new Validator_byte[ MAX_CACHED ];
+
+        /// <summary>
+        /// Constructs the validator.
+        /// </summary>
+        /// <param name="nDims"></param>
+        private Validator_byte( int nDims )
+            : base( typeof( sbyte ), typeof( sbyte ), nDims, "byte["+nDims+"]" )
+        {
+        }
+
+        public override Validator ElementValidator()
+        {
+            return Get( nDims - 1 );
+        }
+      	    
+	    public override bool Validate( object value )
+	    {
+		    if (nDims > 0)
+			   return base.Validate(value);
+		
+		    if (value == null)
+			    return false;
+
+            if (value.GetType() == typeof(sbyte))
+			    return true;
+		
+		    if (value.GetType() == typeof(short))
+		    {
+			    short v = (short) value;
+			    return v >= SByte.MinValue && v <= SByte.MaxValue;
+               
+		    }
+		
+		   if (value.GetType() == typeof(Int32))
+		    {
+			    int v = (Int32) value;
+			    return v >= SByte.MinValue && v <= SByte.MaxValue;
+		    }
+		
+		   if (value.GetType() == typeof(long))
+		   {
+			    long v = (long) value;
+			    return v >= SByte.MinValue && v <= SByte.MaxValue;
+		    }
+		
+		    return false;
+	    }
+		
+	    public override object ValidateValue( object value )
+	    {
+		    value = base.ValidateValue(value);
+		
+		    if ((value.GetType() == typeof(sbyte)) || nDims > 0)
+			    return value;
+
+            return Convert.ToSByte(value);
+	    }      
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_custom.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_custom.cs
new file mode 100644
index 0000000..ec7a9b6
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_custom.cs
@@ -0,0 +1,129 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Validator for custom type
+    /// </summary>
+    public class Validator_custom : TypeValidator
+    {
+        /// <summary></summary>
+        /// <param name="clss">Class of the custom type</param>
+        /// <param name="nDims">number of dimensions. 0 for scalar.</param>
+        /// <returns>an instance of the validator</returns>
+        public static Validator Get( Type clss, int nDims, bool subclassOk )
+        {
+            CheckDims( nDims );
+
+            if ( nDims > MAX_CACHED )
+                return new Validator_custom( clss, nDims, subclassOk );
+
+            Key key = new Key(clss, nDims, subclassOk);
+            Validator v = null;
+            
+            try
+            {
+                 v = validators[key];
+            }
+            catch(Exception)
+            {
+                v = null;
+            }
+
+            if (v == null)
+            {
+                v = new Validator_custom(clss, nDims, subclassOk);
+                validators.Add(key, v);
+            }
+
+            return v;
+
+        }
+
+
+        private  class Key
+	    {
+		    public Key( Type clss, int dims, bool subclassOk )
+		    {
+			    this.clss = clss;
+			    this.dims = dims;
+			    this.subclassOk = subclassOk;
+		    }
+		
+		    private Type clss;
+		
+		    private int dims;
+		
+		    private bool subclassOk;
+		
+		
+		    public override int GetHashCode()
+		    {
+			    return clss.GetHashCode() ^ (dims * 9131) ^ (subclassOk ? 21357 : 8547);
+		    }
+		
+	
+		    public override bool Equals( Object obj )
+		    {
+			    if (obj == this)
+				    return true;
+			
+			    if (obj == null)
+				    return false;
+			
+			    if (obj.GetType() != GetType())
+				    return false;
+			
+			    Key other = (Key) obj;
+			
+			    return other.clss.Equals( clss)
+				    && other.dims == dims
+				    && other.subclassOk == subclassOk;
+		    }
+	    }
+
+        private static Dictionary<Key, Validator> validators = 
+            new Dictionary<Key, Validator>();
+
+        /// <summary>
+        /// Constructs the validator
+        /// </summary>
+        /// <param name="clss">the class of the custom type</param>
+        /// <param name="nDims">the number of dimensions. 0 for scalar. </param>
+        private Validator_custom( Type clss, int nDims, bool subclassOk )
+            : base(clss, clss, nDims, subclassOk ? clss.ToString() + "[" + nDims + "]*" : clss.ToString() + "[" + nDims + "]", subclassOk)
+        {
+            this.clss = clss;
+        }
+
+        private Type clss;
+
+        public override Validator ElementValidator()
+        {
+            return Get( clss, nDims - 1, subclassOk );
+        }
+
+        
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_double.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_double.cs
new file mode 100644
index 0000000..48635e4
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_double.cs
@@ -0,0 +1,65 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Validator for double
+    /// </summary>
+    public class Validator_double : TypeValidator
+    {
+        /// <summary></summary>
+        /// <param name="nDims">number of dimensions. 0 for a scalar.</param>
+        /// <returns>an instance of the validator</returns>
+        public static Validator_double Get( int nDims )
+        {
+            CheckDims( nDims );
+
+            if ( nDims >= validators.Length )
+                return new Validator_double( nDims );
+
+            Validator_double v = validators[ nDims ];
+
+            if ( v == null )
+                v = validators[ nDims ] = new Validator_double( nDims );
+
+            return v;
+        }
+
+        private static Validator_double[] validators = new Validator_double[ MAX_CACHED ];
+
+        /// <summary>
+        /// Constructs the validator.
+        /// </summary>
+        /// <param name="nDims"></param>
+        private Validator_double( int nDims )
+            : base( typeof( Double ), typeof( double ), nDims, "double["+nDims+"]" )
+        { 
+        }
+
+        public override Validator ElementValidator()
+        {
+            return Get( nDims - 1 );
+        }
+       
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_float.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_float.cs
new file mode 100644
index 0000000..9744b8f
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_float.cs
@@ -0,0 +1,62 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    public class Validator_float : TypeValidator
+    {
+        /// <summary></summary>
+        /// <param name="nDims">number of dimensions. 0 for a scalar.</param>
+        /// <returns>an instance of the validator</returns>
+        public static Validator_float Get( int nDims )
+        {
+            CheckDims( nDims );
+
+            if ( nDims >= validators.Length )
+                return new Validator_float( nDims );
+
+            Validator_float v = validators[ nDims ];
+
+            if ( v == null )
+                v = validators[ nDims ] = new Validator_float( nDims );
+
+            return v;
+        }
+
+        private static Validator_float[] validators = new Validator_float[ MAX_CACHED ];
+
+        /// <summary>
+        /// Constructs the validator.
+        /// </summary>
+        /// <param name="nDims"></param>
+        private Validator_float( int nDims )
+            : base( typeof( float ), typeof( float ), nDims, "float["+nDims+"]" )
+        { 
+        }
+
+        public override Validator ElementValidator()
+        {
+            return Get( nDims - 1 );
+        }
+
+        
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_int.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_int.cs
new file mode 100644
index 0000000..af5b05c
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_int.cs
@@ -0,0 +1,99 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Validator for int
+    /// </summary>
+    public class Validator_int : TypeValidator
+    {
+        /// <summary></summary>
+        /// <param name="nDims">number of dimensions. 0 for a scalar.</param>
+        /// <returns>an instance of the validator</returns>
+        public static Validator_int Get( int nDims )
+        {
+            CheckDims( nDims );
+
+            if ( nDims >= validators.Length )
+                return new Validator_int( nDims );
+
+            Validator_int v = validators[ nDims ];
+
+            if ( v == null )
+                v = validators[ nDims ] = new Validator_int( nDims );
+
+            return v;
+        }
+
+        private static Validator_int[] validators = new Validator_int[ MAX_CACHED ];
+
+        /// <summary>
+        /// Constructs the validator.
+        /// </summary>
+        /// <param name="nDims"></param>
+        private Validator_int( int nDims )
+            : base( typeof( int ), typeof( int ), nDims, "int["+nDims+"]" )
+        { 
+        }
+
+        public override Validator ElementValidator()
+        {
+            return Get( nDims - 1 );
+        }
+
+       
+	    public override bool Validate( object value )
+	    {
+		    if (nDims > 0)
+			return base.Validate( value );
+		
+		    if (value == null)
+			    return false;
+		
+		    Type type = value.GetType();
+		
+		    if ( type == typeof(Int32) || type == typeof(Int16) || type == typeof(sbyte) )
+			    return true;
+		
+		    if (type == typeof(long))
+		    {
+			    long v = (long) value;
+			    return v >= Int32.MinValue && v <= Int32.MaxValue;
+		    }
+		
+		    return false;
+	    }
+	
+	
+	    public override object  ValidateValue( object value )
+	    {
+		    value = base.ValidateValue( value );
+		
+		    if ( value.GetType() == typeof(Int32) || nDims > 0)
+			 return value;
+			   
+            return Convert.ToInt32(value);
+    	}
+       
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_long.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_long.cs
new file mode 100644
index 0000000..e8056dc
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_long.cs
@@ -0,0 +1,92 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Validator for long
+    /// </summary>
+    public class Validator_long : TypeValidator
+    {
+        /// <summary></summary>
+        /// <param name="nDims">number of dimensions. 0 for a scalar.</param>
+        /// <returns>an instance of the validator</returns>
+        public static Validator_long Get( int nDims )
+        {
+            CheckDims( nDims );
+
+            if ( nDims >= validators.Length )
+                return new Validator_long( nDims );
+
+            Validator_long v = validators[ nDims ];
+
+            if ( v == null )
+                v = validators[ nDims ] = new Validator_long( nDims );
+
+            return v;
+        }
+
+        private static Validator_long[] validators = new Validator_long[ MAX_CACHED ];
+
+        /// <summary>
+        /// Constructs the validator.
+        /// </summary>
+        /// <param name="nDims"></param>
+        private Validator_long( int nDims )
+            : base( typeof( long ), typeof( long ), nDims, "long["+nDims+"]" )
+        { 
+        }
+
+        public override Validator ElementValidator()
+        {
+            return Get( nDims - 1 );
+        }
+
+        
+	    public override bool Validate( object value )
+	    {
+		    if (nDims > 0)
+			    return base.Validate( value );
+		
+		    if (value == null)
+			    return false;
+		
+		    Type type = value.GetType();
+		
+		    return type == typeof(long) || type == typeof(Int32) ||
+			type == typeof(short) || type == typeof(sbyte);
+	    }
+	
+	   
+	    public override object ValidateValue( object value )
+	    {
+		    value = base.ValidateValue( value );
+		
+		    if (value.GetType() == typeof(long) || nDims > 0)
+			    return value;
+
+            return Convert.ToInt64(value);
+	    }
+
+      
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_object.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_object.cs
new file mode 100644
index 0000000..6a19e8d
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_object.cs
@@ -0,0 +1,55 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    public class Validator_object : TypeValidator
+    {
+
+        private static Validator_object[] validators = new Validator_object[MAX_CACHED];
+
+        public override Validator ElementValidator()
+        {
+            return nDims > 0 ? Get(nDims - 1) : this;
+        }
+
+        private Validator_object(int nDims)
+            : base(typeof (object), typeof (object), nDims, string.Format("object[{0}]", nDims), true)
+        {
+            
+        }
+
+        public static Validator_object Get( int nDims )
+        {
+            CheckDims(nDims);
+
+            if (nDims >= validators.Length)
+                return new Validator_object(nDims);
+
+            Validator_object v = validators[nDims];
+
+            if ( v == null )
+                v=validators[nDims]= new Validator_object(nDims);
+
+            return v;
+        }      
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_short.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_short.cs
new file mode 100644
index 0000000..89f063a
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_short.cs
@@ -0,0 +1,106 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Validator for short
+    /// </summary>
+    public class Validator_short : TypeValidator
+    {
+        /// <summary></summary>
+        /// <param name="nDims">number of dimensions. 0 for a scalar.</param>
+        /// <returns>an instance of the validator</returns>
+        public static Validator_short Get( int nDims )
+        {
+            CheckDims( nDims );
+
+            if ( nDims >= validators.Length )
+                return new Validator_short( nDims );
+
+            Validator_short v = validators[ nDims ];
+
+            if ( v == null )
+                v = validators[ nDims ] = new Validator_short( nDims );
+
+            return v;
+        }
+
+        private static Validator_short[] validators = new Validator_short[ MAX_CACHED ];
+
+        /// <summary>
+        /// Constructs the validator.
+        /// </summary>
+        /// <param name="nDims"></param>
+        private Validator_short( int nDims )
+            : base( typeof( short ), typeof( short ), nDims, "short["+nDims+"]" )
+        { 
+        }
+
+        public override Validator ElementValidator()
+        {
+            return Get( nDims - 1 );
+        }
+
+       
+	    public override bool Validate( object value )
+	    {
+		    if (nDims > 0)
+			    return base.Validate( value );
+    		
+		    if (value == null)
+			    return false;
+    		
+		    Type type = value.GetType();
+    		
+		    if ( type == typeof(short) || type == typeof(sbyte))
+			    return true;
+    		
+		    if (type == typeof(Int32))
+		    {
+			    int v = (Int32) value;
+			    return v >= short.MinValue&& v <= short.MaxValue;
+		    }
+    		
+		    if (type == typeof(long))
+		    {
+			    long v = (long) value;
+			    return v >= short.MinValue && v <= short.MaxValue;
+		    }
+    		
+		    return false;
+	    }
+	
+	
+	    public override object ValidateValue( object value )
+	    {
+		    value = base.ValidateValue( value );
+    		
+		    if (value.GetType() == typeof(short) || nDims > 0)
+			    return value;
+
+            return Convert.ToInt16(value);
+	    }
+
+       
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_string.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_string.cs
new file mode 100644
index 0000000..f7dadc3
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_string.cs
@@ -0,0 +1,65 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Validator for strings
+    /// </summary>
+    public class Validator_string : TypeValidator
+    {
+        /// <summary></summary>
+        /// <param name="nDims">number of dimensions. 0 for a scalar.</param>
+        /// <returns>an instance of the validator</returns>
+        public static Validator_string Get( int nDims )
+        {
+            CheckDims( nDims );
+
+            if ( nDims >= validators.Length )
+                return new Validator_string( nDims );
+
+            Validator_string v = validators[ nDims ];
+
+            if ( v == null )
+                v = validators[ nDims ] = new Validator_string( nDims );
+
+            return v;
+        }
+
+        private static Validator_string[] validators = new Validator_string[ MAX_CACHED ];
+
+        /// <summary>
+        /// Constructs the validator.
+        /// </summary>
+        /// <param name="nDims"></param>
+        private Validator_string( int nDims )
+            : base( typeof( string ), typeof( string ), nDims, "string["+nDims+"]" )
+        { 
+        }
+
+        public override Validator ElementValidator()
+        {
+            return Get( nDims - 1 );
+        }
+
+        
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_void.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_void.cs
new file mode 100644
index 0000000..5534682
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/Validator_void.cs
@@ -0,0 +1,69 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    /// <summary>
+    /// Validator for void
+    /// </summary>
+    public class Validator_void : Validator
+    {
+        /// <summary></summary>
+        /// <param name="nDims">the number of dimensions. 0 for scalar</param>
+        /// <returns>an instance of the validator</returns>
+        public static Validator_void Get( int nDims )
+        {
+            if ( nDims != 0 )
+                throw new ArgumentException( "nDims != 0" );
+
+            if ( validator == null )
+                validator = new Validator_void();
+
+            return validator;
+        }
+
+        private static Validator_void validator;
+
+        private Validator_void()
+        {
+            // nothing to do
+        }
+
+        public override Validator ElementValidator()
+        {
+            return null;
+        }
+
+        public override bool Validate( object value )
+        {
+            return value == null;
+        }
+
+        public override object ValidateValue(object value)
+        {
+            if (Validate(value))
+                return value;
+
+            throw new Exception("value not appropriate for void: " + value);
+        }      
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/_Etch_AuthException.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/_Etch_AuthException.cs
new file mode 100644
index 0000000..de09419
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/_Etch_AuthException.cs
@@ -0,0 +1,35 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    public class _Etch_AuthException : _Etch_RuntimeException
+    {
+        public _Etch_AuthException()
+        {
+            // dont initialize anything
+        }
+
+        public _Etch_AuthException( String msg ) : base( msg )
+        {
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/_Etch_RuntimeException.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/_Etch_RuntimeException.cs
new file mode 100644
index 0000000..908a097
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Support/_Etch_RuntimeException.cs
@@ -0,0 +1,74 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+
+    /// <summary>
+    /// Constructs the EtchRuntimeException. Don't init anything.
+    /// 
+    /// Some common runtime exceptions are:
+    /// 
+    /// ArgumentException
+    /// ArgumentNullException
+    /// ArgumentOutOfRangeException
+    /// ArithmeticException
+    /// DivideByZeroException
+    /// IndexOutOfRangeException
+    /// InvalidCastException
+    /// NotImplementedException
+    /// NotSupportedException
+    /// NullReferenceException
+    /// OverflowException
+    /// </summary>
+    public class _Etch_RuntimeException
+        : Exception
+    {
+        /// <summary>
+        /// Constructs the EtchRuntimeException. Don't init anything.
+        /// </summary>
+        public _Etch_RuntimeException()
+        {
+            // don't init anything.
+        }
+
+       /// <summary>Constructs the EtchRuntimeException</summary>
+       /// <param name = "msg">msg description of the exception that was caught by the stub on the remote side.</param>
+        public _Etch_RuntimeException(String msg)
+        {
+            this.msg = msg;
+        }
+
+       
+        public String GetMessage()
+        {
+            return msg;
+        }
+
+        /// <summary>Description of the exception that was caught by the stub on the remote side. </summary>
+        public String msg;
+
+        public override string ToString()
+        {
+            return "Remote side threw this runtime exception: " + GetMessage();
+        }
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/ArrayValue.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/ArrayValue.cs
new file mode 100644
index 0000000..76aa8b3
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/ArrayValue.cs
@@ -0,0 +1,188 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+/// <summary>An array of values, where each value is of arbitrary type
+/// chosen from the basic java types boolean, byte, short, int,
+/// long, float, double, String, an array of those, the extended
+/// types ArrayValue and StructValue, and specific types supported
+/// by ValueFactory. 
+/// 
+/// ArrayValue is not protected against concurrent access. </summary>
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+
+    public class ArrayValue : IEnumerable
+    {
+        /// <summary>Constructs the ArrayValue.</summary>
+        public ArrayValue( Object array, sbyte typecode, XType customStructType, int dim )
+        {
+            if ( array == null )
+                throw new NullReferenceException( "array == null" );
+
+            if ( !( ( array.GetType() ).IsArray ) )
+                throw new ArgumentException( "object is not of type array" );
+
+            this.array = array;
+            this.typecode = typecode;
+		    this.CustomStructType = customStructType;
+		    this.Dim = dim;
+        }
+
+        /// <summary>
+        /// Constructs the arrayvalue without any type information
+        /// </summary>
+        public ArrayValue( Object array ) : this( array, ( sbyte ) 0, null, 0 )
+        {
+        }
+
+        private Object array;
+        private sbyte typecode;
+        private XType customStructType;
+        private int dim;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the TypeCode for this array value.
+        /// For example, if the array is int[][], then
+        /// the type would be TypeCode.INT4.
+        /// </returns>
+        public sbyte Type
+        {
+            get
+            {
+                return typecode;
+            }
+            set
+            {
+                typecode = value;
+            }
+        }
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>a struct type if a custom type code.</returns>
+        public XType CustomStructType
+        {
+            get
+            {
+                return customStructType;
+            }
+            private set
+            {
+                customStructType = value;
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the dimsionality of the array.
+        /// For example, if the array is int[][], the
+        /// dimensionality would be 2.</returns>
+        public int Dim
+        {
+            get
+            {
+                return dim;
+            }
+            private set
+            {
+                dim = value;
+            }
+        }
+
+        public int Size()
+        {
+            return ( ( Array ) array ).Length;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="index"></param>
+        /// <returns>the element at the specified index</returns>
+        public Object Get( int index )
+        {
+            return ( ( Array ) array ).GetValue( index );
+        }
+
+        /// <summary>
+        /// Reallocates the array so that it is only as long as needed.
+        /// </summary>
+        public void Compact()
+        {
+            if ( addIndex == Size() )
+                return;
+
+            Object narray = Array.CreateInstance( array.GetType().GetElementType(), addIndex );
+            Array.Copy( (Array)array, (Array)narray, addIndex );
+            array = narray;
+        }
+
+        /// <summary>
+        /// Adds the value to the end of the array, making more space
+        /// if needed
+        /// </summary>
+        /// <param name="value"></param>
+        public void Add( Object value )
+        {
+            int n = Size();
+
+            if ( addIndex >= n )
+            {
+                if ( n == 0 )
+                    n = 8;
+                else
+                    n *= 2;
+
+                Object narray = Array.CreateInstance( array.GetType().GetElementType(), n );
+                Array.Copy( (Array)array, (Array)narray, ( ( Array ) array ).Length );
+                array = narray;
+            }
+            ( ( Array ) array ).SetValue( value, addIndex++ );
+        }
+
+        private int addIndex;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the array</returns>
+        public Object GetArray()
+        {
+            return array;
+        }
+
+
+        #region IEnumerable Members
+
+        public IEnumerator GetEnumerator()
+        {
+            return ( ( Array ) array ).GetEnumerator();
+        }
+
+        #endregion
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/DefaultDeliveryService.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/DefaultDeliveryService.cs
new file mode 100644
index 0000000..f740ca8
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/DefaultDeliveryService.cs
@@ -0,0 +1,249 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    public class DefaultDeliveryService : DeliveryService
+    {
+        public DefaultDeliveryService(MailboxManager transport, string uri, Resources resources)
+            : this(transport, new URL(uri), resources)
+        {
+        }
+
+
+        public DefaultDeliveryService(MailboxManager transport, URL uri, Resources resources)
+        {
+            this.transport = transport;
+            transport.SetSession(this);
+            disableTimeout = uri.GetBooleanTerm(DISABLE_TIMEOUT, false);
+        }
+
+        
+        /// <summary>
+        /// Parameter to Globally Disable Timeout.
+        /// </summary>
+        
+        public const string DISABLE_TIMEOUT = "DefaultDeliveryService.disableTimeout";
+        
+        
+        private bool disableTimeout = false;
+
+
+        private SessionMessage _stub;
+
+        private MailboxManager transport;
+
+        
+
+        /// <summary>
+        /// Removes all the stubs in the set of stubs
+        /// </summary>
+        public void RemoveStub()
+        {
+            _stub = null;
+        }
+
+        public Object SessionQuery(object query)
+        {
+            if (_stub != null)
+                return _stub.SessionQuery(query);
+
+            throw new NotSupportedException("unknown query: " + query);
+        }
+
+        public void SessionControl(Object control, Object value)
+        {
+            if (_stub != null)
+                _stub.SessionControl(control, value);
+
+            throw new NotSupportedException("unknown control: " + control);
+        }
+
+        public void SessionNotify(Object eventObj)
+        {
+            if (eventObj is string)
+            {
+                string stringObj = (string) eventObj;
+                if (stringObj == SessionConsts.UP)
+                {
+                    status.Set(SessionConsts.UP);
+                }
+                else if (stringObj == SessionConsts.DOWN)
+                {
+                    status.Set(SessionConsts.DOWN);
+                }
+                
+            }
+           
+                _stub.SessionNotify(eventObj);
+                
+  
+            
+
+        }
+
+        private Monitor<string> status = new Monitor<string>("session status");
+
+       
+        public Object TransportQuery(Object query)
+        {
+            if(query.GetType() == typeof(TransportConsts.WaitUp))
+            {
+                waitUp(((TransportConsts.WaitUp) query)._maxDelay);
+                return null;
+            }
+            else if (query.GetType() == typeof(TransportConsts.WaitDown))
+            {
+                waitDown(((TransportConsts.WaitDown)query)._maxDelay);
+                return null;
+            }
+            else
+            {
+                return transport.TransportQuery(query);
+            }
+
+        }
+
+        private void waitUp(int maxDelay)
+        {
+            status.WaitUntilEq(SessionConsts.UP,maxDelay);
+        }
+
+        private void waitDown(int maxDelay)
+        {
+            status.WaitUntilEq(SessionConsts.DOWN, maxDelay);
+        }
+
+        public void TransportControl(Object control, Object value)
+        {
+            if (control is string)
+            {
+                string stringObj = (string) control;
+
+                if (stringObj == TransportConsts.START_AND_WAIT_UP)
+                {
+                    transport.TransportControl(TransportConsts.START, null);
+                    waitUp((int) value);
+                }
+                else if (stringObj == TransportConsts.STOP_AND_WAIT_DOWN)
+                {
+                    transport.TransportControl(TransportConsts.STOP,null);
+                    waitDown((int)value);
+                }
+                else
+                {
+                    transport.TransportControl(control, value);
+                }       
+            }
+            else
+            {
+                transport.TransportControl(control, value); 
+            }
+           
+        }
+
+        public void TransportNotify(Object eventObj)
+        {
+            transport.TransportNotify(eventObj);
+        }
+
+       
+
+        public Mailbox BeginCall(Message msg)
+        {
+            return transport.TransportCall(null, msg);
+        }
+
+        public Object EndCall(Mailbox mb, XType responseType)
+        {
+            try
+            {
+                int timeout = disableTimeout ? 0 : responseType.Timeout;
+                Element mbe = mb.Read(timeout);
+                if (mbe == null)
+                    throw new TimeoutException("timeout waiting for " + responseType);
+                Message rmsg = mbe.msg;
+                rmsg.CheckType(responseType);
+                Object r = rmsg.Get(responseType.ResponseField);
+                if (r is Exception)
+                {
+                    Exception e = (Exception)r;
+                    throw e;
+                }
+                return r;
+            }
+            finally
+            {
+                mb.CloseRead();
+            }
+        }
+
+        public override string ToString()
+        {
+            return transport.ToString();
+        }
+
+    
+
+     
+        #region SessionMessage Members
+
+        public bool SessionMessage(Who sender, Message msg)
+        {
+           return  _stub.SessionMessage(sender, msg);
+        }
+
+        /// <summary>
+        /// Adds a stub to a list of stub
+        /// </summary>
+        /// <param name="stb"></param>
+        public void SetSession(SessionMessage stb)
+        {
+            if (_stub != null)
+                throw new Exception("Unsupported -- only one stub for now");
+            _stub = stb;
+        }
+
+        #endregion
+
+        #region TransportMessage Members
+
+        public void TransportMessage(Who recipient, Message msg)
+        {
+            transport.TransportMessage(recipient,msg);
+        }
+
+        #endregion
+
+        #region Transport<SessionMessage> Members
+
+
+        public SessionMessage GetSession()
+        {
+            return _stub;
+        }
+
+        #endregion
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Filter/AbstractMessageFilter.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Filter/AbstractMessageFilter.cs
new file mode 100644
index 0000000..532c62c
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Filter/AbstractMessageFilter.cs
@@ -0,0 +1,131 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Filter
+{
+    abstract public class AbstractMessageFilter : TransportMessage, SessionMessage
+    {
+        protected AbstractMessageFilter(TransportMessage transport, URL uri, Resources resources)
+        {
+            this.transport = transport;
+            transport.SetSession(this);
+        }
+
+        /// <summary>
+        /// Our transport.
+        /// </summary>
+        protected readonly TransportMessage transport;
+
+        /// <summary>
+        /// Returns a string such as "Filter/"+transport.
+        /// </summary>
+        /// <returns>a string such as "Filter/"+transport.</returns>
+        abstract public override string ToString();
+
+        public virtual void TransportMessage(Who recipient, Message msg)
+        {
+            transport.TransportMessage(recipient, msg);
+        }
+
+        public SessionMessage GetSession()
+        {
+            return session;
+        }
+
+        public void SetSession(SessionMessage session)
+        {
+            this.session = session;
+        }
+
+        /// <summary>
+        /// Our session.
+        /// </summary>
+        protected SessionMessage session;
+
+        public virtual object TransportQuery(object query)
+        {
+            return transport.TransportQuery(query);
+        }
+
+        public virtual void TransportControl(object control, object value)
+        {
+            transport.TransportControl(control, value);
+        }
+
+        public void TransportNotify(object evnt)
+        {
+            transport.TransportNotify(evnt);
+        }
+
+        public virtual bool SessionMessage(Who sender, Message msg)
+        {
+            return session.SessionMessage(sender, msg);
+        }
+
+        public object SessionQuery(object query)
+        {
+            return session.SessionQuery(query);
+        }
+
+        public void SessionControl(object control, object value)
+        {
+            session.SessionControl(control, value);
+        }
+
+        public void SessionNotify(object evnt)
+        {
+            if (evnt == (object) SessionConsts.UP)
+                if (!SessionUp())
+                    return;
+
+            if (evnt == (object) SessionConsts.DOWN)
+                if (!SessionDown())
+                    return;
+
+            session.SessionNotify(evnt);
+        }
+
+        /**
+         * Tells the filter that the session is up.
+         * @return true if the event should be passed on to our session, false
+         * if it should be swallowed.
+         * @throws Exception 
+         */
+        protected virtual bool SessionUp()
+        {
+            // nothing to do.
+            return true;
+        }
+
+        /**
+         * Tells the filter that the session is down.
+         * @return true if the event should be passed on to our session, false
+         * if it should be swallowed.
+         * @throws Exception 
+         */
+        protected virtual bool SessionDown()
+        {
+            // nothing to do.
+            return true;
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Filter/KeepAlive.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Filter/KeepAlive.cs
new file mode 100644
index 0000000..1c66192
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Filter/KeepAlive.cs
@@ -0,0 +1,308 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Filter
+{
+    public class KeepAlive : AbstractMessageFilter, AlarmListener
+    {
+
+
+        public const String DELAY = "KeepAlive.delay";
+
+
+        public const String COUNT = "KeepAlive.count";
+
+        public KeepAlive(TransportMessage transport, URL uri, Resources resources)
+            : base(transport, uri, resources)
+        {
+
+            delay = uri.GetIntegerTerm(DELAY, 15);
+            if (delay <= 0)
+                throw new ArgumentException("delay <= 0");
+
+            count = uri.GetIntegerTerm(COUNT, 4);
+            if (count <= 0)
+                throw new ArgumentException("count <= 0");
+
+            server = (Boolean) transport.TransportQuery(TransportConsts.IS_SERVER);
+
+            //		Log.report( "KeepAliveInstalled",
+            //			"delay", delay, "count", count, "server", server );
+
+            vf = (ValueFactory)resources.Get(TransportConsts.VALUE_FACTORY);
+
+            mf_delay = new Field("delay");
+            mf_count = new Field("count");
+
+            mt_request = new XType("_Etch_KeepAliveReq");
+            mt_request.PutValidator(mf_delay, Validator_int.Get(0));
+            mt_request.PutValidator(mf_count, Validator_int.Get(0));
+            vf.AddType(mt_request);
+
+            mt_response = new XType("_Etch_KeepAliveResp");
+            vf.AddType(mt_response);
+
+            mt_request.SetResult(mt_response);
+        }
+
+        private int delay;
+
+        private int count;
+
+        private readonly bool server;
+
+        private readonly ValueFactory vf;
+
+        private readonly Field mf_delay;
+
+        private readonly Field mf_count;
+
+        private readonly XType mt_request;
+
+        private readonly XType mt_response;
+
+        public int GetDelay()
+        {
+            return delay;
+        }
+
+        public int GetCount()
+        {
+            return count;
+        }
+
+       
+        public bool GetServer()
+        {
+            return server;
+        }
+
+
+        public override bool SessionMessage(Who sender, Message msg)
+        {
+            if (msg.IsType(mt_request))
+            {
+                handleRequest(msg);
+                return true;
+            }
+
+            if (msg.IsType(mt_response))
+            {
+                handleResponse(msg);
+                return true;
+            }
+
+            return base.SessionMessage(sender, msg);
+        }
+
+
+
+        protected override bool SessionUp()
+        {
+            //		Log.report( "KeepAliveSessionUp", "server", server );
+            up = true;
+            AlarmManager.staticAdd(this, null, delay * 1000);
+            tickle();
+            return true;
+        }
+
+        protected override bool SessionDown()
+        {
+            //		Log.report( "KeepAliveSessionDown", "server", server );
+            up = false;
+            AlarmManager.staticRemove(this);
+            return true;
+        }
+
+        private bool up;
+
+        private void handleRequest(Message msg)
+        {
+            if (!server)
+            {
+                // we're a client that got a request, likely we're talking to a
+                // server that is confused.
+                return;
+            }
+
+            //Log.report( "GotKeepAliveReq", "msg", msg );
+           // Console.WriteLine("GotKeepAliveReq:Msg " + msg);
+
+            int? d = (int?)msg.Get(mf_delay);
+            if (d != null && d.Value > 0)
+            {
+               //Console.WriteLine("KeepAliveResetDelay delay " +  d );
+                delay = d.Value;
+            }
+
+            int? c = (int?)msg.Get(mf_count);
+            if (c != null && c.Value > 0)
+            {
+               // Console.WriteLine( "KeepAliveResetCount count " + c );
+                count = c.Value;
+            }
+
+            tickle();
+
+            sendKeepAliveResp(msg);
+        }
+
+        private void handleResponse(Message msg)
+        {
+            if (server)
+            {
+                // we're a server that got a response, which means either we sent
+                // a request (but we shouldn't do that if we're a server) or the
+                // client is confused.
+                return;
+            }
+
+            //Log.report( "GotKeepAliveResp", "msg", msg );
+            //Console.WriteLine(" GotKeepAliveResp: msg " + msg);
+
+            tickle();
+        }
+
+        private void tickle()
+        {
+            //	lastTickle = Timer.GetNanos();
+      //      lastTickle = HPTimer.Now();
+            lastTickle = HPTimer.Now();
+        }
+
+        private long lastTickle;
+
+        private void checkTickle()
+        {
+           
+
+            long ms = HPTimer.MillisSince(lastTickle);
+            //		Log.report( "KeepAliveIdle", "ms", ms, "server", server );
+            if (ms >= count * delay * 1000)
+            {
+                try
+                {
+                    //				Log.report( "KeepAliveReset", "server", server );
+                    session.SessionNotify("KeepAlive resetting dead connection");
+                    transport.TransportControl(TransportConsts.RESET, 0);
+                }
+                catch (Exception e)
+                {
+                    reportError(e);
+                }
+            }
+        }
+
+        private void sendKeepAliveReq()
+        {
+            Message msg = new Message(mt_request, vf);
+            msg.Add(mf_delay, delay);
+            msg.Add(mf_count, count);
+            try
+            {
+                //		Log.report( "SendKeepAliveReq", "msg", msg );
+                transport.TransportMessage(null, msg);
+            }
+            catch (Exception e)
+            {
+                reportError(e);
+            }
+        }
+
+        private void sendKeepAliveResp(Message msg)
+        {
+            Message rmsg = msg.Reply();
+            try
+            {
+                //Log.report( "SendKeepAliveResp", "rmsg", rmsg );
+                transport.TransportMessage(null, rmsg);
+            }
+            catch (Exception e)
+            {
+                reportError(e);
+            }
+        }
+
+        public int Wakeup(AlarmManager manager, Object state, long due)
+        {
+            //		Log.report( "KeepAliveWakeup", "server", server );
+
+            if (!up)
+                return 0;
+
+            if (!server)
+            {
+                TodoManager.AddTodo(new MyTodo(sendKeepAliveReq, reportError));
+            }
+
+            checkTickle();
+
+            return delay * 1000;
+        }
+
+        private void reportError(Exception e)
+        {
+            try
+            {
+                session.SessionNotify(e);
+            }
+            catch (Exception e1)
+            {
+                Console.WriteLine(e1);
+            }
+        }
+
+        public override string ToString()
+        {
+            return "KeepAlive/" + transport;
+        }
+    }
+
+    public class MyTodo : Todo
+    {
+        public delegate void doit();
+
+        public delegate void report(Exception e);
+
+        public MyTodo(doit d, report r)
+        {
+            this.d = d;
+            this.r = r;
+        }
+
+        private readonly doit d;
+
+        private readonly report r;
+
+        public void Doit(TodoManager mgr)
+        {
+            d();
+        }
+
+        public void Exception(TodoManager mgr, Exception e)
+        {
+            r(e);
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Filter/Logger.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Filter/Logger.cs
new file mode 100644
index 0000000..3ff9ede
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Filter/Logger.cs
@@ -0,0 +1,166 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Globalization;
+using System.IO;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Filter
+{
+    public class Logger : AbstractMessageFilter
+    {
+
+        private const String FILE_PATH = "Logger.filePath";
+
+        private String fileName = null;
+
+        private TextWriter writer = null;
+
+        public static bool testFlag = false;
+
+        private string testRenamedFileName = null;
+
+        enum Direction
+        {
+            UP, DOWN
+        }
+
+        public Logger(TransportMessage transport, URL uri, Resources resources)
+            : base(transport, uri, resources)
+        {
+            InitializeLogger(uri);
+           
+        }
+
+        private void InitializeLogger(URL uri)
+        {
+            string newFullFileName;
+            fileName = uri.GetTerm(FILE_PATH);
+            if (fileName == null)
+            {
+                fileName = "Log.txt";
+            }
+            
+            if (!testFlag)
+            {
+                if (File.Exists(fileName))
+                {
+                    //      string newFileName = Path.GetFileNameWithoutExtension(fileName) + DateTime.Now.ToString("yyyy.MM.dd.HH.mm.ss", CultureInfo.CreateSpecificCulture("en-US")) + Path.GetExtension(fileName);
+                    //    newFullFileName = Path.Combine(new FileInfo(fileName).DirectoryName, newFileName);
+                    newFullFileName = GenerateNewFileName(fileName, new FileInfo(fileName).DirectoryName);
+                    File.Move(fileName, newFullFileName);
+                    File.Delete(fileName);
+                }
+                writer = TextWriter.Synchronized(new StreamWriter(fileName));
+            }
+            else
+            {
+                testRenamedFileName = GenerateNewFileName(fileName,null);
+            }
+        }
+
+        private string GenerateNewFileName(string fileName, string pathName )
+        {
+            if (pathName == null)
+                pathName = "";
+            string newFileName = Path.GetFileNameWithoutExtension(fileName) + DateTime.Now.ToString("yyyy.MM.dd.HH.mm.ss", CultureInfo.CreateSpecificCulture("en-US")) + Path.GetExtension(fileName);
+            string newFullFileName = Path.Combine(pathName, newFileName);
+            return newFullFileName;
+        }
+
+        public override string ToString()
+        {
+            return "Logger/" + transport;
+        }
+
+        public string GetFileName()
+        {
+            return fileName;
+        }
+
+        public string GetTestRenamedFileName()
+        {
+            return testRenamedFileName;
+        }
+
+        public override bool SessionMessage(Who sender, Message msg)
+        {
+            WriteToFile(Direction.UP, sender, msg.ToString());
+            return base.SessionMessage(sender, msg);
+        }
+
+        public override void TransportMessage(Who recipient, Message msg)
+        {
+            WriteToFile(Direction.DOWN, recipient, msg.ToString());
+            base.TransportMessage(recipient, msg);
+        }
+        protected override bool SessionUp()
+        {
+            WriteToFile(Direction.UP, null, transport.ToString());
+            return true;
+        }
+
+        protected override bool SessionDown()
+        {
+            WriteToFile(Direction.DOWN, null, transport.ToString());
+            return true;
+        }
+
+        private void WriteToFile(Direction direction, Who msgOrigin, String msg)
+        {
+            if (writer == null)
+                return;
+            try
+            {
+                lock (writer)
+                {
+                    writer.Write(DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.CreateSpecificCulture("en-US")));
+                    writer.Write(": ");
+                    writer.Write(ConvertDirToString(direction));
+                    writer.Write(": ");
+                    if (msgOrigin != null)
+                    {
+                        writer.Write(msgOrigin.ToString());
+                        writer.Write(": ");
+                    }
+                    writer.Write(msg);
+                    writer.WriteLine();
+                    writer.Flush();
+                }
+            }
+            catch (Exception e)
+            {
+                writer.Close();
+                throw e;
+            }
+
+        }
+
+        private String ConvertDirToString(Direction dir)
+        {
+            if (Direction.DOWN == dir)
+                return "Outgoing";
+            return "Incoming";
+        }
+
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Filter/PwAuth.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Filter/PwAuth.cs
new file mode 100644
index 0000000..bd4ea24
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Filter/PwAuth.cs
@@ -0,0 +1,365 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Filter
+{
+    /// <summary>
+    /// PwAuth is a message filter which watches for Session.UP and attempts to
+    /// authenticate the user by sending a message to the server with the name and
+    /// password in it. If the server responds, the session is notified with the
+    /// user name. If the server responds negatively, the session is notified of the
+    /// failure (using a PwAuthFail event). A transport control may also be sent to
+    /// force a login or logout or to set the name or password. The name and password
+    /// are initialized from the uri, or prompted for if not specified.
+    /// </summary>
+    public class PwAuth : AbstractMessageFilter
+    {
+
+
+
+        /// <summary>
+        /// client sessionQuery: return user name to use for authentication.
+        /// transportQuery: return the current user name (on server it has been validated).
+        /// client transportControl: set user name to use for authentication.
+        /// </summary>
+
+        public const String USER = "PwAuth.user";
+
+
+
+        /// <summary>
+        /// client sessionQuery: return password to use for authentication.
+        /// transportQuery: return the current password (on server it has been validated).
+        /// client transportControl: set password to use for authentication.
+        /// </summary>
+        /// 
+        public const String PASSWORD = "PwAuth.password";
+
+        /// <summary>
+        /// client transportControl: send authentication request
+        /// </summary>
+        private const String AUTHENTICATE = "PwAuth.authenticate";
+
+        public PwAuth(TransportMessage transport, URL uri, Resources resources)
+            : base(transport, uri, resources)
+        {
+
+            server = (Boolean)transport.TransportQuery(TransportConsts.IS_SERVER);
+
+            if (!server)
+            {
+                user = uri.User;
+                password = uri.Password;
+            }
+
+            //		Log.report( "KeepAliveInstalled",
+            //			"delay", delay, "count", count, "server", server );
+
+            vf = (ValueFactory)resources.Get(TransportConsts.VALUE_FACTORY);
+
+            mt_request = new XType("_Etch_PwAuthReq");
+            mt_response = new XType("_Etch_PwAuthResp");
+
+            vf.AddType(mt_request);
+            vf.AddType(mt_response);
+
+            mf_user = new Field("user");
+            mf_password = new Field("password");
+            mf_ok = new Field("ok");
+            mf_status = new Field("status");
+
+            mt_request.PutValidator(mf_user, Validator_string.Get(0));
+            mt_request.PutValidator(mf_password, Validator_string.Get(0));
+            mt_request.SetResult(mt_response);
+            mt_request.Lock();
+
+            mt_response.PutValidator(mf_ok, Validator_boolean.Get(0));
+            mt_response.PutValidator(mf_status, Validator_string.Get(0));
+            mt_response.Lock();
+        }
+
+        private String user;
+
+        private String password;
+
+        private readonly bool server;
+
+        private readonly ValueFactory vf;
+
+        private readonly Field mf_user;
+
+        private readonly Field mf_password;
+
+        private readonly Field mf_ok;
+
+        private readonly Field mf_status;
+
+        private readonly XType mt_request;
+
+        private readonly XType mt_response;
+
+        public bool GetServer()
+        {
+            return server;
+        }
+
+        public override bool SessionMessage(Who sender, Message msg)
+        {
+            if (msg.IsType(mt_request))
+            {
+                HandlePwAuthReq(sender, msg);
+                return true;
+            }
+
+            if (msg.IsType(mt_response))
+            {
+                HandlePwAuthResp(sender, msg);
+                return true;
+            }
+
+            return base.SessionMessage(sender, msg);
+        }
+
+
+        protected override bool SessionUp()
+        {
+            if (!server)
+            {
+                // client: send authentication request.
+                SendPwAuthReq();
+            }
+            return true;
+        }
+
+
+        protected override bool SessionDown()
+        {
+            if (server)
+            {
+                // make sure that server session's idea of user is cleared.
+                SessionNotifyUser(null, null);
+            }
+
+            return true;
+        }
+
+        private void SendPwAuthReq()
+        {
+            if (user == null)
+            {
+                user = (String)session.SessionQuery(USER);
+                if (user == null)
+                    throw new Exception("PwAuth: user == null");
+            }
+
+            if (password == null)
+            {
+                password = (String)session.SessionQuery(PASSWORD);
+                if (password == null)
+                    throw new Exception("PwAuth: password == null");
+            }
+
+            Message msg = new Message(mt_request, vf);
+            msg.Add(mf_user, user);
+            msg.Add(mf_password, password);
+            transport.TransportMessage(null, msg);
+        }
+
+        private void HandlePwAuthReq(Who sender, Message msg)
+        {
+            if (!server)
+            {
+                // we're a client that got a request, likely we're talking to a
+                // server that is confused.
+                return;
+            }
+
+            Console.WriteLine(" Sender: " + sender);
+            Console.WriteLine(" Message: " + msg);
+
+            String u = (String)msg.Get(mf_user);
+            String p = (String)msg.Get(mf_password);
+
+            try
+            {
+                OkStatus as1 = (OkStatus)SessionQuery(new UserPassword(u, p));
+
+                if (as1.ok)
+                    SessionNotifyUser(u, p);
+                else
+                    SessionNotifyUser(null, null);
+
+                sendPwAuthResp(sender, msg, as1.ok, as1.status);
+            }
+            catch (Exception e)
+            {
+                SessionNotifyUser(null, null);
+                sendPwAuthResp(sender, msg, false, e.ToString());
+                throw e;
+            }
+        }
+
+        private void sendPwAuthResp(Who recipient, Message msg, bool result, String status)
+        {
+            Message rmsg = msg.Reply();
+            rmsg.Add(mf_ok, result);
+            rmsg.Add(mf_status, status);
+            transport.TransportMessage(recipient, rmsg);
+        }
+
+        private void HandlePwAuthResp(Who sender, Message msg)
+        {
+            if (server)
+            {
+                // we're a server that got a response, likely we're talking to a
+                // client that is confused.
+                return;
+            }
+
+            // Log.report( "GotPwAuthResp", "sender", sender, "msg", msg );
+
+            bool result = (Boolean)msg.Get(mf_ok);
+            String status = (String)msg.Get(mf_status);
+
+            session.SessionNotify(new OkStatus(result, status));
+        }
+
+
+        public override object TransportQuery(Object query)
+        {
+            if ((string)query == USER)
+                return user;
+
+            if ((string)query == PASSWORD)
+                return password;
+
+            return base.TransportQuery(query);
+        }
+
+
+        public override void TransportControl(Object control, Object value)
+        {
+            if ((string)control == USER)
+            {
+                CheckNotServer();
+                user = (String)value;
+                return;
+            }
+
+            if ((string)control == PASSWORD)
+            {
+                CheckNotServer();
+                password = (String)value;
+                return;
+            }
+
+            if ((string)control == AUTHENTICATE)
+            {
+                CheckNotServer();
+                SendPwAuthReq();
+                return;
+            }
+
+            base.TransportControl(control, value);
+        }
+
+        private void CheckNotServer()
+        {
+            if (server)
+                throw new Exception("control not permitted by server");
+        }
+
+
+        private void SessionNotifyUser(String user, String password)
+        {
+            this.user = user;
+            this.password = password;
+            session.SessionNotify(new UserPassword(user, password));
+        }
+
+        /// <summary>
+        /// Server session query response to AuthUserPassword.
+        /// </summary>
+        public class OkStatus
+        {
+            /// <summary>Constructs the AuthOkStatus.</summary>
+            /// <param name="ok">true if user / password valid.</param>
+            /// <param name="status">message related to ok.</param>
+            public OkStatus(bool ok, String status)
+            {
+                this.ok = ok;
+                this.status = status;
+            }
+
+
+            public override String ToString()
+            {
+                return String.Format("AuthOkStatus( %s, %s )", ok, status);
+            }
+
+            // true if the user / password matched 
+            public readonly bool ok;
+
+            // message related to ok
+            public readonly String status;
+        }
+
+        /// <summary>
+        /// Server session query to get AuthOkStatus, also server session event
+        /// to report changes in authentication status.
+        /// </summary>
+        public class UserPassword
+        {
+
+            /// <summary>Constructs the CheckAuth.</summary>
+            /// <param name="user">name to check</param>
+            /// <param name="password">password of the user</param>
+            public UserPassword(String user, String password)
+            {
+                this.user = user;
+                this.password = password;
+            }
+
+
+            public override String ToString()
+            {
+                return String.Format("AuthUserPassword( %s )", user);
+            }
+
+            // The user name to check
+            public readonly String user;
+
+            // The password of the user
+            public readonly String password;
+        }
+
+
+        public override string ToString()
+        {
+            return "PwAuth/" + transport;
+        }
+    }
+
+
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/Binary/BinaryTaggedData.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/Binary/BinaryTaggedData.cs
new file mode 100644
index 0000000..26efbfc
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/Binary/BinaryTaggedData.cs
@@ -0,0 +1,247 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Fmt.Binary
+{
+    /// <summary>
+    /// Common elements for binary tagged data input and output.
+    /// </summary>
+    public class BinaryTaggedData : TaggedData
+    {
+        /// <summary>
+        /// Sentinel which marks the end of a struct or array item list
+        /// in a binary input or output stream.
+        /// </summary>
+
+        public class SentinelObject
+        {
+            public override string ToString()
+            {
+                return "NONE";
+            }
+        }
+        public static readonly SentinelObject NONE = new SentinelObject();
+
+
+        /// <summary>
+        /// This is the current version of the protocol.
+        /// </summary>
+        public const sbyte VERSION = 3;
+
+        public BinaryTaggedData()
+        {
+            // do nothing
+        }
+
+        /// <summary>
+        /// Constructs the BinaryTaggedData.
+        /// </summary>
+        /// <param name="vf"></param>
+        public BinaryTaggedData(ValueFactory vf)
+            : base(vf)
+        {
+        }
+
+
+        public override sbyte CheckValue(object value)
+        {
+            if (value == null)
+                return TypeCode.NULL;
+            else if (value == NONE)
+                return TypeCode.NONE;
+
+            Type type = value.GetType();
+
+            if (value is long)
+                return CheckLong((long)value);
+
+            else if (value is Int32)
+                return CheckInteger((Int32)value);
+
+            else if (value is short)
+                return CheckShort((short)value);
+
+            else if (value is SByte)
+                return CheckByte((sbyte)value);
+
+            else if (value is Double)
+                return (sbyte)TypeCode.DOUBLE;
+
+            else if (value is float)
+                return (sbyte)TypeCode.FLOAT;
+
+            else if (value is String)
+            {
+                String s = (String)value;
+                if (s.Length == 0)
+                    return TypeCode.EMPTY_STRING;
+
+                return TypeCode.STRING;
+            }
+
+            else if (value is Boolean)
+            {
+                if ((Boolean)value)
+                    return TypeCode.BOOLEAN_TRUE;
+
+                return TypeCode.BOOLEAN_FALSE;
+            }
+
+            else if (value is StructValue)
+                return TypeCode.CUSTOM;
+
+
+            else if (value is Array)
+            {
+                Array a = (Array)value;
+                //if (a.GetType() == typeof(Int32[]))
+                //    return TypeCode.INTS;
+                //if (a.GetType() == typeof(Int16[]))
+                //    return TypeCode.SHORTS;
+                //if (a.GetType() == typeof(Boolean[]))
+                //    return TypeCode.BOOLS;
+                if (a.GetType() == typeof(SByte[]))
+                    return TypeCode.BYTES;
+                //if (a.GetType() == typeof(Int64[]))
+                //    return TypeCode.LONGS;
+                //if (a.GetType() == typeof(Single[]))
+                //    return TypeCode.FLOATS;
+                //if (a.GetType() == typeof(Double[]))
+                //    return TypeCode.DOUBLES;
+                return TypeCode.ARRAY;
+
+            }
+
+            return TypeCode.CUSTOM;
+
+        }
+
+        public override sbyte GetNativeTypeCode(Type c)
+        {
+            if (c == typeof(Boolean))
+                return TypeCode.BOOLEAN_TRUE;
+
+            if (c == typeof(SByte))
+                return TypeCode.BYTE;
+
+            if (c == typeof(short))
+                return TypeCode.SHORT;
+
+            if (c == typeof(int))
+                return TypeCode.INT;
+
+            if (c == typeof(long))
+                return TypeCode.LONG;
+
+            if (c == typeof(float))
+                return TypeCode.FLOAT;
+
+            if (c == typeof(double))
+                return TypeCode.DOUBLE;
+
+            if (c == typeof(string))
+                return TypeCode.STRING;
+
+            if (c == typeof(Object))
+                return TypeCode.ANY;
+
+            return TypeCode.CUSTOM;
+        }
+
+        public override XType GetCustomStructType(Type c)
+        {
+            return vf.GetCustomStructType(c);
+        }
+
+
+
+        public override Type GetNativeType(sbyte type)
+        {
+            switch (type)
+            {
+                case TypeCode.BOOLEAN_TRUE:
+                case TypeCode.BOOLEAN_FALSE:
+                    return typeof(Boolean);
+
+                case TypeCode.BYTE:
+                    return typeof(sbyte);
+
+                case TypeCode.SHORT:
+                    return typeof(short);
+
+                case TypeCode.INT:
+                    return typeof(int);
+
+                case TypeCode.LONG:
+                    return typeof(long);
+
+                case TypeCode.FLOAT:
+                    return typeof(float);
+
+                case TypeCode.DOUBLE:
+                    return typeof(double);
+
+                case TypeCode.EMPTY_STRING:
+                case TypeCode.STRING:
+                    return typeof(string);
+
+                case TypeCode.ANY:
+                    return typeof(Object);
+
+                default:
+                    throw new Exception("unsupported native type " + type);
+            }
+        }
+
+        private static sbyte CheckByte(sbyte v)
+        {
+            if (v >= TypeCode.MIN_TINY_INT && v <= TypeCode.MAX_TINY_INT)
+                return v;
+            return TypeCode.BYTE;
+        }
+
+        private static sbyte CheckShort(short v)
+        {
+            if (v >= SByte.MinValue && v <= SByte.MaxValue)
+                return CheckByte((sbyte)v);
+
+            return TypeCode.SHORT;
+        }
+
+        private static sbyte CheckInteger(int v)
+        {
+            if (v >= short.MinValue && v <= short.MaxValue)
+                return CheckShort((short)v);
+
+            return TypeCode.INT;
+        }
+
+        private static sbyte CheckLong(long v)
+        {
+            if (v >= int.MinValue && v <= int.MaxValue)
+                return CheckInteger((int)v);
+
+            return TypeCode.LONG;
+        }
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/Binary/BinaryTaggedDataFormatFactory.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/Binary/BinaryTaggedDataFormatFactory.cs
new file mode 100644
index 0000000..97e1ec4
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/Binary/BinaryTaggedDataFormatFactory.cs
@@ -0,0 +1,38 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Fmt.Binary
+ 
+{
+    public class BinaryTaggedDataFormatFactory : FormatFactory
+    {
+        
+        public BinaryTaggedDataFormatFactory() {}
+        
+        public override TaggedDataInput NewTaggedDataInput( Org.Apache.Etch.Bindings.Csharp.Msg.ValueFactory vf, string uri )
+        {
+            return new BinaryTaggedDataInput( vf, uri );
+        }
+
+        public override TaggedDataOutput NewTaggedDataOutput( Org.Apache.Etch.Bindings.Csharp.Msg.ValueFactory vf, string uri )
+        {
+            return new BinaryTaggedDataOutput( vf, uri );
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/Binary/BinaryTaggedDataInput.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/Binary/BinaryTaggedDataInput.cs
new file mode 100644
index 0000000..fbf9b3c
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/Binary/BinaryTaggedDataInput.cs
@@ -0,0 +1,398 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.IO;
+using System.Text;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Fmt.Binary
+{
+    /// <summary>
+    /// TaggedDataInputStream has methods to support reading little-endian integer
+    /// and floating point data types as well as tagged values from an input
+    /// stream.
+    /// </summary>
+    public class BinaryTaggedDataInput : BinaryTaggedData, TaggedDataInput
+    {
+        /// <summary>
+        /// Constructs the BinaryTaggedDataInput.
+        /// </summary>
+        /// <param name="vf">the value factory for the service.</param>
+        /// <param name="uri">the uri used to construct the transport stack.</param>
+        public BinaryTaggedDataInput( ValueFactory vf, string uri )
+            : base( vf )
+        {
+            // do nothing.
+        }
+
+        /////////////////////////////
+        // TaggedDataInput methods //
+        /////////////////////////////
+
+
+        public Message ReadMessage(FlexBuffer buf1)
+        {
+            buf = buf1;
+            
+            // lengthBudget is how many array elements total are reasonable to
+            // allocate while parsing this message. the largest value comes as each
+            // byte of the incoming message turned into an array element. the total
+            // will always be lower than this as often it takes multiple bytes to
+            // make a single array element. so, each time we make an array, we
+            // deduct the specified length from lengthBudget. if the result is
+            // negative, then either the incoming message is misformed or someone is
+            // trying to spoof us.
+            
+            lengthBudget = buf.Avail();
+
+            try
+            {
+                Message msg = StartMessage();
+                ReadKeysAndValues(msg);
+                EndMessage(msg);
+                return msg;
+            }
+            finally
+            {
+                buf = null;
+                lengthBudget = 0;
+            }
+        }
+
+        private FlexBuffer buf;
+
+        private int lengthBudget;
+
+        private StructValue ReadStruct()
+        {
+            StructValue sv = StartStruct();
+            ReadKeysAndValues( sv );
+            EndStruct( sv );
+            return sv;
+
+        }
+
+        private ArrayValue ReadArray( Validator v )
+        {
+            ArrayValue av = StartArray();
+            ReadValues( av, v );
+            EndArray( av );
+            return av;
+        }
+
+
+        private void ReadKeysAndValues( StructValue sv )
+        {
+            XType t = sv.GetXType;
+
+            while ( true )
+            {
+                Field key = ReadField( t );
+                if (key == null)
+                    break;
+
+                //Object obj = ReadValue( intValidator, true );
+                //if ( obj == NONE )
+                //    break;
+
+                //int id = ( int ) obj;
+                //Field key = t.GetField( id );
+                //if (key == null)
+                //    key = new Field(id, id.ToString());
+
+                Validator v = t.GetValidator( key );
+                if (v != null)
+                {
+                    sv.Add(key, ReadValue(v));
+                }
+                else
+                {
+                    // read the value but ignore it.
+                    Object obj = ReadValue(Validator_object.Get(0));
+                    if (false)
+                        sv.Add( key, obj );
+                }
+            }
+        }
+
+        private void ReadValues( ArrayValue av, Validator v )
+        {
+            Validator ev = v.ElementValidator();
+            while ( true )
+            {
+                Object value = ReadValue( ev, true );
+                if ( value == NONE )
+                    break;
+
+                av.Add( value );
+            }
+        }
+
+        ////////////////////////
+        // Main input methods //
+        ////////////////////////
+
+        private Message StartMessage()
+        {
+            sbyte version = buf.GetByte();
+			
+			if (version != VERSION)
+				throw new IOException(
+					"binary tagged data version mismatch: got "+version+" expected "+VERSION );
+
+            XType t = ReadType();
+            int length = ReadLength();
+
+            return new Message(t, vf, length);
+        }
+
+        private void EndMessage( Message msg )
+        {
+            // nothing to do., readKeysAndValues swallowed the NONE.
+        }
+
+        private StructValue StartStruct() 
+	    {
+            XType t = ReadType();
+            int length = ReadLength();
+
+            return new StructValue(t, vf, length);
+	    }
+
+        private void EndStruct( StructValue sv )
+        {
+            // nothing to do, readKeysAndValues swallowed the NONE.
+        }
+
+        private ArrayValue StartArray()
+        {
+            sbyte type = buf.GetByte();
+
+            XType customStructType;
+            if(type == TypeCode.CUSTOM || type == TypeCode.STRUCT)
+                customStructType = ReadType();
+            else
+                customStructType = null;
+
+            int dim = ReadIntegerValue();
+            if (dim <= 0 || dim > Validator.MAX_NDIMS)
+                throw new ArgumentException("dim <= 0 || dim > Validator.MAX_NDIMS");
+
+            int length = ReadLength();
+
+            Object array = AllocateArrayValue( type, customStructType, dim, length );
+
+            return new ArrayValue( array, type, customStructType, dim );
+        }
+
+        private void EndArray(ArrayValue array)
+        {
+            array.Compact();
+        }
+
+        private XType ReadType()
+        {
+            Object obj = ReadValue(intOrStrValidator, false);
+            if (obj is int)
+            {
+                int id = (int)obj;
+                XType type = vf.GetType(id);
+
+                if (type == null)
+                    type = new XType(id, id.ToString());
+
+                return type;
+            }
+
+            String name = (String)obj;
+            XType ntype = vf.GetType(name);
+
+            if (ntype == null)
+                ntype = new XType(name);
+
+            return ntype;
+        }
+
+        private Field ReadField( XType type )
+        {
+            Object obj = ReadValue(intOrStrValidator, true);
+
+            if (obj == NONE)
+                return null;
+
+            if (obj is int)
+            {
+                int id = (int)obj;
+                Field field = type.GetField(id);
+
+                if (field == null)
+                    field = new Field(id, id.ToString());
+
+                return field;
+            }
+
+            String name = (String)obj;
+            Field nfield = type.GetField(name);
+
+            if (nfield == null)
+                nfield = new Field(name);
+
+            return nfield;
+        }
+        
+        private readonly Validator intOrStrValidator =
+		    new ComboValidator( Validator_int.Get( 0 ), Validator_string.Get( 0 ) );
+
+        private int ReadLength()
+        {
+            int length = ReadIntegerValue();
+
+            if (length < 0 || length > lengthBudget)
+                throw new ArgumentException(
+                    "length < 0 || length > lengthBudget");
+            
+            lengthBudget -= length;
+
+            return length;
+        }
+
+        private int ReadIntegerValue() 
+	    {
+            return (int)ReadValue(intValidator);
+	    }
+
+        private readonly Validator intValidator = Validator_int.Get( 0 );
+
+        ///////////////////////////
+        // LOCAL UTILITY METHODS //
+        ///////////////////////////
+
+        private Object ValidateValue(Validator v, Object value)
+        {
+            // v == null more or less implies that a field is not known
+            // for a type. thus we don't care about the field value as
+            // we are going to ignore it. therefore, return null.
+
+            if (v == null)
+                return null;
+
+            if (value == null)
+                return null;
+
+            return v.ValidateValue(value);
+        }
+
+        private Object ValidateValue( Validator v, Boolean noneOk, Object value )
+        {
+            if (noneOk && value == NONE)
+                return value;
+
+            return ValidateValue(v, value);
+        }
+
+        private Object ReadValue( Validator v )
+        {
+            return ReadValue( v, false );
+        }
+
+        private Object ReadValue( Validator v, Boolean noneOk )
+        {
+            sbyte type = buf.GetByte();
+
+            switch ( type )
+            {
+                case TypeCode.NULL:
+                    return ValidateValue( v, null );
+
+                case TypeCode.NONE:
+                    return ValidateValue(v, noneOk, NONE);
+
+                case TypeCode.BOOLEAN_FALSE:
+                    return ValidateValue( v, false );
+
+                case TypeCode.BOOLEAN_TRUE:
+                    return ValidateValue( v, true );
+
+                case TypeCode.BYTE:
+                    return  ValidateValue( v, buf.GetByte() );
+
+                case TypeCode.SHORT:
+                    return  ValidateValue( v, buf.GetShort() );
+
+                case TypeCode.INT:
+                    return  ValidateValue( v, buf.GetInt() );
+
+                case TypeCode.LONG:
+                    return ValidateValue( v, buf.GetLong() );
+
+                case TypeCode.FLOAT:
+                    return ValidateValue( v, buf.GetFloat() );
+
+                case TypeCode.DOUBLE:
+                    return ValidateValue( v, buf.GetDouble() );
+
+                case TypeCode.BYTES:
+                    return ValidateValue( v, ReadSbytes() );
+
+                case TypeCode.EMPTY_STRING:
+                    return ValidateValue( v, "" );
+
+                case TypeCode.STRING:
+                    return ValidateValue( v, Encoding.UTF8.GetString( ReadBytes() ) );
+
+                //case TypeCode.BOOLS:
+                //case TypeCode.SHORTS:
+                //case TypeCode.INTS:
+                //case TypeCode.LONGS:
+                //case TypeCode.FLOATS:
+                //case TypeCode.DOUBLES:
+                case TypeCode.ARRAY:
+                    return ValidateValue( v, FromArrayValue( ReadArray( v ) ) );
+
+                case TypeCode.STRUCT:
+                case TypeCode.CUSTOM:
+                    return ValidateValue( v, vf.ImportCustomValue( ReadStruct() ) );
+
+                default:
+                    if (type >= TypeCode.MIN_TINY_INT && type <= TypeCode.MAX_TINY_INT)
+                        return ValidateValue(v, type);
+                    throw new Exception( "unsupported type code "+type );
+            }
+        }
+
+        private byte[] ReadBytes()
+        {
+            int length = ReadLength();
+            byte[] b = new byte[ length ];
+            buf.GetFully( b );
+            return b;
+        }
+
+        private sbyte[] ReadSbytes()
+        {
+            int length = ReadLength();
+            sbyte[] b = new sbyte[length];
+            buf.GetFully((byte[])(Array)b);
+            return b;
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/Binary/BinaryTaggedDataOutput.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/Binary/BinaryTaggedDataOutput.cs
new file mode 100644
index 0000000..f1508f7
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/Binary/BinaryTaggedDataOutput.cs
@@ -0,0 +1,364 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Fmt.Binary
+{
+    /// <summary>
+    /// An implementation of TaggedDataOutput which uses a binary encoding.
+    /// </summary>
+    public sealed class BinaryTaggedDataOutput : BinaryTaggedData, TaggedDataOutput
+    {
+        /// <summary>
+        /// Name of uri parameter which controls whether we write ints or strings
+        /// for types and fields.
+        /// </summary>
+        public const String STRING_TYPE_AND_FIELD =
+		    "BinaryTaggedDataOutput.stringTypeAndField";
+
+        /// <summary>
+        /// Constructs the BinaryTaggedDataOutput with a null buffer.
+        /// </summary>
+        /// <param name="vf">the value factory for the service.</param>
+        /// <param name="uri">the uri used to construct the transport stack.</param>
+        public BinaryTaggedDataOutput(ValueFactory vf, string uri)
+            : base(vf)
+        {
+            this.level = vf.GetLevel();
+            URL u = new URL(uri);
+            stringTypeAndField = u.GetBooleanTerm(STRING_TYPE_AND_FIELD, false);
+        }
+
+        private readonly Validator.Level level;
+
+        private readonly bool stringTypeAndField;
+
+        //////////////////////////////
+        // TaggedDataOutput methods //
+        //////////////////////////////
+
+        #region TaggedDataOutput methods
+
+        public void WriteMessage(Message msg, FlexBuffer buf)
+        {
+            try
+            {
+                this.buf = buf;
+                StartMessage(msg);
+                WriteKeysAndValues(msg);
+                EndMessage(msg);
+            }
+            finally
+            {
+                this.buf = null;
+            }
+        }
+
+        private FlexBuffer buf;
+
+        private void WriteStruct(StructValue sv)
+        {
+            StartStruct(sv);
+            WriteKeysAndValues(sv);
+            EndStruct(sv);
+        }
+
+        private void WriteArray(ArrayValue av, Validator v)
+        {
+            StartArray(av);
+            WriteValues(av, v);
+            EndArray(av);
+        }
+
+        private void WriteKeysAndValues(StructValue sv)
+        {
+            XType t = sv.GetXType;
+            foreach (KeyValuePair<Field, Object> me in sv)
+            {
+                Field f = me.Key;
+                WriteField(f);
+                WriteValue(t.GetValidator(f), me.Value);
+            }
+        }
+
+        private void WriteValues(ArrayValue av, Validator v)
+        {
+            Validator ev = v.ElementValidator();
+            foreach (Object value in av)
+                WriteValue(ev, value);
+        }
+
+
+        /////////////////////////
+        // Main output methods //
+        /////////////////////////
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="msg"></param>
+        /// Exception:
+        ///     throws Exception
+        private void StartMessage(Message msg)
+        {
+            // since message is top-level, no type code is written to
+            // indicate a message is starting. we do write a version number
+            // to indicate this version of the binary tagged data output
+            buf.PutByte(VERSION);
+            StartStruct(msg);
+            //       WriteType( msg.GetXType );
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="msg"></param>
+        /// Exception:
+        ///     throws Exception
+        private void EndMessage(Message msg)
+        {
+            EndStruct(msg);
+
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="sv"></param>
+        /// Exception:
+        ///     throws Exception
+        private void StartStruct(StructValue sv)
+        {
+            // the caller has already written a type code to indicate a
+            // struct is starting.
+            WriteType(sv.GetXType);
+            WriteIntValue(sv.Count);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="sv"></param>
+        /// Exception:
+        ///     throws Exception
+        private void EndStruct(StructValue sv)
+        {
+            WriteNoneValue();
+        }
+
+        private readonly IList<StructValue> structs = new List<StructValue>();
+
+        private void StartArray(ArrayValue array)
+        {
+            // the caller has already written a type code to indicate an
+            // array is starting.
+            sbyte type = array.Type;
+            buf.PutByte(type);
+            if (type == TypeCode.CUSTOM)
+                WriteType(array.CustomStructType);
+            WriteIntValue(array.Dim);
+            WriteIntValue(array.Size());
+
+        }
+
+        private void WriteType(XType type)
+        {
+            if (stringTypeAndField)
+                WriteStringValue(type.Name);
+            else
+                WriteIntValue(type.Id);
+        }
+
+        private void WriteField(Field field)
+        {
+            if (stringTypeAndField)
+                WriteStringValue(field.Name);
+            else
+                WriteIntValue(field.Id);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="array"></param>
+        /// Exception:
+        ///     throws Exception
+        private void EndArray(ArrayValue array)
+        {
+            WriteNoneValue();
+        }
+
+        private void WriteIntValue(int value)
+        {
+            WriteValue(intValidator, value);
+        }
+
+        private readonly Validator intValidator = Validator_int.Get(0);
+
+        private void WriteStringValue(String value)
+        {
+            WriteValue(stringValidator, value);
+        }
+
+        private readonly Validator stringValidator = Validator_string.Get(0);
+
+        private void WriteNoneValue()
+        {
+            WriteValue(noneValidator, NONE);
+        }
+
+        private readonly Validator noneValidator = Validator_none.Get();
+
+        #endregion
+
+        ///////////////////////////
+        // LOCAL UTILITY METHODS //
+        ///////////////////////////
+
+        #region Local Utility Methods
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="v">the validator for this value, or none if there
+        /// isn't one</param>
+        /// <param name="value"></param>
+        /// Exception:
+        ///     throws Exception
+        private void WriteValue(Validator v, Object value)
+        {
+            sbyte typeCode = CheckValue(value);
+
+            if (level != Validator.Level.NONE && value != null)
+            {
+                if (level == Validator.Level.FULL && v == null)
+                    throw new ArgumentException("validator missing");
+                
+                if (v != null && !v.Validate(value))
+                    throw new ArgumentException( String.Format(
+                        "validator {0} failed for value {1}", v, value));
+            }
+
+            buf.PutByte(typeCode);
+
+            switch (typeCode)
+            {
+                case TypeCode.NULL:
+                case TypeCode.BOOLEAN_FALSE:
+                case TypeCode.BOOLEAN_TRUE:
+                case TypeCode.EMPTY_STRING:
+                case TypeCode.NONE:
+                    return;
+
+                case TypeCode.BYTE:
+                    buf.PutByte((Convert.ToSByte(value)));
+                    return;
+                case TypeCode.SHORT:
+                    buf.PutShort(Convert.ToInt16(value));
+                    return;
+
+                case TypeCode.INT:
+                    buf.PutInt(Convert.ToInt32(value));
+                    return;
+
+                case TypeCode.LONG:
+                    buf.PutLong(Convert.ToInt64(value));
+                    return;
+
+                case TypeCode.FLOAT:
+                    buf.PutFloat(Convert.ToSingle(value));
+                    return;
+
+                case TypeCode.DOUBLE:
+                    buf.PutDouble(Convert.ToDouble(value));
+                    return;
+
+                case TypeCode.BYTES:
+                    WriteBytes((sbyte[])value);
+                    return;
+
+                // reserved for future use
+                //case TypeCode.BOOLS:
+                //case TypeCode.SHORTS:
+                //case TypeCode.INTS:
+                //case TypeCode.LONGS:
+                //case TypeCode.FLOATS:
+                //case TypeCode.DOUBLES:
+                case TypeCode.ARRAY:
+                    WriteArray(ToArrayValue(value, v), v);
+                    return;
+
+                case TypeCode.STRING:
+                    WriteBytes(Encoding.UTF8.GetBytes((String)value));
+                    return;
+
+                case TypeCode.CUSTOM:
+                    {
+                        StructValue sv = vf.ExportCustomValue(value);
+                        if (sv == null)
+                            throw new Exception("unsupported type " + value.GetType());
+
+                        WriteStruct(sv);
+                        return;
+                    }
+
+                default:
+                    // type is either "tiny" integer or unused...
+                    if (typeCode >= TypeCode.MIN_TINY_INT && typeCode <= TypeCode.MAX_TINY_INT)
+                        return;
+
+                    throw new Exception("unsupported typecode " + typeCode);
+            }
+        }
+
+        /// <summary>
+        /// Writes a value (signed or unsigned) to the output stream.
+        /// </summary>
+        /// <param name="value">the value to write to the output stream.</param>
+        /// Exception:
+        ///     throws Exception if there's a problem with the output stream
+        private void WriteBytes(sbyte[] value)
+        {
+            int n = value.Length;
+            WriteIntValue(n);
+            buf.Put((byte[])(Array)value, 0, n);
+        }
+
+        /// <summary>
+        /// Writes a value (signed or unsigned) to the output stream.
+        /// </summary>
+        /// <param name="value">the value to write to the output stream.</param>
+        /// Exception:
+        ///     throws Exception if there's a problem with the output stream
+        private void WriteBytes(byte[] value)
+        {
+            int n = value.Length;
+            WriteIntValue(n);
+            buf.Put(value, 0, n);
+        }
+
+        #endregion Local utility methods
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/Binary/Validator_none.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/Binary/Validator_none.cs
new file mode 100644
index 0000000..3705dc9
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/Binary/Validator_none.cs
@@ -0,0 +1,68 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Fmt.Binary
+{
+    /// <summary>
+    /// A validator for the special end of list marker,
+    /// </summary>
+    public class Validator_none : Validator
+    {
+        public static Validator_none Get()
+        {
+            if ( validator == null )
+                validator = new Validator_none();
+            return validator;
+        }
+
+        private static Validator_none validator;
+
+        /// <summary>
+        /// constructs the validator
+        /// </summary>
+        public Validator_none()
+        {
+            //nothing to do
+        }
+
+        public override Validator ElementValidator()
+        {
+        
+            throw new ArgumentException("not an array");
+        }
+
+        public override bool Validate( Object value )
+        {
+            return value == BinaryTaggedData.NONE;
+        }
+
+      
+
+        public override object ValidateValue(object value)
+        {
+            if (Validate(value))
+                return value;
+
+            throw new Exception("value not appropriate for none: " + value);
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/ByteToSbyteConverter.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/ByteToSbyteConverter.cs
new file mode 100644
index 0000000..5c8b6a7
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/ByteToSbyteConverter.cs
@@ -0,0 +1,55 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Fmt
+{
+    /// <summary>
+    /// Class that provides methods for : 
+    /// 1) Converting a single value from byte to sbyte.
+    /// 2) Converting a single value for sbyte to byte.
+    /// 3) Converting an array of values of the 2 above.
+    /// </summary>
+    public static class ByteConverter
+    {
+        /// <summary>
+        /// Converts a byte value to an sbyte value.
+        /// </summary>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public static sbyte ByteToSbyte( byte value )
+        {
+            sbyte convertedValue = 0;
+
+            if ( value > 127 )
+                convertedValue = ( sbyte ) ( 127 - value );
+
+            return convertedValue;
+        }
+
+        public static byte SbyteToByte( sbyte value )
+        {
+            byte convertedValue = 0;
+
+            if ( value < 0 )
+                convertedValue = ( byte ) ( 127 - value );
+
+            return convertedValue;
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/TaggedData.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/TaggedData.cs
new file mode 100644
index 0000000..85195d4
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/TaggedData.cs
@@ -0,0 +1,203 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Fmt
+{
+    /// <summary>
+    /// Common interface for various types of tagged data input and output.
+    /// </summary>
+    abstract public class TaggedData
+    {
+        public TaggedData()
+        { 
+        }
+
+        /// <summary>
+        /// Constructs the TaggedData.
+        /// </summary>
+        /// <param name="vf"></param>
+        public TaggedData( ValueFactory vf )
+        {
+            this.vf = vf;
+        }
+
+        /// <summary>
+        /// The value factory to use for tagged input and output.
+        /// </summary>
+        protected readonly ValueFactory vf;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the value factory to use for tagged input and output.</returns>
+        public ValueFactory GetValueFactory()
+        {
+            return vf;
+        }
+
+
+        protected ArrayValue ToArrayValue( Object value, Validator v )
+        {
+
+            Type c = value.GetType();
+            int dim = 0;
+
+            while ( c.IsArray )
+            {
+                dim++;
+                c = c.GetElementType();
+            }
+            
+            // now we want the type code for c, and if the type code is custom,
+            // we'll also want the struct type code.
+
+            sbyte typeCode = GetNativeTypeCode( c );
+
+            XType customStructType;
+            if (typeCode == TypeCode.CUSTOM || typeCode == TypeCode.STRUCT)
+            {
+                customStructType = GetCustomStructType(c);
+
+                if (customStructType == null && c == typeof(StructValue))
+			    {
+				    Validator_StructValue x = FindStructValueValidator( v );
+                    if (x != null)
+                        customStructType = x.GetXType();
+			    }
+			
+			if (customStructType == null )
+				throw new ArgumentException(" In tagged Data" );
+   
+            }
+               
+            else
+                customStructType = null;
+
+            return new ArrayValue( value, typeCode, customStructType, dim );
+        }
+
+        private Validator_StructValue FindStructValueValidator( Validator v )
+	    {
+		    if (v is Validator_StructValue)
+			return (Validator_StructValue) v;
+		
+		    if (v is ComboValidator)
+		    {
+			    ComboValidator x = (ComboValidator) v;
+			    Validator_StructValue y = FindStructValueValidator( x.A() );
+			
+			    if (y != null)
+				    return y;
+			
+		    	 return FindStructValueValidator( x.B() );
+		    }
+		
+		    return null;
+	    }
+
+        protected Object FromArrayValue( ArrayValue av )
+        {
+            return av.GetArray();
+        }
+
+        protected Object AllocateArrayValue( sbyte typeCode, XType customStructType,
+            int dim, int length )
+        {
+            Type clss = GetComponentType( typeCode, customStructType, dim );
+            if ( clss == null )
+                throw new ArgumentException(String.Format(
+                    "could not get array for {0}, {1}, {2}",
+                    typeCode, customStructType, dim));
+            
+            return Array.CreateInstance( clss, length );
+        }
+
+        private Type GetComponentType( sbyte typeCode, XType customStructType, int dim )
+        {
+            Type c;
+            if (typeCode == TypeCode.CUSTOM || typeCode == TypeCode.STRUCT)
+            {
+                //    c = GetCustomType( customStructType );
+                c = customStructType.GetComponentType();
+                if (c == null)
+                    c = typeof (StructValue);
+            }
+                
+            else
+                c = GetNativeType(typeCode);
+            //Console.WriteLine( "c = " + c );
+            if ( c == null )
+                return null;
+
+            if ( dim == 0 )
+                return c;
+
+            int[] dims;
+
+            while ( dim > 0 )
+            {
+                dims = new int[ dim ];
+                if ( dim > 1 )
+                    c = c.MakeArrayType();
+                dim--;
+            }
+
+            //Object o = Array.CreateInstance( c, 1 );
+
+            //c = ( ( Array ) o ).GetType();
+            //Console.WriteLine( "type= "+c );
+            return c;
+        }
+
+        /// <summary>
+        /// Returns the type code for the specified class. This
+	    /// is needed when we have an array and we have determine
+	    /// the base type and now we're fixing to serialize it.
+	    /// We use the base type code to reconstitute it on the
+	    /// other side. So we don't return a perfect code the way
+	    /// checkValue does, but rather just something that let's
+	    /// us recreate the appropriate array type on import.
+        /// </summary>
+        /// <param name="c"></param>
+        /// <returns>a type code for the specified class.</returns>
+        abstract public sbyte GetNativeTypeCode( Type c );
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="c"></param>
+        /// <returns>a struct type for the specified custom class.</returns>
+        abstract public XType GetCustomStructType( Type c );
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="type"></param>
+        /// <returns>the class for a specified (native) type code.</returns>
+        abstract public Type GetNativeType( sbyte type );
+
+        
+
+        abstract public sbyte CheckValue( Object value );
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/TypeCode.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/TypeCode.cs
new file mode 100644
index 0000000..3faffc3
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Fmt/TypeCode.cs
@@ -0,0 +1,185 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Fmt
+{
+    /// <summary>
+    /// Values denoting types of encoded values. There are two value ranges:
+    /// 
+    ///  -128 to -65: codes for defined types.
+    /// -64 to 127: tiny integer values.
+    ///            
+    /// Tiny integers are completely encoded within the type byte.
+    /// </summary>
+    public class TypeCode
+    {
+        /// <summary>
+        /// A code denoting a null value.
+        /// </summary>
+        public const sbyte NULL = -128;
+
+        /// <summary>
+        /// A code denoting no value. 
+        /// For example, an array is a sequence of values (some of which may
+	    /// be NULL), terminated by a NONE.
+        /// </summary>
+        public const sbyte NONE = -127;
+
+
+        /// <summary>
+        /// A code denoting a false boolean value.
+        /// </summary>
+        public const sbyte BOOLEAN_FALSE = -126;
+
+        /// <summary>
+        /// A code denoting a true boolean value.
+        /// </summary>
+        public const sbyte BOOLEAN_TRUE = -125;
+
+        /// <summary>
+        /// A code denoting a signed const sbyte.
+        /// </summary>
+        public const sbyte BYTE = -124;
+
+        /// <summary>
+        /// A code denoting a single const sbyte signed short.
+        /// </summary>
+        public const sbyte SHORT = -123;
+
+        /// <summary>
+        /// A code denoting a four sbyte signed integer.
+        /// </summary>
+        public const sbyte INT = -122;
+             
+        /// <summary>
+        /// A code denoting an eight const sbyte signed long, lsb first.
+        /// </summary>
+        public const sbyte LONG = -121;
+
+        /// <summary>
+        /// A code denoting a four const sbyte ieee floating format number.
+        /// </summary>
+        public const sbyte FLOAT = -120;
+
+        /// <summary>
+        /// A code denoting an eight const sbyte ieee floating format number.
+        /// </summary>
+        public const sbyte DOUBLE = -119;
+
+        //// Arrays /////
+
+        /// <summary>
+        /// A code denoting an array of booleans.
+        /// </summary>
+        //public const sbyte BOOLS = -118;
+
+        /// <summary>
+        /// A code denoting an array of bytes.
+        /// </summary>
+        public const sbyte BYTES = -117;
+
+        /// <summary>
+        /// A code denoting an array of shorts.
+        /// </summary>
+        //public const sbyte SHORTS = -116;
+
+        /// <summary>
+        /// A code denoting an array of ints.
+        /// </summary>
+        //public const sbyte INTS = -115;
+
+        /// <summary>
+        /// A code denoting an array of longs.
+        /// </summary>
+        //public const sbyte LONGS = -114;
+
+        /// <summary>
+        /// A code denoting an array of singles.
+        /// </summary>
+        //public const sbyte FLOATS = -113;
+
+        /// <summary>
+        /// A code denoting an array of doubles.
+        /// </summary>
+        //public const sbyte DOUBLES = -112;
+
+        /// <summary>
+        /// A code denoting a sequence of values.
+        /// </summary>
+        public const sbyte ARRAY = -111;
+
+
+        //// strings /////
+        
+        /// <summary>
+        /// A code denoting an empty string.
+        /// </summary>
+        public const sbyte EMPTY_STRING = -110;
+
+        /// <summary>
+        /// A code denoting a utf-8 encoded string.
+        /// </summary>
+        public const sbyte STRING = -109;
+
+        /// <summary>
+        /// A code denoting a custom value (struct, exception, enum, extern)
+	    /// from a value factory. An associated value identifies the specific
+	    /// type. The format on the wire of STRUCT and CUSTOM are the same.
+	    /// Emit CUSTOM instead of STRUCT, and accept STRUCT as if it were
+	    /// CUSTOM.
+        /// </summary>
+        public const sbyte STRUCT = -108;
+
+
+
+        /// <summary>
+        /// A code denoting a custom value (struct, exception, enum, extern)
+        /// from a value factory. An associated value identifies the specific
+        /// type. The format on the wire of STRUCT and CUSTOM are the same.
+        /// Emit CUSTOM instead of STRUCT, and accept STRUCT as if it were
+        /// CUSTOM.
+        /// </summary>
+        public const sbyte CUSTOM = -107;
+
+
+        /// <summary>
+        /// A code denoting that any value is ok (as long as we know how
+        /// to serialize it). Dynamic methods should be applied to determine
+        /// the type. This type never appears on the wire.
+        /// </summary>
+        public const sbyte ANY = -106;
+
+        ////////////////////
+        // tiny integers //
+        ////////////////////
+
+        /// <summary>
+        /// Minimum "small" integer.
+        /// </summary>
+        public const sbyte MIN_TINY_INT = -64;
+
+        /// <summary>
+        /// Maximum "small" integer. Small integers are encoded asis
+        /// (with embedded type code)
+        /// </summary>
+        public const sbyte MAX_TINY_INT = 127;
+
+        
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/FormatFactory.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/FormatFactory.cs
new file mode 100644
index 0000000..a48fed6
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/FormatFactory.cs
@@ -0,0 +1,101 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    public abstract class FormatFactory
+    {
+	    public const String BINARY = "binary";
+    	
+	    public const String XML = "xml";
+	
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="vf"></param>
+        /// <param name="uri"></param>
+        /// <returns>the tagged data input with the specified value factory and
+        /// initialized by terms from the uri.</returns>
+        abstract public TaggedDataInput NewTaggedDataInput( ValueFactory vf, string uri );
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="vf"></param>
+        /// <param name="uri"></param>
+        /// <returns>the tagged data output with the specified value factory and
+        /// initialized by terms from the uri.</returns>
+        abstract public TaggedDataOutput NewTaggedDataOutput( ValueFactory vf, string uri );
+
+        private readonly static Dictionary<String, Object> formatFactories = new Dictionary<String, Object>();
+
+        /// <summary>
+        /// Gets the named format factory.
+        /// </summary>
+        /// <param name="name">the name of a configured format factory.</param>
+        /// <returns>the named format factory, or null if it isn't defined.</returns>
+        public static FormatFactory Get( String name )
+        {
+            Object factory = formatFactories[name];
+
+            if (factory == null)
+                return null;
+            if (factory is string)
+            {
+                try
+                {
+                
+                    Type c = Type.GetType((string) factory);
+                    factory = Activator.CreateInstance(c);
+                    if (!(factory is FormatFactory))
+                        throw new ArgumentException(
+                            String.Format(" Instance for format name {0} does not implement FormatFactory {1}", name, factory));
+                    
+                 //   formatFactories.Add(name,factory);
+                   
+                }
+                catch(Exception e)
+                {
+                    throw new ArgumentException(" Could not create instance of format name " + name,e);
+                }
+            }
+           return (FormatFactory) factory;
+        }
+
+        /// <summary>
+        /// Puts a named format factory.
+        /// </summary>
+        /// <param name="name">the uri scheme of this format factory.</param>
+        /// <param name="factory">thefully qualified class name or instance
+        /// of the FormatFactory to associate with the name</param>
+        public static void Put( String name, Object factory )
+        {
+            formatFactories.Add( name, factory );
+        }
+
+        static FormatFactory()
+        {
+            Put(BINARY, "Org.Apache.Etch.Bindings.Csharp.Transport.Fmt.Binary.BinaryTaggedDataFormatFactory");
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/MailboxManager.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/MailboxManager.cs
new file mode 100644
index 0000000..ce49226
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/MailboxManager.cs
@@ -0,0 +1,53 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    public interface MailboxManager : TransportMessage, SessionMessage
+    {
+        /// <summary>
+        /// Removes the mailbox from the set of mailbox receiving responses
+        /// to messages
+        /// </summary>
+        /// <param name="mb"></param>
+        
+        void Unregister(Mailbox mb);
+
+        /// <summary>
+        /// Redelivers defunct messages from a closed mailbox.
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="msg"></param>
+
+        void Redeliver(Who sender, Message msg);
+
+        /// <summary>
+        /// Begin a call sequence and return the mailbox which will receive the
+        /// response.
+        /// </summary>
+        /// <param name="recipient"></param>
+        /// <param name="msg"></param>
+        /// <returns></returns>
+        Mailbox TransportCall(Who recipient, Message msg);
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Messagizer.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Messagizer.cs
new file mode 100644
index 0000000..219f968
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/Messagizer.cs
@@ -0,0 +1,197 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    /// <summary>
+    /// Messagizer is a PacketHandler which accepts packets from
+    /// a PacketSource and turns them into messages for delivery
+    /// to a MessageHandler. Messagizer is also a MessageSource,
+    /// accepting messages and turning them into packets for delivery
+    /// to a PacketSource.
+    /// </summary>
+    public class Messagizer : TransportMessage, SessionPacket
+    {
+        /// <summary>
+        /// Name of format name in uri or resources. The value is "Messagizer.format".
+        /// The result of looking up this name should be a String.
+        /// <seealso cref="Messagizer(TransportPacket, URL, Resources)"/>
+        /// </summary>
+        public const String FORMAT = "Messagizer.format";
+
+        /// <summary>
+        /// Constructs the Messagizer as a session of transport using uri and resources.
+        /// </summary>
+        /// <param name="transport">used to deliver packets to the peer.</param>
+        /// <param name="uri">the uri being used to configure the transport stack.</param>
+        /// <param name="resources">the associated set of resources for this service.</param>      
+        
+        public Messagizer(TransportPacket transport, string uri, Resources resources)
+        	: this(transport, new URL(uri), resources)
+        {
+        }
+
+
+        /// <summary>
+        /// Constructs the Messagizer as a session of transport using uri and resources.
+        /// </summary>
+        /// <param name="transport">used to deliver packets to the peer.</param>
+        /// <param name="uri">the uri being used to configure the transport stack.</param>
+        /// <param name="resources">the associated set of resources for this service.</param>
+        public Messagizer(TransportPacket transport, URL uri, Resources resources)
+        {
+            // find the format.
+
+            this.transport = transport;
+
+            String format = uri.GetTerm(FORMAT, FormatFactory.BINARY);
+
+            // find the format factory.
+
+            FormatFactory ff = FormatFactory.Get( format );
+            if ( ff == null )
+                throw new ArgumentException(
+                String.Format( "format factory is not defined as '{0}' in format factories", format ) );
+
+            // find the value factory.
+
+            ValueFactory vf = ( ValueFactory ) resources.Get( TransportConsts.VALUE_FACTORY );
+            if ( vf == null )
+                throw new ArgumentException(String.Format(
+                    "value factory is not defined as '{0}' in resources",
+                    TransportConsts.VALUE_FACTORY));
+
+            tdi = ff.NewTaggedDataInput( vf, uri.ToString() );
+            tdo = ff.NewTaggedDataOutput( vf, uri.ToString() );
+
+            transport.SetSession(this);
+        }
+
+      
+        // private readonly ValueFactory vf;
+        private readonly TaggedDataInput tdi;
+        private readonly TaggedDataOutput tdo;
+        private TransportPacket transport;
+        private SessionMessage session;
+
+        public override string ToString()
+        {
+            return String.Format("Messagizer : {0}", transport);
+        }
+
+        public TransportPacket GetTransport()
+        {
+            return transport;
+        }
+
+       
+
+        
+
+
+        private readonly FlexBuffer msgBuf = new FlexBuffer();
+
+        
+        public Object SessionQuery( Object query )
+        {
+            return session.SessionQuery( query );
+        }
+
+        public void SessionControl( Object control, Object value )
+        {
+            session.SessionControl( control, value );
+        }
+
+        public void SessionNotify( Object eventObj )
+        {
+            session.SessionNotify( eventObj );
+        }
+
+        
+
+        public Object TransportQuery( Object query )
+        {
+            return transport.TransportQuery( query );
+        }
+
+        public void TransportControl( Object control, Object value )
+        {
+            transport.TransportControl( control, value );
+        }
+
+        public void TransportNotify( Object eventObj )
+        {
+            transport.TransportNotify( eventObj );
+        }
+
+        #region TransportMessage Members
+
+        public void SetSession(SessionMessage session)
+        {
+            this.session = session;
+        }
+
+        public SessionMessage GetSession()
+        {
+            return this.session;
+        }
+
+        public void TransportMessage(Who recipient, Message msg)
+        {
+
+            // packetize the message.
+
+            lock (msgBuf)
+            {
+                try
+                {
+                    // assert that msgBuf is reset.
+                    // leave space for the packet header
+                    msgBuf.Skip(transport.HeaderSize(), true);
+                    tdo.WriteMessage(msg, msgBuf);
+                    msgBuf.SetIndex(0);
+                    transport.TransportPacket(recipient,msgBuf);
+                }
+                finally
+                {
+                    msgBuf.Reset();
+                }
+            }
+           
+        }
+
+        #endregion
+
+        #region SessionPacket Members
+
+        public void SessionPacket(Who sender, FlexBuffer buf)
+        {
+            Message msg = tdi.ReadMessage(buf);
+            bool handled = session.SessionMessage(sender,msg);
+            if (!handled)
+                session.SessionNotify(new UnwantedMessage(sender,msg));
+        }
+
+        #endregion
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/PlainMailbox.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/PlainMailbox.cs
new file mode 100644
index 0000000..a870860
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/PlainMailbox.cs
@@ -0,0 +1,276 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    /// <summary>
+    /// A plain implementation of a mailbox using a fixed size circular queue.
+    /// </summary>
+    /// 
+    public class PlainMailbox : Mailbox, AlarmListener
+    {
+        /// <summary>
+        /// Constructs the PlainMailbox
+        /// </summary>
+        /// <param name="mailboxManager">The mailbox manager to use to unregister this mailbox
+        /// and to deliver undelivered messages.</param>
+        /// <param name="messageId"></param>
+        public PlainMailbox(MailboxManager mailboxManager, long messageId)
+        {
+            if (mailboxManager == null)
+                throw new NullReferenceException("mailboxManager == null");
+
+            this.mailboxManager = mailboxManager;
+            this.messageId = messageId;
+
+            queue = new CircularQueue<Element>(1);
+        }
+
+        private readonly MailboxManager mailboxManager;
+
+        private readonly long messageId;
+
+        private readonly CircularQueue<Element> queue;
+
+        private bool alarmSet;
+
+        private Notify notify;
+
+        private Object state;
+
+        public MailboxManager GetMailboxManager()
+        {
+            return mailboxManager;
+        }
+
+        public long GetMessageId()
+        {
+            return messageId;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="msg"></param>
+        /// Exception:
+        ///     throws Exception
+        public bool Message(Who sender, Message msg)
+        {
+            bool ok = queue.Put(new Element(sender, msg), -1);
+            if (ok)
+                fireNotify();
+            return ok;
+        }
+
+        private void fireNotify()
+        {
+            Notify n;
+            Object s;
+            bool c;
+
+            lock (queue)
+            {
+                n = notify;
+                s = state;
+                c = queue.IsClosed();
+            }
+
+            if (n != null)
+                n.mailboxStatus(this, s, c);
+        }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        /// Exception:
+        ///     throws ThreadInterruptedException
+        public Element Read()
+        {
+            Element elem = null;
+            try
+            {
+                elem = queue.Get();
+            }
+
+            catch (Exception)
+            {
+
+            }
+            return elem;
+        }
+
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="maxDelay"></param>
+        /// <returns></returns>
+        /// Exception:
+        ///     throw ThreadInterruptedException
+        public Element Read(int maxDelay)
+        {
+            Element elem = null;
+            try
+            {
+                elem = queue.Get(maxDelay);
+            }
+
+            catch (Exception)
+            {
+
+            }
+            return elem;
+        }
+
+        public bool CloseDelivery()
+        {
+
+
+            lock (queue)
+            {
+                if (queue.IsClosed())
+                    return false;
+
+
+                if (alarmSet)
+                {
+                    alarmSet = false;
+                    AlarmManager.staticRemove(this);
+                }
+                mailboxManager.Unregister(this);
+                queue.Close();
+
+            }
+
+
+            fireNotify();
+            return true;
+
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// Exception:
+        ///     throws Exception
+        public bool CloseRead()
+        {
+            if (CloseDelivery())
+            {
+                Element mbe;
+                while ((mbe = Read()) != null)
+                    mailboxManager.Redeliver(mbe.sender, mbe.msg);
+                return true;
+            }
+
+            return false;
+
+        }
+
+
+
+        public int Wakeup(AlarmManager manager, Object state, long due)
+        {
+            //Console.WriteLine(" In wakeup");
+            CloseDelivery();
+            return 0;
+        }
+
+        public void RegisterNotify(Notify newNotify, Object state, int maxDelay)
+        {
+            if (newNotify == null)
+                throw new ArgumentNullException("newNotify == null");
+
+            if (maxDelay < 0)
+                throw new ArgumentException("maxDelay < 0");
+
+            bool isNotEmptyOrIsClosed;
+
+            lock (queue)
+            {
+                if (this.notify != null)
+                    throw new Exception("this.notify != null");
+
+                this.notify = newNotify;
+                this.state = state;
+
+                if (maxDelay > 0)
+                {
+                    alarmSet = true;
+                    AlarmManager.staticAdd(this, null, maxDelay);
+                }
+
+                isNotEmptyOrIsClosed = !queue.IsEmpty() || queue.IsClosed();
+            }
+
+            if (isNotEmptyOrIsClosed)
+                fireNotify();
+        }
+
+        public void UnregisterNotify(Notify oldNotify)
+        {
+            if (oldNotify == null)
+                throw new ArgumentNullException("oldNotify == null");
+
+            if (this.notify == null)
+                return;
+
+            lock (queue)
+            {
+                if (oldNotify != this.notify)
+                    throw new ArgumentException("oldNotify != this.notify");
+
+                if (alarmSet)
+                {
+                    alarmSet = false;
+                    AlarmManager.staticRemove(this);
+                }
+
+                this.notify = null;
+                this.state = null;
+            }
+        }
+
+        public bool IsEmpty()
+        {
+            return queue.IsEmpty();
+        }
+
+        public bool IsClosed()
+        {
+            return queue.IsClosed();
+        }
+
+        public bool IsFull()
+        {
+            return queue.IsFull();
+        }
+
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/PlainMailboxManager.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/PlainMailboxManager.cs
new file mode 100644
index 0000000..7f11c5d
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/PlainMailboxManager.cs
@@ -0,0 +1,269 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    /// <summary>
+    /// MailboxManager is a MessageHandler which accepts packets for
+    /// possible delivery to a mailbox, or to another message handler
+    /// if an appropriate mailbox cannot be found. MailboxManager is
+    /// forwarding them to another MessageSource. If requested, a
+    /// mailbox is created with a message's msgid and added to the
+    /// set of mailboxes waiting for messages.
+    /// </summary>
+    public class PlainMailboxManager : MailboxManager
+    {
+        /// <summary>
+        /// Constructs the PlainMailboxManager.
+        /// </summary>
+        /// <param name="transport">a transport to send messages </param>
+        /// <param name="uri">the uri of this transport stack</param>
+        /// <param name="resources">the resources of this transport stack</param>
+        public PlainMailboxManager(TransportMessage transport, string uri, Resources resources)
+            : this(transport, new URL(uri), resources)
+        {
+            // nothing else.
+        }
+
+        /// <summary>
+        /// Constructs the PlainMailboxManager.
+        /// </summary>
+        /// <param name="transport">a transport to send messages </param>
+        /// <param name="uri">the uri of this transport stack</param>
+        /// <param name="resources">the resources of this transport stack</param>
+        public PlainMailboxManager(TransportMessage transport, URL uri, Resources resources)
+        {
+            this.transport = transport;
+            transport.SetSession(this);
+        }
+
+        private readonly TransportMessage transport;
+
+        public override string ToString()
+        {
+            return String.Format( "PlainMailboxManager/{0} ", transport );
+        }
+    	
+	    private readonly IdGenerator idGen = new IdGenerator( DateTime.Now.Ticks, 37 );
+
+        /////////////////////
+        // Mailbox methods //
+        /////////////////////
+
+        private Dictionary<long, Mailbox> mailboxes =
+            new Dictionary<long, Mailbox>();
+
+        /// <summary>
+        /// Adds a mailbox to the set of mailbox receiving responses
+        /// to messages.
+        /// </summary>
+        /// <param name="mb"></param>
+        public void Register( Mailbox mb )
+	    {
+            long msgid = mb.GetMessageId();
+		    lock (mailboxes)
+		    {
+                if (!up)
+                    throw new InvalidOperationException("connection down");
+
+			    if (mailboxes.ContainsKey( msgid ))
+				    throw new ArgumentException( "dup msgid in mailboxes" );
+    			
+			    mailboxes.Add( msgid, mb );
+		    }
+	    }
+       
+        public void Unregister( Mailbox mb )
+        {
+            lock ( mailboxes )
+            {
+                mailboxes.Remove( mb.GetMessageId() );
+            }
+        }
+
+        private Mailbox GetMailbox( long msgid )
+        {
+            lock ( mailboxes )
+            {
+                return mailboxes[msgid];
+            }
+        }
+      
+        public void Redeliver( Who sender, Message msg ) 
+        {
+            session.SessionMessage(sender, msg);
+        }
+
+        public Object SessionQuery( Object query )
+        {
+            return session.SessionQuery( query );
+        }
+
+        public void SessionControl( Object control, Object value )
+        {
+            session.SessionControl( control, value );
+        }
+
+        public void SessionNotify( Object eventObj )
+        {
+           if(eventObj.Equals(SessionConsts.UP))
+           {
+               up = true;
+           }
+           else if (eventObj.Equals(SessionConsts.DOWN))
+           {
+               up = false;
+               UnRegisterAll();
+           }
+            session.SessionNotify(eventObj);
+        }
+
+        private bool up;
+
+        public Object TransportQuery( Object query )
+        {
+            return transport.TransportQuery( query );
+        }
+
+        public void TransportControl( Object control, Object value )
+        {
+            transport.TransportControl( control, value );
+        }
+
+        public void TransportNotify( Object eventObj )
+        {
+            transport.TransportNotify( eventObj );
+        }
+
+        public void UnRegisterAll()
+        {
+            Mailbox[] mbs;
+            lock (mailboxes) 
+            {
+                mbs = new Mailbox[mailboxes.Values.Count];
+                mailboxes.Values.CopyTo(mbs, 0);
+            }
+            foreach (Mailbox mb in mbs)
+            {
+                mb.CloseDelivery();
+            }
+        }
+
+
+        #region SessionMessage Members
+
+        public bool SessionMessage(Who sender, Message msg)
+        {
+            long? msgid = msg.InReplyTo;
+            if (msgid != null)
+            {
+                Mailbox mb;
+                try
+                {
+                    mb = GetMailbox(msgid.Value);
+                }
+                catch
+                {
+                    mb = null;
+                }
+                if (mb != null)
+                {
+                    try
+                    {
+                        return mb.Message(sender, msg);
+
+                    }
+                    catch (Exception)
+                    {
+                        // timeout or mailbox closed - fall through
+                    }
+                }
+                // no such mailbox - fall through
+                return false;
+            }
+            // no such mailbox or no msgid - fall through
+            return session.SessionMessage(sender, msg);
+
+          
+        }
+
+        #endregion
+
+        #region MailboxManager Members
+
+
+        public Mailbox TransportCall(Who recipient, Message msg)
+        {
+            if (msg.MessageId != null)
+                throw new Exception(" message has already been sent");
+            if (msg.InReplyTo != null)
+                throw new Exception(" message is marked as a reply");
+
+            long mid = idGen.Next();
+
+            msg.MessageId = mid;
+            Mailbox mb = new PlainMailbox(this, mid);
+            Register(mb);
+            try
+            {
+                transport.TransportMessage(recipient, msg);
+            }
+            catch(Exception e)
+            {
+                Unregister(mb);
+                throw e;
+            }
+            return mb;
+        }
+
+        #endregion
+
+        #region TransportMessage Members
+
+        public void TransportMessage(Who recipient, Message msg)
+        {
+            transport.TransportMessage(recipient,msg);
+        }
+
+        #endregion
+
+        #region Transport<SessionMessage> Members
+
+
+        public void SetSession(SessionMessage session)
+        {
+            this.session = session;
+        }
+
+        public SessionMessage GetSession()
+        {
+            return this.session;
+        }
+
+        private SessionMessage session;
+
+        #endregion
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/SessionMessage.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/SessionMessage.cs
new file mode 100644
index 0000000..28f3293
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/SessionMessage.cs
@@ -0,0 +1,29 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    public interface SessionMessage : Session
+    {
+        bool SessionMessage(Who sender, Message msg);
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/TaggedDataInput.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/TaggedDataInput.cs
new file mode 100644
index 0000000..38c940e
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/TaggedDataInput.cs
@@ -0,0 +1,38 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    /// <summary>A TaggedDataInputStream reads type tagged values from an input stream.</summary>
+    public interface TaggedDataInput
+    {
+       
+        
+        /// <summary>
+        /// Reads a message from the buf.
+        /// </summary>
+        /// <returns>a message read from the buf.</returns>
+        Message ReadMessage(FlexBuffer buf);
+
+      
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/TaggedDataOutput.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/TaggedDataOutput.cs
new file mode 100644
index 0000000..386f8c4
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/TaggedDataOutput.cs
@@ -0,0 +1,39 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    /// <summary>
+    /// A TaggedDataOutputStream writes type tagged data values to an output stream.
+    /// </summary>
+    public interface TaggedDataOutput
+    {
+       
+        /// <summary>
+        /// Writes the message to the buf.
+        /// </summary>
+        /// <param name="msg">the message to be written</param>
+        void WriteMessage(Message msg, FlexBuffer msgBuf);
+
+        
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/TcpTransportFactory.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/TcpTransportFactory.cs
new file mode 100644
index 0000000..9721ab8
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/TcpTransportFactory.cs
@@ -0,0 +1,170 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Net.Sockets;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using TcpListener=Org.Apache.Etch.Bindings.Csharp.Util.TcpListener;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    /// <summary>
+    /// TransportFactory for tcp connections and listeners.
+    /// </summary>
+    public class TcpTransportFactory : TransportFactory
+    {
+        /// <summary>
+        /// Constructs a TcpTransportFactory which delivers TcpConnection or a
+        /// TlsConnection depending upon the isSecure parameter.
+        /// </summary>
+        /// <param name="isSecure">true if TlsConnection is desired, false otherwise</param>
+        public TcpTransportFactory(bool isSecure)
+        {
+            this.isSecure = isSecure;
+        }
+
+        private readonly bool isSecure;
+        
+        private const String SOCKET = "TcpTransportFactory.socket";
+
+        protected override TransportMessage NewTransport(string uri, Resources resources)
+        {
+            URL u = new URL(uri);
+
+            Object socket = resources.Get(SOCKET);
+
+            TransportData c;
+
+            if (isSecure)
+                c = new TlsConnection((Socket)socket, u, resources);
+            else
+                c = new TcpConnection((Socket)socket, u, resources);
+
+            TransportPacket p = new Packetizer(c, u, resources);
+
+            TransportMessage m = new Messagizer(p, u, resources);
+
+            m = AddFilters(m, u, resources);
+
+            //MailboxManager r = new PlainMailboxManager(m, u, resources);
+
+            //DeliveryService d = new DefaultDeliveryService(r, u, resources);
+
+            ValueFactory vf = (ValueFactory) resources.Get(TransportConsts.VALUE_FACTORY);
+            vf.LockDynamicTypes();
+
+            return m;
+        }
+
+        protected override Transport<ServerFactory> NewListener( string uri, Resources resources )
+        {
+            Transport<SessionListener<Socket>> l = new TcpListener(uri, resources);
+            return new MySessionListener(this, l, uri, resources);
+        }
+
+        public class MySessionListener : Transport<ServerFactory>, SessionListener<Socket>
+        {
+            public MySessionListener(TcpTransportFactory ttf, Transport<SessionListener<Socket>> transport,
+                String uri, Resources resources )
+            {
+                this.ttf = ttf;
+                this.transport = transport;
+                this.uri = uri;
+                this.resources = resources;
+
+                transport.SetSession(this);
+            }
+
+            private readonly TcpTransportFactory ttf;
+            private readonly Transport<SessionListener<Socket>> transport;
+            private readonly string uri;
+            private readonly Resources resources;
+
+            public override string ToString()
+            {
+                return "TcpTransportFactory.MySessionListener/" + transport;
+            }
+
+            public void SessionAccepted(Socket socket)
+            {
+                Resources r = new Resources(resources);
+                r.Add(SOCKET, socket);
+
+                ValueFactory vf = session.NewValueFactory(uri);
+                r.Add(TransportConsts.VALUE_FACTORY, vf);
+
+                TransportMessage t = ttf.NewTransport(uri, r);
+
+                session.NewServer(t, uri, r);
+            }
+
+            #region Transport<ServerFactory> Members
+
+            public object TransportQuery(object query)
+            {
+                return transport.TransportQuery(query);
+            }
+
+            public void TransportControl(object control, object value)
+            {
+                transport.TransportControl(control, value);
+            }
+
+            public void TransportNotify(object eventObj)
+            {
+                transport.TransportNotify(eventObj);
+            }
+
+            public ServerFactory GetSession()
+            {
+                return session;
+            }
+
+            public void SetSession(ServerFactory session)
+            {
+                this.session = session;
+            }
+
+            private ServerFactory session;
+
+            #endregion
+
+            #region Session Members
+
+            public object SessionQuery(object query)
+            {
+                return session.SessionQuery(query);
+            }
+
+            public void SessionControl(object control, object value)
+            {
+                session.SessionControl(control, value);
+            }
+
+            public void SessionNotify(object eventObj)
+            {
+                session.SessionNotify(eventObj);
+            }
+
+            #endregion
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/TransportMessage.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/TransportMessage.cs
new file mode 100644
index 0000000..86ba22d
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/TransportMessage.cs
@@ -0,0 +1,29 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    public interface TransportMessage : Transport<SessionMessage>
+    {
+        void TransportMessage(Who recipient, Message msg);
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/UnwantedMessage.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/UnwantedMessage.cs
new file mode 100644
index 0000000..97db31d
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Transport/UnwantedMessage.cs
@@ -0,0 +1,46 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    /// <summary>
+    /// Event class used with SessionNotify to report unwanted messages.
+    /// </summary>
+    public class UnwantedMessage
+    {
+        public UnwantedMessage(Who sender, Message msg)
+        {
+            this.sender = sender;
+            this.msg = msg;
+        }
+
+        public readonly Who sender;
+
+        public readonly Message msg;
+
+        public override String ToString()
+        {
+            return String.Format("Unwanted message from {0}: {1}", sender, msg);
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/AbstractStartable.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/AbstractStartable.cs
new file mode 100644
index 0000000..266d94c
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/AbstractStartable.cs
@@ -0,0 +1,104 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Generic implementation of Startable
+    /// </summary>
+    abstract public class AbstractStartable : Startable
+    {
+        public void Start()
+        {
+            lock (this)
+            {
+                if (IsStarted())
+                    throw new Exception("is already started");
+                SetStarted();
+            }
+
+            try
+            {
+                Start0();
+            }
+            catch (Exception)
+            {
+                Stop();
+                throw;
+            }
+        }
+
+        public void Stop()
+        {
+            lock (this)
+            {
+                CheckIsStarted();
+                SetStopped();
+            }
+
+            Stop0();
+        }
+
+        private bool started;
+
+        private void SetStarted()
+        {
+            started = true;
+        }
+
+        protected void SetStopped()
+        {
+            started = false;
+        }
+
+        public bool IsStarted()
+        {
+            return started;
+        }
+
+        /// <summary>
+        /// Check that the startable is started
+        /// Exception:
+        ///     ThreadInterruptedException if not started
+        /// </summary>
+        /// 
+        public void CheckIsStarted()
+        {
+            if (!IsStarted())
+                throw new Exception("is not started");
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// Exception:
+        ///     throws Exception
+        abstract protected void Start0();
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// Exception:
+        ///     throws Exception
+        abstract protected void Stop0();
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/AlarmListener.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/AlarmListener.cs
new file mode 100644
index 0000000..acb3268
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/AlarmListener.cs
@@ -0,0 +1,66 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Classes wanting alarms must implement this interface to receive the
+    /// alarm.
+    /// </summary>
+    public interface AlarmListener
+    {
+        /// <summary>
+        /// Reports that the listener's alarm went off.
+        /// </summary>
+        /// 
+        /// <param name="manager">the manager of the alarm.</param>
+        /// 
+        /// <param name="state">a bit of state for the listener.</param>
+        /// 
+        /// <param name="due">due the time the alarm was set to go off. This is in the
+        /// time coordinates as returned by Timer.GetNanos().</param>
+        /// 
+        /// <returns>
+        /// the positive or negative snooze time in ms for this alarm,
+        /// or 0 to shutoff the alarm. If a positive number is returned, it is
+        /// added to the current due time of the alarm to calculate the new
+        /// due time for the alarm. Thus there should be very little drift
+        /// in the frequency of the alarms (although there is some because
+        /// of system clock jitter).
+        /// 
+        /// If the system is very busy, or if the listeners are trying to
+        /// do too much, alarms may not be processed quickly enough and
+        /// calculated new due times will already be in the past. This is a
+        /// pathological condition which will spiral out of control if not
+        /// detected.
+        /// 
+        /// If a negative number is returned, it is subtracted from the current
+        /// value of Timer.GetNanos() to calculate the new due time for the
+        /// alarm. (In this case, subtracting the negative number is the same
+        /// as adding the absolute value...)
+        /// </returns>
+        /// 
+        /// <see cref="Timer.GetNanos()"/>
+
+
+        int Wakeup( AlarmManager manager, Object state, long due );
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/AlarmManager.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/AlarmManager.cs
new file mode 100644
index 0000000..adf8fc8
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/AlarmManager.cs
@@ -0,0 +1,557 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Threading;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    
+    /// <summary>
+    /// The alarm manager is used to implement alarms.
+    /// A listener desiring a wakeup call should add itself to the manager
+    /// with the specified delay in milliseconds. The listener may be removed
+    /// at any time. When the alarm goes off, the listener may reset or remove
+    /// the alarm.
+    /// </summary>
+    public class AlarmManager : AbstractStartable
+    {
+        /// <summary>
+        /// Adds the listener to the set of those getting wakeup calls.
+        /// </summary>
+        /// <param name="listener">the target of the wakeup call.</param>
+        /// <param name="state">a bit of state for the listener.</param>
+        /// <param name="delay">the positive delay in milliseconds before the wakeup call.</param>
+        public static void staticAdd(AlarmListener listener, Object state, int delay)
+        {
+            GetAlarmManager(true).Add(listener, state, delay);
+        }
+
+        /// <summary>
+        /// Removes the listener from the set of those getting wakeup calls.
+        /// </summary>
+        /// <param name="listener">the target of the wakeup call.</param>
+        public static void staticRemove(AlarmListener listener)
+        {
+            AlarmManager am = GetAlarmManager(false);
+            if (am != null)
+                am.Remove(listener);
+        }
+
+        /// <summary>
+        /// Gets the statically configured alarm manager, creating one if
+        /// specified and none exists.
+        /// </summary>
+        /// <param name="startIt">if true, we really need one and if there isn't
+        /// one then one should be started, otherwise one should not be started</param>
+        /// <returns>he statically configured alarm manager, or a newly
+        /// created one if there is none.</returns>
+        public static AlarmManager GetAlarmManager(bool startIt)
+        {
+            if (alarmManager == null)
+            {
+                lock (alarmManagerSync)
+                {
+                    if (alarmManager == null)
+                    {
+                        if (!startIt)
+                            return null;
+
+                        AlarmManager am = new AlarmManager();
+                        am.Start();
+                        alarmManager = am;
+                    }
+                }
+            }
+
+            return alarmManager;
+        }
+
+        /// <summary>
+        /// Sets the statically configured alarm manager, returning the old one
+        /// if any. Don't forget to stop the old one.
+        /// </summary>
+        /// <param name="newAlarmManager">a new AlarmManager to be statically available</param>
+        /// <returns>the old statically available AlarmManager.</returns>
+        public static AlarmManager SetAlarmManager(AlarmManager newAlarmManager)
+        {
+            lock (alarmManagerSync)
+            {
+                AlarmManager oldAlarmManager = alarmManager;
+                alarmManager = newAlarmManager;
+                return oldAlarmManager;
+            }
+        }
+
+        private static AlarmManager alarmManager;
+
+        private readonly static Object alarmManagerSync = new Object();
+
+        /// <summary>
+        /// Constructs the AlarmManager.
+        /// </summary>
+        /// <param name="nWorkers">the number of worker threads to create to process
+        /// wakeups. Must be > 0 and < 100.</param>
+        public AlarmManager(int nWorkers)
+        {
+            if (nWorkers <= 0 || nWorkers >= 100)
+                throw new ArgumentException("nWorkers <= 0 || nWorkers >= 100");
+
+            this.nWorkers = nWorkers;
+        }
+
+        /// <summary>
+        /// onstructs the AlarmManager with the default number of workers.
+        /// </summary>
+        public AlarmManager()
+            : this(DEFAULT_NWORKERS)
+        {
+
+        }
+
+        private readonly int nWorkers;
+
+        /// <summary>
+        /// The default number of worker threads (1).
+        /// </summary>
+        public const int DEFAULT_NWORKERS = 1;
+
+
+        protected override void Start0()
+        {
+            ClearAlarms();
+            ClearQueue();
+
+            worker = new Thread[nWorkers];
+            for (int i = 0; i < nWorkers; i++)
+            {
+                worker[i] = new Thread(run);
+                worker[i].IsBackground = true;
+                worker[i].Start();
+            }
+        }
+        private Thread[] worker;
+
+        protected override void Stop0()
+        {
+            ClearAlarms();
+            ClearQueue();
+
+            lock (this)
+            {
+                Monitor.PulseAll(this);
+            }
+
+            for (int i = 0; i < nWorkers; i++)
+            {
+                if (worker[i] != null)
+                {
+                    worker[i].Join();
+                    worker[i] = null;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Adds the listener to the set of those getting wakeup calls. If the
+        /// listener is already scheduled for a wakeup call, the schedule is
+        /// adjusted. There can only be one outstanding wakeup call per listener.
+        /// This method is thread safe.
+        /// </summary>
+        /// <param name="listener">the target of the wakeup call.</param>
+        /// <param name="state">a bit of state for the listener.</param>
+        /// <param name="delay">the positive delay in milliseconds before the wakeup call.</param>
+        /// <exception cref="ArgumentException">throws ArgumentException if the delay is less
+        /// than or equal to 0</exception>
+        [MethodImpl(MethodImplOptions.Synchronized)]
+        public void Add(AlarmListener listener, Object state, int delay)
+        {
+            if (listener == null)
+                throw new ArgumentNullException("listener");
+
+            if (delay <= 0)
+                throw new ArgumentException("delay <= 0");
+
+            CheckIsStarted();
+
+            long due = HPTimer.Now() + delay * HPTimer.NS_PER_MILLISECOND;
+
+            Alarm alarm = GetAlarm(listener);
+            if (alarm != null)
+            {
+                // schedule is being adjusted
+                Dequeue(alarm);
+                alarm.setDue(due);
+                alarm.setState(state);
+                Enqueue(alarm);
+            }
+            else
+            {
+                alarm = new Alarm(listener, state, due);
+                AddAlarm(listener, alarm);
+                Enqueue(alarm);
+            }
+
+            NotifyWorker("add");
+        }
+
+        [MethodImpl(MethodImplOptions.Synchronized)]
+        private void Update(Alarm alarm, int delay)
+        {
+            long due = delay > 0
+                ? alarm.getDue() + delay * HPTimer.NS_PER_MILLISECOND
+                : HPTimer.Now() - delay * HPTimer.NS_PER_MILLISECOND;
+
+            alarm.setDue(due);
+            Enqueue(alarm);
+            NotifyWorker("update");
+        }
+
+        /// <summary>
+        /// Removes any scheduled wakeup call for this listener.
+        /// This method is thread safe.
+        /// </summary>
+        /// <param name="listener">the target of the wakeup call.</param>
+        [MethodImpl(MethodImplOptions.Synchronized)]
+        public void Remove(AlarmListener listener)
+        {
+            CheckIsStarted();
+
+            Alarm alarm = RemoveAlarm(listener);
+            if (alarm != null)
+            {
+                Dequeue(alarm);
+                NotifyWorker("remove");
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.Synchronized)]
+        private void Remove(Alarm alarm)
+        {
+            RemoveAlarm(alarm.listener);
+        }
+
+        private void Wakeup(Alarm alarm)
+        {
+            try
+            {
+                int delay = alarm.listener.Wakeup(this, alarm.getState(), alarm.getDue());
+                if (delay != 0)
+                    Update(alarm, delay);
+                else
+                    Remove(alarm);
+            }
+            catch (Exception e)
+            {
+                Remove(alarm);
+                Report(e);
+            }
+        }
+
+        private Alarm getNextDueAlarm()
+        {
+            // ok, the worker needs to get the next due alarm and
+            // then wait until its due time, then return it. if alerted
+            // by notifyWorker, it should refresh the next due alarm.
+            // one trick will be in excluding multiple workers from
+            // coming in here at the same time.
+            lock (getNextDueAlarmSync)
+            {
+                lock (this)
+                {
+                    while (true)
+                    {
+                        //					
+                        if (!IsStarted())
+                            return null;
+
+                        Alarm alarm = getFirst();
+
+                        if (alarm == null)
+                        {
+                            try
+                            {
+                                //Console.WriteLine(" Waiting in getNextDueAlarm ");
+
+                                Monitor.Wait(this, Int32.MaxValue);
+
+                                //Console.WriteLine(" Done Waiting in getNextDueAlarm ");
+
+                                continue;
+                            }
+                            catch (Exception e)
+                            {
+                                Console.WriteLine(e);
+                                return null;
+                            }
+                        }
+
+                        long delayNs = alarm.getDue() - HPTimer.Now();
+                        if (delayNs > 0)
+                        {
+                            try
+                            {
+                                long delay = delayNs / HPTimer.NS_PER_MILLISECOND;
+                                if (delay > 0)
+                                {
+                                    int d = (int)delay;
+                                    Monitor.Wait(this, d);
+                                }
+                                continue;
+                            }
+                            catch (Exception e)
+                            {
+                                Console.WriteLine(e);
+                                return null;
+                            }
+                        }
+
+                        // the alarm being returned has not been removed
+                        // from alarmsByListener. it is presumed that the
+                        // alarm will be set again. if not, it should be
+                        // removed.
+
+                        Dequeue(alarm);
+                        return alarm;
+                    }
+                }
+            }
+        }
+
+        private readonly Object getNextDueAlarmSync = new Object();
+
+        private void NotifyWorker(String reason)
+        {
+            //		Log.report( "notify", "who", this, "reason", reason, "where", new Throwable() );
+            // the set of alarms has changed.
+            Monitor.Pulse(this);
+        }
+
+        public void run()
+        {
+            try
+            {
+                Alarm alarm;
+                while ((alarm = getNextDueAlarm()) != null)
+                {
+                    Wakeup(alarm);
+                }
+            }
+            catch (Exception e)
+            {
+                Report(e);
+            }
+        }
+
+        private void Report(Exception e)
+        {
+            Console.WriteLine(e);
+        }
+
+        private Alarm GetAlarm(AlarmListener listener)
+        {
+            Alarm alarm;
+            return alarmsByListener.TryGetValue(listener, out alarm) ? alarm : null;
+        }
+
+        private void AddAlarm(AlarmListener listener, Alarm alarm)
+        {
+            alarmsByListener.Add(listener, alarm);
+        }
+
+        private Alarm RemoveAlarm(AlarmListener listener)
+        {
+            Alarm alarm = GetAlarm(listener);
+            if (alarm != null)
+                alarmsByListener.Remove(listener);
+            return alarm;
+        }
+
+        private void ClearAlarms()
+        {
+            alarmsByListener.Clear();
+        }
+
+        private readonly Dictionary<AlarmListener, Alarm> alarmsByListener = new Dictionary<AlarmListener, Alarm>();
+
+        ////////////////////////
+        // ALARMS BY DUE TIME //
+        ////////////////////////
+
+        private Alarm getFirst()
+        {
+            if (alarms.Count == 0)
+                return null;
+
+            return alarms[0];
+        }
+
+        private void Enqueue(Alarm alarm)
+        {
+            alarms.Add(alarm);
+            alarms.Sort();
+        }
+
+        private void Dequeue(Alarm alarm)
+        {
+            alarms.Remove(alarm);
+
+        }
+
+        private void ClearQueue()
+        {
+            alarms.Clear();
+        }
+
+        private readonly List<Alarm> alarms = new List<Alarm>();
+
+
+        private class Alarm : IComparable<Alarm>
+        {
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <param name="listener">the target of the wakeup call.</param>
+            /// <param name="state">a bit of state for the listener.</param>
+            /// <param name="due">he absolute due time for the alarm.</param>
+            public Alarm(AlarmListener listener, Object state, long due)
+            {
+                this.listener = listener;
+                this.state = state;
+                this.due = due;
+            }
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <returns>the state for the listener.</returns>
+            public Object getState()
+            {
+                return state;
+            }
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <param name="state">a new bit of state for the listener./param>
+            public void setState(Object state)
+            {
+                this.state = state;
+            }
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <returns>the time the alarm is due.</returns>
+            public long getDue()
+            {
+                return due;
+            }
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <param name="due"></param>
+            public void setDue(long due)
+            {
+                this.due = due;
+            }
+
+
+            public override int GetHashCode()
+            {
+                return (int)((due ^ (due >> 32)) ^ (seq ^ (seq >> 32)));
+            }
+
+
+            public override bool Equals(Object obj)
+            {
+                if (obj == this)
+                    return true;
+
+                if (obj == null)
+                    return false;
+
+                if (obj.GetType() != typeof(Alarm))
+                    return false;
+
+                Alarm other = (Alarm)obj;
+
+                return due == other.due && seq == other.seq;
+            }
+
+            public int CompareTo(Alarm other)
+            {
+                if (due < other.due)
+                    return -1;
+
+                if (due > other.due)
+                    return 1;
+
+                // due time is the same for both, now we need to
+                // compare the seq.
+
+                if (seq < other.seq)
+                    return -1;
+
+                if (seq > other.seq)
+                    return 1;
+
+                return 0;
+            }
+
+            /// <summary>
+            /// The listener for wakeup events.
+            /// </summary>
+            public readonly AlarmListener listener;
+
+            /// <summary>
+            /// Just a bit of state for the listener.
+            /// </summary>
+            private Object state;
+
+            /// <summary>
+            /// The time the alarm is due.
+            /// </summary>
+            private long due;
+
+            /// <summary>
+            /// A unique for all reasonable time sequence number.
+            /// </summary>
+            private readonly long seq = idGen.Next();
+
+            private readonly static IdGenerator idGen = new IdGenerator();
+        }
+
+        /// <summary>
+        /// Shuts down the default alarm manager if there is one.
+        /// </summary>
+        public static void shutdown()
+        {
+            AlarmManager am = SetAlarmManager(null);
+            if (am != null)
+                am.Stop();
+        }
+
+
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/ArrayIterator.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/ArrayIterator.cs
new file mode 100644
index 0000000..91dbe92
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/ArrayIterator.cs
@@ -0,0 +1,71 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System.Collections.Generic;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public class ArrayIterator<T> : IEnumerator<T> 
+    {
+
+        /// <param name="values"></param>
+        public ArrayIterator( T[] values ) 
+       {
+            this.values = values;
+       }
+
+        private T[] values;
+
+        private int index = -1;
+
+        /// <returns> index value if less than the length of values</returns>
+        public bool MoveNext()
+        {
+            if(index < values.Length)
+                index++;
+            return index < values.Length;
+        }
+
+        /// <summary>Resets index before the beginning of the array</summary>
+        public void Reset()
+        {
+            index = -1;
+        }
+
+        /// <summary>returns the value at the index of the 'values'</summary>
+        public T Current
+        {
+            get
+            {
+                return values[index];
+            }
+        }
+
+        /// <summary>returns the value at the index of the 'values'</summary>
+        object System.Collections.IEnumerator.Current
+        {
+            get
+            {
+                return values[index];
+            }
+        }
+
+        public void Dispose(){}
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Assertion.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Assertion.cs
new file mode 100644
index 0000000..f03ba62
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Assertion.cs
@@ -0,0 +1,32 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public class Assertion
+    {
+        public static void Check(bool ok, string msg)
+        {
+            if (!ok)
+                throw new Exception("assertion failed: " + msg);
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/CharIterator.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/CharIterator.cs
new file mode 100644
index 0000000..bb0b5c8
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/CharIterator.cs
@@ -0,0 +1,58 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public class CharIterator 
+    {
+        private readonly String _s;
+        private readonly int _n;
+        private int _i = -1;
+
+        public CharIterator( String s )
+        {
+            if ( s == null )
+                throw new ArgumentNullException( "String to iterate over shouldn't be null" );
+
+            _s = s;
+            _n = s.Length;
+        }
+
+        public Boolean MoveNext()
+        {
+            if ( _i < (_n-1) )
+            {
+                _i++;
+                return true;
+            }
+            else
+                return false;
+        }
+
+        public Char Current
+        {
+            get
+            {
+                return _s[ _i ];
+            }
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/CircularQueue.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/CircularQueue.cs
new file mode 100644
index 0000000..c3e67c8
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/CircularQueue.cs
@@ -0,0 +1,404 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+
+    /// <summary>
+    /// A circular queue of a fixed size. Elements are added to one
+    /// end and removed from the other, with the queue size ranging
+    /// from empty to full. Operations can optionally wait until
+    /// finished or return status indicating success or failure.
+    /// For instance, adding to a full queue can wait until an item
+    /// is removed before adding the new item or it can wait only
+    /// a specified amount of time before completing successfully
+    /// or giving up.
+    /// </summary>
+    /// <typeparam name="T">the type of items in the queue.</typeparam>
+    public sealed class CircularQueue<T>
+    {
+        /// <summary>
+        /// Constructs the Circular Queue
+        /// </summary>
+        /// <param name="size">the maximum number of items allowed in the queue.</param>
+        public CircularQueue( int size )
+        {
+            if ( size < 1)
+                throw new ArgumentOutOfRangeException("size < 1");
+            this.size = size;
+       //     items = new T[ size ];
+            items = new Object[size];
+        }
+
+        /// <summary>
+        /// Constructs the CircularQueue with the maximum number of items
+        /// defaulted to 10.
+        /// </summary>
+        public CircularQueue() : this (10)
+        {
+        }
+
+        private readonly int size;
+
+//        private readonly T[] items;
+        private readonly Object[] items;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the maximum number of items that may be put in the queue.</returns>
+        public int Size()
+        {
+            return size;
+        }
+
+        private int count;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the current number of items in the queue.</returns>
+        public int Count()
+        {
+            return count;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>true if the queue is empty.</returns>
+        public bool IsEmpty()
+        {
+            return count == 0;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>true if the queue is full.</returns>
+        public bool IsFull()
+        {
+            return count == size;
+        }
+
+        private int head;
+
+        private Object Get0()
+        {
+            Debug.Assert(count>0,"count > 0");
+
+            Object obj = items[head];
+
+            Debug.Assert(obj != null,"obj != null");
+
+            items[head] = null;
+
+            count--;
+            head++;
+
+            if (head == size)
+                head = 0;
+
+            return obj;
+            
+        }
+
+       /* private T IntGet()
+	    {
+		    Debug.Assert( !IsEmpty() );
+    		
+		    Debug.Assert( items[head] != null );
+		    T t = items[head];
+            items[ head ] = default( T ); //null;
+    		
+		    // wake up someone waiting for space.
+            if ( IsFull() )
+                System.Threading.Monitor.Pulse( this );
+    		
+		    count--;
+    		
+		    head++;
+		    if (head == size)
+			    head = 0;
+    		
+		    return t;
+	    } */
+
+        private int tail;
+
+        private void Put0(Object obj)
+        {
+
+            Debug.Assert(obj != null, "obj != null");
+            Debug.Assert(count < size, "count < size");
+            Debug.Assert(items[tail] == null, "items[tail] == null");
+
+            items[tail] = obj;
+
+            count++;
+
+            tail++;
+
+            if (tail == size)
+                tail = 0;
+            
+        }
+
+   /*     private void IntPut( T t )
+	    {
+		    Debug.Assert( t != null );
+		    Debug.Assert( !IsFull() );
+    		
+		    Debug.Assert( items[tail] == null );
+		    items[tail] = t;
+    		
+		    // wake up someone waiting for an item.
+            if ( IsEmpty() )
+                System.Threading.Monitor.Pulse(this);
+    		
+		    count++;
+    		
+		    tail++;
+		    if (tail == size)
+			    tail = 0;
+	    } */
+
+
+
+        /// <summary>
+        /// Gets the next available item from the queue, waiting
+        /// until an item is available or the queue is closed.
+        /// </summary>
+        /// <returns>the item from the queue, or null if the queue
+        /// is closed.</returns>
+        /// Exception:
+        ///     throws ThreadInterruptedException if thread is interrupted
+        public T Get() 
+	    {
+           
+            return Get( 0 );
+	    }
+
+        /// <summary>
+        /// Gets the next available item from the queue, waiting
+        /// until an item is available or the queue is closed.
+        /// </summary>
+        /// <param name="maxDelay">the maximum time in ms to wait for
+        /// something to be put in the queue; 0 means wait forever,
+        /// less than 0 means don't wait.</param>
+        /// <returns>the item from the queue, or null if maxDelay
+        /// has been exceeded or the queue is closed.</returns>
+        /// Exception:
+        ///     throws ThreadInterruptedException
+
+        [MethodImpl(MethodImplOptions.Synchronized)]
+        public T Get( int maxDelay ) 
+	    {
+		    if (!IsEmpty())
+			    return GetAndNotify();
+
+            if (IsClosed() || maxDelay < 0)
+               return default( T ); //null;
+    		
+		    // the queue is empty, not closed, and caller has requested a delay
+
+            long now = HPTimer.Now();
+            long end = EndTime(now, maxDelay);
+
+            Debug.Assert(end > now, "end > now");
+
+            int d;
+            while ((d = RemTime(end, now)) > 0)
+		    {
+			    // the queue is empty, not closed, and delay has not run out...
+                Debug.Assert(IsEmpty(), "IsEmpty()");
+                Debug.Assert(!IsClosed(),"!IsClosed()");
+
+                System.Threading.Monitor.Wait(this, d);
+
+			    if (!IsEmpty())
+				    return GetAndNotify();
+
+                if ( IsClosed() )
+                    return default( T ); //null;
+
+                now = HPTimer.Now();
+		    }
+
+            return default( T ); // null;
+	    }
+
+        /// <summary>
+        /// Puts an item in the queue, waiting until space is available
+        /// or the queue is closed.
+        /// </summary>
+        /// <param name="t">a non-null item to put in the queue.</param>
+        /// <returns>true if the item was placed in the queue,
+        /// or false if the queue is closed.</returns>
+        /// Exception:
+        ///     throws ThreadInterruptedException if the thread is interrupted
+
+        public bool Put( T t ) 
+	    {
+		    return Put( t, 0 );
+	    }
+
+        
+        /// <summary>
+        /// Puts an item in the queue, waiting until space is available
+        /// or the queue is closed.
+        /// </summary>
+        /// <param name="obj">a non-null item to put in the queue.</param>
+        /// <param name="maxDelay">the maximum time in ms to wait for
+        /// available space the queue; 0 means wait forever,
+        /// less than 0 means don't wait.</param>
+        /// <returns>true if the item was placed in the queue,
+        /// or false if maxDelay has been exceeded or the queue is closed.</returns>
+        /// Exception:
+        ///     throws ThreadInterruptedException if the thread is interrupted
+
+        [MethodImpl(MethodImplOptions.Synchronized)]
+        public bool Put( T obj, int maxDelay ) 
+	    {
+		    if (obj == null)
+			    throw new ArgumentNullException( "t == null" );
+    		
+		    if (IsClosed())
+			    return false;
+    		
+		    // the queue is not closed.
+    		
+		    if (!IsFull())
+		    {
+			    PutAndNotify( obj );
+			    return true;
+		    }
+    		
+		    // the queue is not closed, the queue is full.
+    		
+		    if (maxDelay < 0)
+			    return false;
+			
+            long now = HPTimer.Now();
+            long end = EndTime(now, maxDelay);
+            
+            int d;
+            while ((d = RemTime(end, now)) > 0)    
+		    {
+			    // the queue is not closed, the queue is full, and delay has not run out...
+			    Debug.Assert( !IsClosed() );
+                Debug.Assert( IsFull() );
+                
+                System.Threading.Monitor.Wait(this, d);
+                
+			    if (IsClosed())
+				    return false;
+    			
+			    // the queue is not closed.
+    			
+			    if (!IsFull())
+			    {
+			        PutAndNotify(obj);
+				    return true;
+			    }
+
+                now = HPTimer.Now();
+		    }
+    		
+		    return false;
+	    }
+
+        /// <summary>
+        /// Closes the queue so that no more items may be put into it.
+        /// Get will return null when there are no more items to return.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.Synchronized)]
+        public void Close()
+	    {
+		    if (!closed)
+		    {
+                closed = true;
+                System.Threading.Monitor.PulseAll(this);
+		    }
+            
+	    }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>true if the queue is closed.</returns>
+        public bool IsClosed()
+        {
+            return closed;
+        }
+
+        private bool closed;
+
+        private T GetAndNotify()
+        {
+            bool notify = IsFull();
+
+            Object obj = Get0();
+
+            notify = notify || !IsEmpty();
+
+            if (notify)
+                System.Threading.Monitor.Pulse(this);
+
+            return (T) obj;
+        }
+
+        private void PutAndNotify(T obj)
+        {
+            bool notify = IsEmpty();
+
+            Put0(obj);
+
+            notify = notify || !IsFull();
+
+            if (notify)
+                System.Threading.Monitor.Pulse(this);
+           
+        }
+
+        private long EndTime(long now, int maxDelay)
+        {
+            if (maxDelay == 0 || maxDelay == int.MaxValue)
+                return long.MaxValue;
+
+            return now + maxDelay * HPTimer.NS_PER_MILLISECOND;
+        }
+
+        private int RemTime(long end, long now)
+        {
+            if (end == long.MaxValue)
+                return int.MaxValue;
+
+            long ms = (end - now) / HPTimer.NS_PER_MILLISECOND;
+            if (ms > int.MaxValue)
+                return int.MaxValue;
+
+            return (int)ms;
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Connection.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Connection.cs
new file mode 100644
index 0000000..32d0415
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Connection.cs
@@ -0,0 +1,331 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Implementation of runner which handles a network connection.
+    /// </summary>
+    abstract public class Connection<H> : Runner, 
+        Transport<H>, RunnerHandler where H : Session
+    {
+
+        #region QUERIES
+
+        /// <summary>
+        /// Source query to get the local address
+        /// </summary>
+        public const String LOCAL_ADDRESS = "LOCAL_ADDRESS";
+
+	    /// <summary>
+	    /// Source query to get the remote address.
+	    /// </summary>
+	    public const String REMOTE_ADDRESS = "REMOTE_ADDRESS";
+
+        #endregion  
+
+        #region EVENTS
+        
+        
+	    /// <summary>
+	    /// Host name to specify to select listening on all interfaces.
+        /// The value is "0.0.0.0".
+	    /// </summary>
+	    public const String ALL_INTFS = "0.0.0.0";
+
+        /// <summary>
+        /// Translates host name per well know names.
+        /// </summary>
+        /// <param name="s">input host name</param>
+        /// <returns></returns>
+        protected static String TranslateHost( String s )
+        {
+            if ( s != null && s.Equals( ALL_INTFS ) )
+                return null;
+            return s;
+        }
+
+        #endregion
+
+
+        /// <summary>
+        /// Constructs the Connection.
+        /// </summary>
+        public Connection()
+        {
+            SetHandler(this);
+        }
+      
+        public void Started( )
+        { 
+            // nothing to do.
+        }
+
+        public void Stopped( )
+        {
+            // nothing to do.
+        }
+
+        public void Exception( String what, Exception e )
+        {
+            TodoManager.AddTodo(new TodoDelegateImpl(
+                delegate(TodoManager mgr)
+                {
+                    session.SessionNotify(e);
+                },
+                delegate(TodoManager mgr, Exception e1)
+                {
+                    Console.WriteLine(e);
+                    if (e1 != e)
+                        Console.WriteLine(e1);
+                }));
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="first"></param>
+        /// <returns></returns>
+        /// Exception:
+        ///     throws Exception
+        protected override bool Run0( bool first )
+        {
+            bool ok = OpenSocket(!first);
+            if ( !ok )
+                return false;
+
+            try
+            {
+                SetUpSocket();
+            }
+            catch ( Exception e )
+            {
+                FireException( "setup", e );
+                Close( true );
+                return true;
+            }
+
+            try
+            {
+                FireUp();
+                ReadSocket();
+                return true;
+            }
+            catch (SocketException e)
+            {
+                // TODO ignore "socket closed" condition
+                FireException("run", e);
+                Close(true);
+                return true;
+            }
+            catch (Exception e)
+            {
+                FireException("run", e);
+                Close(true);
+                return true;
+            }
+            finally
+            {
+                FireDown();
+                Close( false );
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="reconnect">reconnect true if we are trying to reconnect, false if this
+        /// is the first time.</param>
+        /// <returns>true if we should reconnect, false if we should stop.</returns>
+        /// Exception:
+        ///     throws Exception
+        abstract protected bool OpenSocket( bool reconnect );
+        
+        /// <summary>
+        /// Sets up a newly opened socket. This may involve setting socket
+        /// options and opening input and output streams.
+        /// </summary>
+        /// Exception:
+        ///     throws Exception
+        abstract protected void SetUpSocket();
+
+        /// <summary>
+        /// Performs the usual and customary operations on a socket, such
+        /// as read or accept.
+        /// </summary>
+        /// Exception:
+        ///     throws Exception
+        abstract protected void ReadSocket();
+
+        /// <summary>
+        /// Terminates operations on the socket.
+        /// </summary>
+        /// <param name="reset">true if the socket should be terminated immediately.</param>
+        /// Exception:
+        ///     throws Exception
+        abstract public void Close( bool reset );
+
+        public void Close()
+        {
+            Close( false );
+        }
+
+        public virtual Object TransportQuery( Object query )
+        {
+            if ( query.Equals( LOCAL_ADDRESS ) )
+                return LocalAddress();
+
+            if ( query.Equals( REMOTE_ADDRESS ) )
+                return RemoteAddress();
+
+            if ( query is TransportConsts.WaitUp )
+            {
+                WaitUp( ( ( TransportConsts.WaitUp ) query )._maxDelay );
+                return null;
+            }
+
+            if ( query is TransportConsts.WaitDown )
+            {
+                WaitDown( ( ( TransportConsts.WaitDown ) query )._maxDelay );
+                return null;
+            }
+
+            throw new NotSupportedException("unknown query: " + query);
+        }
+
+        abstract public EndPoint LocalAddress();
+
+        abstract public EndPoint RemoteAddress();
+
+        public void TransportControl( Object control, Object value )
+        {
+            if ( control.Equals( TransportConsts.START ) )
+            {
+                Start();
+                return;
+            }
+
+            if ( control.Equals( TransportConsts.START_AND_WAIT_UP ) )
+            {
+                Start();
+                WaitUp( ( int ) value );
+                return;
+            }
+
+            if ( control.Equals( TransportConsts.STOP ) )
+            {
+                Stop();
+                return;
+            }
+
+            if ( control.Equals( TransportConsts.STOP_AND_WAIT_DOWN ) )
+            {
+                Stop();
+                WaitDown( ( int ) value );
+                return;
+            }
+
+            if (control.Equals( TransportConsts.RESET ))
+            {
+                Close(true);
+                return;
+            }
+
+            throw new NotSupportedException( "unknown control: " + control );
+        }
+
+        public void TransportNotify( Object eventObj )
+        {
+            //ignore
+        }
+
+        private void FireUp()
+	    {
+            status.Set(SessionConsts.UP);
+            TodoManager.AddTodo(new TodoDelegateImpl(
+                delegate(TodoManager mgr)
+                {
+                    session.SessionNotify(SessionConsts.UP);
+                },
+                delegate(TodoManager mgr, Exception e1)
+                {
+                    Console.WriteLine(e1);
+                }));
+          
+	    }
+
+        private void FireDown() 
+	    {
+            status.Set(SessionConsts.DOWN);
+            TodoManager.AddTodo(new TodoDelegateImpl(
+                delegate(TodoManager mgr)
+                {
+                    session.SessionNotify(SessionConsts.DOWN);
+                },
+               delegate(TodoManager mgr, Exception e1)
+               {
+                   Console.WriteLine(e1);
+               }));
+
+        }
+
+        public H GetSession()
+        {
+            return this.session;
+        }
+
+        public void SetSession(H session)
+        {
+            this.session = session;
+        }
+
+        /// <summary>
+        /// The session for the connection.
+        /// </summary>
+        protected H session;
+
+        /// <summary>
+        /// Waits until the connection is up.
+        /// </summary>
+        /// <param name="maxDelay">time in milliseconds to wait.</param>
+        /// Exception:
+        ///     throws ThreadInterruptedException
+        public void WaitUp( int maxDelay ) 
+	    {
+		    status.WaitUntilEq( SessionConsts.UP, maxDelay );
+	    }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="maxDelay">time in milliseconds to wait.</param>
+        /// Exception:
+        ///     throws InterruptedException
+        public void WaitDown( int maxDelay ) 
+	    {
+            status.WaitUntilEq(SessionConsts.DOWN, maxDelay);
+	    }
+
+        private readonly Monitor<String> status = new Monitor<String>( "status", SessionConsts.DOWN );
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/DateSerializer.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/DateSerializer.cs
new file mode 100644
index 0000000..6806b41
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/DateSerializer.cs
@@ -0,0 +1,78 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{ 
+    /// <summary>
+    /// Serialize a DateTime into our network standard format, which
+    /// is the unix standard of milliseconds since jan 1, 1970 utc.
+    /// </summary>
+    public class DateSerializer : ImportExportHelper
+    {
+        private const String FIELD_NAME = "dateTime";
+
+        private readonly XType type;
+        private readonly Field field;
+
+        public DateSerializer( XType type, Field field )
+        {
+            this.type = type;
+            this.field = field;
+        }
+        
+        /// <summary>
+        /// Defines custom fields in the value factory so that the importer
+        /// can find them
+        /// </summary>
+        /// <param name="type"></param>
+        /// <param name="class2type"></param>
+        public static void Init( XType type, Class2TypeMap class2type )
+        {
+            Field field = type.GetField( FIELD_NAME );
+            class2type.Add( typeof( DateTime ), type );
+            type.SetComponentType( typeof( DateTime ) );
+            type.SetImportExportHelper( new DateSerializer( type, field ) );
+            type.PutValidator( field, Validator_long.Get( 0 ) );
+            type.Lock();
+        }
+
+        public override Object ImportValue( StructValue sv )
+        {
+            long ms = (long)sv.Get(field);
+            return new DateTime(epoch + ms * TICKS_PER_MS, DateTimeKind.Utc).ToLocalTime();
+        }
+
+        public override StructValue ExportValue( ValueFactory vf, Object value )
+        {
+            long ms = (((DateTime)value).ToUniversalTime().Ticks - epoch) / TICKS_PER_MS;
+            StructValue sv = new StructValue( type, vf );
+            sv.Add(field, ms);
+            return sv;
+        }
+
+        private const long TICKS_PER_MS = 10000;
+
+        private static readonly long epoch =
+            new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks;
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/EmptyIterator.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/EmptyIterator.cs
new file mode 100644
index 0000000..47596da
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/EmptyIterator.cs
@@ -0,0 +1,65 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public class EmptyIterator<E> : IEnumerator<E>
+    {
+
+        #region IEnumerator<E> Members
+
+        public E Current
+        {
+            get { throw new Exception( "No such element" ); }
+        }
+
+        #endregion
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            throw new Exception( "Invalid operation" );
+        }
+
+        #endregion
+
+        #region IEnumerator Members
+
+        object System.Collections.IEnumerator.Current
+        {
+            get { throw new Exception( "No such element" ); }
+        }
+
+        public bool MoveNext()
+        {
+            return false;
+        }
+
+        public void Reset()
+        {
+            throw new Exception( "Invalid operation" );
+        }
+
+        #endregion
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/EqualsHelper.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/EqualsHelper.cs
new file mode 100644
index 0000000..9d8d0b9
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/EqualsHelper.cs
@@ -0,0 +1,29 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+        /// <param name="a"></param>
+        /// <param name="b"></param>
+        /// <returns>true if the value of a and b are equal even though the format is not 
+        /// (e.g., 23 as a Byte vs. Integer).</returns>
+        public delegate bool Equals(Object a, Object b);
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/FlexBuffer.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/FlexBuffer.cs
new file mode 100644
index 0000000..8cea09a
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/FlexBuffer.cs
@@ -0,0 +1,765 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// A FlexBuffer wraps a byte array and manages the active region of
+    /// it (0..length). It also supports dynamically extending the buffer
+    /// as needed.
+    /// 
+    /// A FlexBuffer also has an index (read or write cursor). The various
+    /// Get and put operations always occur at the current index, with the
+    /// index adjusted appropriately afterward. Get will not move index past
+    /// length. If put needs to move index past length, length is also
+    /// adjusted. This may cause the byte array to be re-allocated to a
+    /// larger size.
+    /// </summary>
+    public sealed class FlexBuffer
+    {
+        /// <summary>
+        /// Constructs a FlexBuffer with initial length and index of 0.
+        /// </summary>
+        public FlexBuffer()
+        	: this(new byte[INIT_BUFFER_LEN], 0, 0)
+        {
+            
+        }
+
+        /// <summary>
+        /// Constructs the FlexBuffer out of an existing buffer, ready to
+        /// read, with the index set to 0 and length set to buffer.length. 
+        /// The buffer is adopted, not copied. If you want to copy, use one 
+        /// of the put methods instead.
+        /// 
+        /// Note: this is the same as FlexBuffer( buffer, 0, buffer.length ).
+        /// </summary>
+        /// <param name="buffer">the buffer to adopt.</param>
+        /// <see cref="put(byte[])"/>
+
+        public FlexBuffer(byte[] buffer)
+        	: this(buffer, 0, buffer.Length)
+        {
+            
+        }
+
+        /// <summary>
+        /// Constructs the FlexBuffer out of an existing buffer, ready to
+        /// read, with the index set to 0 and length set to buffer.length. 
+        /// The buffer is adopted, not copied. If you want to copy, use one 
+        /// of the put methods instead.
+        /// 
+        /// Note: this is the same as FlexBuffer( buffer, 0, length ).
+        /// </summary>
+        /// <param name="buffer">the buffer to adopt.</param>
+        /// <param name="length">the length of the data in the buffer (data presumed
+        /// to start at 0).</param>
+        /// <see cref="put(byte[], int, int)"/>
+
+        public FlexBuffer(byte[] buffer, int length)
+        	: this(buffer, 0, length)
+        {
+            
+        }
+
+        /// <summary>
+        /// Constructs the FlexBuffer out of an existing buffer, ready to
+        /// read, with the index set to 0 and length set to buffer.length. 
+        /// The buffer is adopted, not copied. If you want to copy, use one 
+        /// of the put methods instead.
+        /// 
+        /// Note: if you want to start off writing to the end of the buffer
+        /// and not reading it, specify index as the place to start writing, 
+        /// and length as the amount of data that is valid after index ( which 
+        /// might reasonably be 0 )
+        /// </summary>
+        /// <param name="buffer">the buffer to adopt.</param>
+        /// /// <param name="index">the index to start reading or writing.</param>
+        /// <param name="length">the length of the valid data in the buffer, 
+        /// starting at the index.</param>
+        /// 
+        
+        public FlexBuffer(byte[] buffer, int index, int length )
+        {
+            if ( buffer == null )
+                throw new NullReferenceException( "buffer == null" );
+            if ( index < 0 )
+                throw new ArgumentException( " index < 0 " );
+            if ( length < 0 )
+                throw new ArgumentException( "length < 0 " );
+            if ( index + length > buffer.Length )
+                throw new ArgumentException( "index + length > buffer.Length" );
+
+            this.buffer = buffer;
+            this.index = index;
+            this.length = index + length;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the current byte array. Might change if any operation
+        /// needs to extend length past the end of the array.</returns>
+        public byte[] GetBuf()
+        {
+            return buffer;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="len"></param>
+        /// Exception:
+        ///     throws IOException
+
+        private void EnsureLength( int len ) 
+	    {
+		    int n = buffer.Length;
+		    if (len <= n)
+			    return;
+    		
+            // the buffer is not big enough, expand it
+
+		    int k = n;
+            if ( k < INIT_BUFFER_LEN )
+                k = INIT_BUFFER_LEN;
+
+            while ( len > k && k < MAX_BUFFER_LEN )
+                k = k << 1;
+    		
+		    if (len > k)
+			    throw new IOException( "buffer overflow" );
+    		
+		    byte[] b = new byte[k];
+            Array.Copy( buffer, 0, b, 0, n );
+		    buffer = b;
+	    }
+
+        private byte[] buffer;
+	
+	    private const int INIT_BUFFER_LEN = 32;
+	    
+	    private const int TRIM_BUFFER_LEN = 16*1024;
+	
+	    private const int MAX_BUFFER_LEN = 4*1024*1024;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the current value of length. This is the last
+        /// index of valid data in the buffer.</returns>
+        public int Length()
+        {
+            return length;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="length">length the new value of length. Length must be >= 0.
+        /// If length is less than index, index is also set to length. If length
+        /// is larger than the current buffer, the buffer is expanded.</param>
+        /// <returns>this flex buffer object.</returns>
+        /// Exception:
+        ///     throws ArgumentOutOfRangeException, IOException
+        public FlexBuffer SetLength( int length ) 
+	    {
+		    if (length < 0)
+			    throw new ArgumentOutOfRangeException( "length < 0" );
+    		
+		    EnsureLength( length );
+    		
+		    this.length = length;
+    		
+		    if (index > length)
+			    index = length;
+    		
+		    return this;
+	    }
+
+        private int length;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the current value of index.</returns>
+        public int Index()
+        {
+            return index;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="index">index the new value of index. Index must be >= 0.</param>
+        /// <returns>this flex buffer object.</returns>
+        /// Exception:
+        ///     throws ArgumentOutOfRangeException
+
+        public FlexBuffer SetIndex( int index ) 
+	    {
+		    if (index < 0 || index > length)
+			    throw new ArgumentOutOfRangeException( "index < 0 || index > length" );
+    		
+		    this.index = index;
+    		
+		    return this;
+	    }
+
+        private int index;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>length() - index(). Result is always >= 0. This is the amount
+        /// of data that could be read using the various forms of Get. It doesn't
+        /// really mean anything in relation to put.</returns>
+
+        public int Avail()
+        {
+            return length - index;
+        }
+
+        /// <summary>
+        /// Sets both length and index to 0.
+        /// 
+        /// Shorthand for SetLength( 0 ).
+        /// </summary>
+        /// <returns>this flex buffer object.</returns>
+
+        public FlexBuffer Reset()
+        {
+            index = 0;
+            length = 0;
+		
+			if (buffer.Length > TRIM_BUFFER_LEN)
+				buffer = new byte[TRIM_BUFFER_LEN];
+
+            return this;
+        }
+
+        /// <summary>
+        /// Compacts the buffer by moving remaining data (from index to length)
+        /// to the front of the buffer. Sets index to 0, and sets length to
+        /// Avail (before index was changed).
+        /// </summary>
+        /// <returns>this flex buffer object.</returns>
+
+        public FlexBuffer Compact()
+        {
+            if(index == 0)
+                return this;
+
+            int n = Avail();
+            if(n == 0)
+            {
+                Reset();
+                return this;
+            }
+
+            Array.Copy(buffer, index, buffer, 0, n);
+
+            index = 0;
+            length = n;
+
+            return this;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the byte value at index, and adjusts index
+        /// by adding one.</returns>
+        /// Exception:
+        ///     End of File exception / NullReferenceException
+
+        public int Get() 
+	    {
+		    CheckAvail( 1 );
+
+		    return buffer[index++] & 255;
+	    }
+
+        /// <summary>
+        /// Copies data from the byte array to buf as if by repeated
+        /// calls to Get().
+        /// </summary>
+        /// <param name="buf">a buffer to receive the data. At most
+        /// min( buf.length, Avail() ) bytes are transferred.</param>
+        /// <returns>the amount of data transferred.</returns>
+        /// Exception:
+        ///     End of File exception / NullReferenceException
+
+        public int Get( byte[] buf ) 
+	    {
+            return Get( buf, 0, buf.Length );
+	    }
+
+
+        /// <summary>
+        /// Copies data from the byte array to buf as if by repeated
+        /// calls to Get().
+        /// </summary>
+        /// <param name="buf">a buffer to receive the data. At most
+        /// min( len, Avail() ) bytes are transferred, starting
+        /// at off.</param>
+        /// <param name="off">the index in buf to receive the data.
+        /// off must be >= 0 && less than or equal to buf.length.</param>
+        /// <param name="len">the max amount of data to transfer. Len
+        /// must be >= 0 and less than or equal to buf.length - off.</param>
+        /// <returns>the amount of data transferred.</returns>
+        /// Exception:
+        ///     End of File exception / NullReferenceException
+
+        public int Get( byte[] buf, int off, int len ) 
+	    {
+		    CheckBuf( buf, off, len );
+    		
+		    if (len == 0)
+			    return 0;
+
+            CheckAvail( 1 );
+    		
+		    int n = Math.Min( len, Avail() );
+    		
+	//	    Array.Copy( buffer, index, buf, off, n );
+            Buffer.BlockCopy(buffer, index, buf, off, n);
+		    index += n;
+    		
+		    return n;
+	    }
+
+        public sbyte GetByte()
+        {
+            CheckAvail( 1 );
+            return (sbyte)buffer[ index++ ];
+        }
+        public readonly static bool littleEndian = false;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>a short composed from the next 2 bytes. Little-endian.</returns>
+        /// Exception:
+        ///     throws Exception if avail() < 2
+        public short GetShort()
+        {
+            CheckAvail( 2 );
+
+            if ( littleEndian )
+            {
+                // little-endian
+                int value = buffer[ index++ ] & 255;
+                return ( short ) ( value + ( ( buffer[ index++ ] & 255 ) << 8 ) );
+            }
+            else
+            {
+                // big-endian
+                int value = buffer[ index++ ];
+                return ( short ) ( ( value << 8 ) + ( buffer[ index++ ] & 255 ) );
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>an integer composed of 4 bytes from
+        /// the buffer, with the first byte being the least
+        /// significant and the last being the most significant.</returns>
+        /// Exception:
+        ///     End of File exception / NullReferenceException
+
+        public int GetInt() 
+	    {
+            CheckAvail( 4 );
+
+            if ( littleEndian )
+            {
+                // little-endian
+                int value = buffer[ index++ ] & 255;
+                value += ( ( buffer[ index++ ] & 255 ) << 8 );
+                value += ( ( buffer[ index++ ] & 255 ) << 16 );
+                return value + ( ( buffer[ index++ ] & 255 ) << 24 );
+            }
+            else
+            {
+                // big-endian
+                int value = buffer[ index++ ];
+                value = ( value << 8 ) + ( buffer[ index++ ] & 255 );
+                value = ( value << 8 ) + ( buffer[ index++ ] & 255 );
+                return ( value << 8 ) + ( buffer[ index++ ] & 255 );
+            }
+	    }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>a long comprised of the next 8 bytes. Little-endian</returns>
+        public long GetLong()
+        {
+            CheckAvail( 8 );
+            if ( littleEndian )
+            {
+                // little-endian
+                long value = buffer[ index++ ] & 255;
+                value += ( ( ( long ) ( buffer[ index++ ] & 255 ) ) << 8 );
+                value += ( ( ( long ) ( buffer[ index++ ] & 255 ) ) << 16 );
+                value += ( ( ( long ) ( buffer[ index++ ] & 255 ) ) << 24 );
+                value += ( ( ( long ) ( buffer[ index++ ] & 255 ) ) << 32 );
+                value += ( ( ( long ) ( buffer[ index++ ] & 255 ) ) << 40 );
+                value += ( ( ( long ) ( buffer[ index++ ] & 255 ) ) << 48 );
+                return value + ( ( ( long ) ( buffer[ index++ ] & 255 ) ) << 56 );
+            }
+            else
+            {
+                // big-endian
+                long value = buffer[ index++ ];
+                value = ( value << 8 ) + ( buffer[ index++ ] & 255 );
+                value = ( value << 8 ) + ( buffer[ index++ ] & 255 );
+                value = ( value << 8 ) + ( buffer[ index++ ] & 255 );
+                value = ( value << 8 ) + ( buffer[ index++ ] & 255 );
+                value = ( value << 8 ) + ( buffer[ index++ ] & 255 );
+                value = ( value << 8 ) + ( buffer[ index++ ] & 255 );
+                return ( value << 8 ) + ( buffer[ index++ ] & 255 );
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>a float from the next available bytes</returns>
+        public float GetFloat()
+        {
+            return BitConverter.ToSingle( BitConverter.GetBytes( GetInt() ), 0 );
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>a double from the next available bytes</returns>
+        public double GetDouble()
+        {
+            return BitConverter.Int64BitsToDouble( GetLong() );
+        }
+
+
+        public void GetFully( byte[] b )
+        {
+            CheckAvail( b.Length );
+            int n = Get( b, 0, b.Length );
+            Debug.Assert( n == b.Length );
+        }
+
+        
+        /// <summary>
+        /// Puts a byte into the buffer at the current index,
+        /// then adjusts the index by one. Adjusts the length
+        /// as necessary. The buffer is expanded if needed.
+        /// </summary>
+        /// <param name="b">byte to be put</param>
+        /// <returns>this flex buffer object.</returns>
+        /// Exception: 
+        ///     IOException if the buffer overflows its max length.
+
+        public FlexBuffer Put( int b ) 
+	    {
+		    EnsureLength( index+1 );
+		    buffer[index++] = (byte) b;
+		    FixLength();
+    		
+		    return this;
+	    }
+
+        /// <summary>
+        /// Puts some bytes into the buffer as if by repeated
+        /// calls to put().
+        /// </summary>
+        /// <param name="buf">the source of the bytes to put. The entire
+        /// array of bytes is put.</param>
+        /// <returns>flex buffer object.</returns>
+        /// Exception: 
+        ///     IOException if the buffer overflows its max length.
+        public FlexBuffer Put( byte[] buf ) 
+	    {
+            return Put( buf, 0, buf.Length );
+	    }
+
+        /// <summary>
+        /// Puts some bytes into the buffer as if by repeated
+        /// calls to Put().
+        /// </summary>
+        /// <param name="buf">the source of the bytes to put.</param>
+        /// <param name="off">the index to the first byte to put.</param>
+        /// <param name="len">the number of bytes to put.</param>
+        /// <returns>flex buffer object.</returns>
+        /// Exception:
+        ///     IOException if the buffer overflows its max length.
+
+        public FlexBuffer Put( byte[] buf, int off, int len ) 
+	    {
+		    CheckBuf( buf, off, len );
+    		
+		    if (len == 0)
+			    return this;
+    		
+		    EnsureLength( index+len );
+	//	    Array.Copy( buf, off, buffer, index, len );
+            Buffer.BlockCopy(buf, off, buffer, index, len);
+		    index += len;
+		    FixLength();    
+    		
+		    return this;
+	    }
+
+        /// <summary>
+        /// Copies the Available bytes from buf into buffer as if by
+        /// repeated execution of put( buf.Get() ).
+        /// </summary>
+        /// <param name="buf">the source of the bytes to put. All Available
+        /// bytes are copied.</param>
+        /// <returns>flex buffer object.</returns>
+        /// Exception: 
+        ///     IOException if the buffer overflows its max length.
+
+        public FlexBuffer Put( FlexBuffer buf ) 
+	    {
+            int n = buf.Avail();
+            Put( buf.buffer, buf.index, n );
+            buf.Skip( n, false );
+		    return this;
+	    }
+
+        /// <summary>
+        /// Copies the specified number of bytes from buf into buffer
+        /// as if by repeated execution of Put( buf.Get() ).
+        /// </summary>
+        /// <param name="buf">the source of the bytes to put.</param>
+        /// <param name="len"></param>len the number of bytes to put. Len must be 
+        /// less than or equal to buf.Avail().
+        /// <returns>flex buffer object.</returns>
+        /// Exception:
+        ///     IOException if the buffer overflows its max length.
+
+        public FlexBuffer Put( FlexBuffer buf, int len ) 
+	    {
+		    if (len > buf.Avail())
+			    throw new ArgumentOutOfRangeException( "len > buf.Avail()" );
+
+            Put( buf.buffer, buf.index, len );
+            buf.Skip( len, false );
+		    return this;
+	    }
+
+        public void PutByte( byte value )
+        {
+            EnsureLength( index + 1 );
+            buffer[ index++ ] = ( byte ) value;
+            FixLength();
+        }
+
+        public void PutByte( sbyte value )
+        {
+            EnsureLength( index + 1 );
+            buffer[ index++ ] = ( byte ) value;
+            FixLength();
+        }
+
+        /// <summary>
+        /// Put short as the next 2 bytes. Little-endian
+        /// </summary>
+        /// <param name="value"></param>
+        public void PutShort( short value )
+        {
+            EnsureLength( index + 2 );
+            if ( littleEndian )
+            {
+                buffer[ index++ ] = ( byte ) value;
+                buffer[ index++ ] = ( byte ) ( value >> 8 );
+            }
+            else
+            {
+                /// In C#, since we're using the byte (which is unsigned),
+                /// it doesn't matter whether you do logical or arithmetic 
+                /// shift. Hence, an equivalent of the Java >>> operator is 
+                /// not required here. 
+                buffer[ index++ ] = ( byte ) ( value >> 8 );
+                buffer[ index++ ] = ( byte ) value;
+            }
+            FixLength();
+        }
+
+        public void PutInt( int value )
+        {
+            EnsureLength( length + 4 );
+
+            if ( littleEndian )
+            {
+                buffer[ index++ ] = ( byte ) value;
+                buffer[ index++ ] = ( byte ) ( value >> 8 );
+                buffer[ index++ ] = ( byte ) ( value >> 16 );
+                buffer[ index++ ] = ( byte ) ( value >> 24 );
+            }
+            else
+            {
+
+                buffer[ index++ ] = ( byte ) ( value >> 24 );
+                buffer[ index++ ] = ( byte ) ( value >> 16 );
+                buffer[ index++ ] = ( byte ) ( value >> 8 );
+                buffer[ index++ ] = ( byte ) value;
+                
+            }
+            FixLength();
+        }
+
+        public void PutLong( long value )
+        {
+            EnsureLength( index+8 );
+
+            if ( littleEndian )
+            {
+                buffer[ index++ ] = ( byte ) value;
+                buffer[ index++ ] = ( byte ) ( value >> 8 );
+                buffer[ index++ ] = ( byte ) ( value >> 16 );
+                buffer[ index++ ] = ( byte ) ( value >> 24 );
+                buffer[ index++ ] = ( byte ) ( value >> 32 );
+                buffer[ index++ ] = ( byte ) ( value >> 40 );
+                buffer[ index++ ] = ( byte ) ( value >> 48 );
+                buffer[ index++ ] = ( byte ) ( value >> 56 );
+            }
+            else
+            {
+
+                buffer[ index++ ] = ( byte ) ( value >> 56 );
+                buffer[ index++ ] = ( byte ) ( value >> 48 );
+                buffer[ index++ ] = ( byte ) ( value >> 40 );
+                buffer[ index++ ] = ( byte ) ( value >> 32 );
+                buffer[ index++ ] = ( byte ) ( value >> 24 );
+                buffer[ index++ ] = ( byte ) ( value >> 16 );
+                buffer[ index++ ] = ( byte ) ( value >> 8 );
+                buffer[ index++ ] = ( byte ) value;
+                
+            }
+            FixLength();
+        }
+
+        public void PutFloat( float value )
+        {
+            PutInt( BitConverter.ToInt32( BitConverter.GetBytes( value ), 0 ) );
+        }
+
+        public void PutDouble( double value )
+        {
+            PutLong( BitConverter.DoubleToInt64Bits( value ) );
+        }
+
+
+        /// <summary>
+        /// Adjusts index as if by a Get or put but without transferring
+        /// any data. This could be used to skip over a data item in an
+        /// input or output buffer.
+        /// </summary>
+        /// <param name="len">len the number of bytes to skip over. Len must be
+        /// greater than or equal to 0. If put is false, it is an error if len >Avail(). 
+        /// If put is true, the buffer 
+        /// may be extended (and the buffer length adjusted).</param>
+        /// <param name="put">put if true it is ok to extend the length of the
+        /// buffer.</param>
+        /// <returns>this Flexbuffer object.</returns>
+        /// Exception:
+        ///     IOException 
+        public FlexBuffer Skip( int len, bool put ) 
+	    {
+		    if (len < 0)
+			    throw new ArgumentException( "count < 0" );
+    		
+		    if (len == 0)
+			    return this;
+    		
+		    if (put)
+		    {
+			    EnsureLength( index+len );
+    			
+			    index += len;
+			    FixLength();
+    			
+			    return this;
+		    }
+
+            CheckAvail( len );
+    		
+		    index += len;
+    		
+		    return this;
+	    }
+
+        
+        /// <summary>
+        /// If index has moved past length during a put, then adjust length
+        /// to track index.
+        /// </summary>
+        private void FixLength()
+        {
+            if(index > length)
+                length = index;
+        }
+
+
+        private void CheckBuf(byte[] buf, int off, int len)
+        {
+            if(buf == null)
+                throw new NullReferenceException("buf == null");
+
+            if(off < 0 || off > buf.Length)
+                throw new ArgumentOutOfRangeException("off < 0 || off > buf.length");
+
+            if(len < 0)
+                throw new ArgumentOutOfRangeException("len < 0");
+
+            if(off+len > buf.Length)
+                throw new ArgumentOutOfRangeException("off+len > buf.length");
+        }
+
+        /// <summary>
+        /// Return the currently Available bytes.
+        /// </summary>
+        /// <returns>the currently Available bytes.</returns>
+        /// Exception: 
+        ///     throws an IO Exception
+        public byte[] GetAvailBytes() 
+	    {
+		    byte[] buf = new byte[Avail()];
+		    Get( buf );
+		    return buf;
+	    }
+
+        /// <summary>
+        /// Checks that there are enough bytes to for a read.
+        /// </summary>
+        /// <param name="len">the length required by a read operation.</param>
+        private void CheckAvail( int len )
+        {
+            if ( len > Avail() )
+                throw new EndOfStreamException( " len > Avail() " );
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/HPTimer.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/HPTimer.cs
new file mode 100644
index 0000000..f73dac8
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/HPTimer.cs
@@ -0,0 +1,115 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Runtime.InteropServices;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+	public abstract class HPTimer
+	{
+		[DllImport("kernel32.dll")]
+		private static extern bool QueryPerformanceCounter(out long x);
+
+		[DllImport("kernel32.dll")]
+		private static extern bool QueryPerformanceFrequency(out long x);
+
+		static HPTimer()
+		{
+			long freq = 0;
+
+			if (!QueryPerformanceFrequency(out freq))
+				throw new Exception( "QueryPerformanceFrequency not supported" );
+			
+			// freq is ticks / second.
+			// we wanna compute seconds from ticks.
+			// the easy computation is seconds = ticks / freq
+			// to Get ns, we compute ns = ticks * 1,000,000,000 / freq
+			// the problem is ticks * 1,000,000,000 will likely overflow.
+			// what we want to do is precompute nsPerTick = 1,000,000,000 / freq
+			// and then compute ns = ticks * nsPerTick.
+
+			//Console.WriteLine( "HPTimer: freq = "+freq );
+			nsPerTick = ((double) NS_PER_SECOND)/freq;
+			//Console.WriteLine( "HPTimer: nsPerTick = "+nsPerTick );
+		}
+
+        public const long NS_PER_MICROSECOND = 1000;
+        public const long NS_PER_MILLISECOND = 1000 * NS_PER_MICROSECOND;
+        public const double NS_PER_SECOND = 1000.0 * NS_PER_MILLISECOND;
+
+		/// <summary>
+		/// Returns the current high precision timer value in nanos.
+		/// </summary>
+		/// <returns></returns>
+		public static long Now()
+		{
+			long x = 0;
+			
+			if (!QueryPerformanceCounter(out x))
+				throw new Exception( "QueryPerformanceCounter not supported" );
+
+			return (long) (x * nsPerTick);
+		}
+
+		/// <summary>
+		/// Returns the difference in nanos between the current timer value and
+		/// a timer value previously returned by Now.
+		/// </summary>
+		/// <param name="y"></param>
+		/// <returns></returns>
+		public static long NsSince( long y )
+		{
+			return Now() - y;
+		}
+
+		/// <summary>
+		/// Returns the difference in millis between the current timer value and
+		/// a timer value previously returned by Now.
+		/// </summary>
+		/// <param name="y"></param>
+		/// <returns></returns>
+		public static long MillisSince( long y )
+		{
+            return NsSince(y) / NS_PER_MILLISECOND;
+		}
+
+		/// <summary>
+		/// Returns the difference in seconds between the current timer value and
+		/// a timer value previously returned by Now.
+		/// </summary>
+		/// <param name="y"></param>
+		/// <returns></returns>
+		public static double SecondsSince( long y )
+		{
+            return NsSince(y) / NS_PER_SECOND;
+		}
+
+		/// <summary>
+		/// Returns the number of high precision clock ticks per nano.
+		/// </summary>
+		/// <returns></returns>
+		public static double NsPerTick()
+		{
+			return nsPerTick;
+		}
+
+		private static double nsPerTick;
+	}
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/IdGenerator.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/IdGenerator.cs
new file mode 100644
index 0000000..981a22d
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/IdGenerator.cs
@@ -0,0 +1,81 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Runtime.CompilerServices;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Synchronously generates long id numbers. 
+    /// </summary>
+    public sealed class IdGenerator 
+    {
+        /// <summary>
+        /// Constructs the IdGenerator with the default starting point of 1
+        /// and the default stride of 1.
+        /// </summary>
+        public IdGenerator() : this( 1, 1 )
+        {
+            
+        }
+
+        /// <summary>
+        /// Constructs the IdGenerator with the specified starting point
+        /// and the default stride of 1.
+        /// </summary>
+        /// <param name="nextId"></param>
+        public IdGenerator( long nextId ) : this( nextId, 1 )
+        {
+            
+        }
+
+        /// <summary>
+        /// Constructs the IdGenerator with the specified starting point
+        /// and the specified stride.
+        /// </summary>
+        /// <param name="nextId"></param>
+        /// <param name="stride"></param>
+        public IdGenerator( long nextId, int stride )
+        {
+            if ( stride <= 0 )
+                throw new ArgumentException( "stride <= 0" );
+
+            this.nextId = nextId;
+            this.stride = stride;
+        }
+
+        private long nextId;
+	
+	    private readonly int stride;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>The next Id in sequence</returns>
+        [MethodImpl(MethodImplOptions.Synchronized)]
+        public long Next()
+        {
+            long id = nextId;
+            nextId += stride;
+            return id;
+        }
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/InputStream.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/InputStream.cs
new file mode 100644
index 0000000..23007d6
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/InputStream.cs
@@ -0,0 +1,64 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public interface InputStream
+    {
+        /// <summary>
+        /// Returns the number of bytes that can be read (or skipped over) 
+        /// from this input stream without blocking by the next caller of a 
+        /// method for this input stream.
+        /// </summary>
+        /// <returns></returns>
+         int Available();
+
+        /// <summary>
+        /// Closes this input stream and releases any system resources 
+        /// associated with the stream.
+        /// </summary>
+         void Close();
+
+        /// <summary>
+        /// Reads the next byte of data from the input stream.
+        /// </summary>
+        /// <returns>the next byte of data, or -1 if the end of 
+        /// the stream is reached.</returns>
+         int Read();
+
+        /// <summary>
+        ///  Reads some number of bytes from the input stream and stores them 
+        /// into the buffer array b.
+        /// </summary>
+        /// <param name="buf">the buffer into which the data is read.</param>
+        /// <returns>the total number of bytes read into the buffer, or -1 is 
+        /// there is no more data because the end of the stream has been reached.</returns>
+         int Read(byte[] buf);
+
+        /// <summary>
+        /// Reads up to len bytes of data from the input stream into an array of bytes.
+        /// </summary>
+        /// <param name="b">the buffer into which the data is read.</param>
+        /// <param name="off">the start offset in array b  at which the data is written.</param>
+        /// <param name="len">the maximum number of bytes to read.</param>
+        /// <returns>the total number of bytes read into the buffer, or -1 if there is no more
+        /// data because the end of the stream has been reached.</returns>
+         int Read(byte[] b, int off, int len);
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/IntCounter.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/IntCounter.cs
new file mode 100644
index 0000000..39063c1
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/IntCounter.cs
@@ -0,0 +1,53 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System.Runtime.CompilerServices;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    ///  A safe integer counter
+    /// </summary>
+    public class IntCounter
+    {
+        /// <summary>
+        /// Adjusts the value of the counter by k
+        /// </summary>
+        /// <param name="k">the adjustment to the counter.</param>
+        /// <returns>the new value of the counter.</returns>
+        /// 
+        [MethodImpl( MethodImplOptions.Synchronized )]
+        public int Adjust( int k )
+        {
+            value += k;
+            return value;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the value of the counter</returns>
+        public int Get()
+        {
+            return value;
+        }
+
+        private int value;
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Integer.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Integer.cs
new file mode 100644
index 0000000..c8ae955
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Integer.cs
@@ -0,0 +1,190 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public class Integer : IComparable, IComparable<Integer>, IEquatable<Integer>, IConvertible
+    {
+        public Integer(Integer other)
+        {
+            this.value = other.value;
+        }
+
+        public Integer(int value)
+        {
+            this.value = value;
+        }
+
+        private readonly int value;
+
+        public override string ToString()
+        {
+            return value.ToString();
+        }
+
+        public static implicit operator Integer(int value)
+        {
+            return new Integer(value);
+        }
+
+        public static implicit operator int(Integer value)
+        {
+            return value.value;
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (obj == this)
+                return true;
+
+            if (obj == null || obj.GetType() != GetType())
+                return false;
+
+            Integer other = (Integer)obj;
+            return value == other.value;
+        }
+
+        public override int GetHashCode()
+        {
+            return value;
+        }
+
+        #region IComparable Members
+
+        public int CompareTo(object obj)
+        {
+            if (obj is Integer)
+                return CompareTo((Integer)obj);
+            throw new ArgumentException("obj is not Integer");
+        }
+
+        #endregion
+
+        #region IComparable<Integer> Members
+
+        public int CompareTo(Integer other)
+        {
+            if (value < other.value) return -1;
+            if (value > other.value) return 1;
+            return 0;
+        }
+
+        #endregion
+
+        #region IEquatable<Integer> Members
+
+        public bool Equals(Integer other)
+        {
+            return other != null && value == other.value;
+        }
+
+        #endregion
+
+        #region IConvertible Members
+
+        TypeCode IConvertible.GetTypeCode()
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        bool IConvertible.ToBoolean(IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        byte IConvertible.ToByte(IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        char IConvertible.ToChar(IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        DateTime IConvertible.ToDateTime(IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        decimal IConvertible.ToDecimal(IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        double IConvertible.ToDouble(IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        short IConvertible.ToInt16(IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        int IConvertible.ToInt32(IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        long IConvertible.ToInt64(IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        sbyte IConvertible.ToSByte(IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        float IConvertible.ToSingle(IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        string IConvertible.ToString(IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        object IConvertible.ToType(Type conversionType, IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        ushort IConvertible.ToUInt16(IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        uint IConvertible.ToUInt32(IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        ulong IConvertible.ToUInt64(IFormatProvider provider)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        #endregion
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/ListSerializer.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/ListSerializer.cs
new file mode 100644
index 0000000..21f7cbc
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/ListSerializer.cs
@@ -0,0 +1,96 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public class ListSerializer : ImportExportHelper
+    {
+        private static String FIELD_NAME = "values";
+
+         /// <summary>
+        /// Defines custom fields in the value factory so that the importer
+        /// can find them.
+        /// </summary>
+        /// <param name="type"></param>
+        /// <param name="class2type"></param>
+        public static void Init( XType type, Class2TypeMap class2type )
+        {
+            Field field = type.GetField( FIELD_NAME );
+     /*       class2type.Add( typeof( List<object> ), type );
+            type.SetClass(typeof(List<object>)); */
+            class2type.Add(typeof(ArrayList), type);
+            type.SetComponentType(typeof(ArrayList));
+            type.SetImportExportHelper( new ListSerializer( type, field ) );
+            type.PutValidator( field, Validator_object.Get( 1 ) );
+            type.Lock();
+        }
+
+        public ListSerializer( XType type, Field field )
+        {
+            this.type = type;
+            this.field = field;
+        }
+
+        private readonly XType type;
+        private readonly Field field;
+
+
+        public override Object ImportValue( StructValue sv )
+        {
+       //    List<object> list = new List<object>();
+            ArrayList list = new ArrayList();
+            Object[] values = ( Object[] ) sv.Get( field );
+            int n = values.Length;
+            int index = 0;
+            while ( index < n )
+            {
+               
+                object value = ( object ) values[ index++ ];
+                list.Add( value );
+            }
+
+            return list;
+        }
+
+        public override StructValue ExportValue(ValueFactory vf, Object value)
+        {
+     //       List<object> list = (List<object>)value;
+            ArrayList list = (ArrayList)value;
+            Object[] values = new Object[ list.Count];
+            int index = 0;
+
+            foreach ( object me in list )
+            {
+                values[ index++ ] = me;
+              
+            }
+
+            StructValue sv = new StructValue(type, vf);
+            sv.Add( field, values );
+            return sv;
+
+        }
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/MapSerializer.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/MapSerializer.cs
new file mode 100644
index 0000000..862fdc8
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/MapSerializer.cs
@@ -0,0 +1,98 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public class MapSerializer : ImportExportHelper
+    {
+        private static String FIELD_NAME = "keysAndValues";
+
+         /// <summary>
+        /// Defines custom fields in the value factory so that the importer
+        /// can find them.
+        /// </summary>
+        /// <param name="type"></param>
+        /// <param name="class2type"></param>
+        public static void Init( XType type, Class2TypeMap class2type )
+        {
+            Field field = type.GetField( FIELD_NAME );
+      /*      class2type.Add( typeof( Dictionary<object,object> ), type );
+            type.SetClass(typeof(Dictionary<object, object>)); */
+            class2type.Add(typeof(Hashtable), type);
+            type.SetComponentType(typeof(Hashtable));
+            type.SetImportExportHelper( new MapSerializer( type, field ) );
+            type.PutValidator( field, Validator_object.Get( 1 ) );
+            type.Lock();
+        }
+
+        public MapSerializer( XType type, Field field )
+        {
+            this.type = type;
+            this.field = field;
+        }
+
+        private readonly XType type;
+        private readonly Field field;
+
+
+        public override Object ImportValue( StructValue sv )
+        {
+     //      Dictionary<object,object> map = new Dictionary<object,object>();
+           Hashtable map = new Hashtable();
+            Object[] keysAndValues = ( Object[] ) sv.Get( field );
+            int n = keysAndValues.Length;
+            int index = 0;
+            while ( index < n )
+            {
+                object key = ( object ) keysAndValues[ index++ ];
+                object value = ( object ) keysAndValues[ index++ ];
+                map.Add( key, value );
+            }
+
+            return map;
+        }
+
+        public override StructValue ExportValue(ValueFactory vf, Object value)
+        {
+       //     Dictionary<object, object> map = (Dictionary<object, object>)value;
+
+            Hashtable map = (Hashtable)value;
+
+            Object[] keysAndValues = new Object[ map.Count * 2];
+            int index = 0;
+
+            foreach ( DictionaryEntry me in map )
+            {
+                keysAndValues[ index++ ] = me.Key;
+                keysAndValues[ index++ ] = me.Value;
+            }
+
+            StructValue sv = new StructValue( type, vf );
+            sv.Add( field, keysAndValues );
+            return sv;
+
+        }
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Monitor.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Monitor.cs
new file mode 100644
index 0000000..aa33359
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Monitor.cs
@@ -0,0 +1,301 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Runtime.CompilerServices;
+using System.Threading;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// A class which we can use to monitor conditions.
+    /// </summary>
+    /// <typeparam name="T">Type of object that can be stored in the monitor</typeparam>
+    public class Monitor<T>
+    {
+        /// <summary>
+        /// Constructs the Monitor.
+        /// </summary>
+        /// <param name="description">a description of this monitor</param>
+        /// <param name="initialValue">the initial value of this monitor</param>
+        public Monitor( String description, T initialValue )
+        {
+            this.description = description;
+            this.value = initialValue;
+        }
+        /// <summary>
+        /// Constructs the Monitor with null initial value
+        /// </summary>
+        /// <param name="description">a description of this monitor</param>
+        
+        public Monitor( String description ) : this( description, default( T ) )
+        {   
+        }
+
+        /// <summary>
+        /// Get the description of the Monitor
+        /// </summary>
+        /// <returns> return the description of this monitor</returns>
+
+        public String GetDescription()
+        {
+            return description;
+        }
+
+        private String description;
+	    private T value;
+
+        public override string ToString()
+        {
+            return "Monitor "+description+": "+value;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>The current value of the monitor</returns>
+        public T Get()
+        {
+            return value;
+        }
+
+        /// <summary>
+        /// Sets the current value.
+        /// </summary>
+        /// <param name="newValue"> the value to be set</param>
+        /// <returns>the old value.</returns>
+        [MethodImpl(MethodImplOptions.Synchronized)]
+        public T Set( T newValue )
+	    {
+		    T oldValue = value;
+		    value = newValue;
+		    System.Threading.Monitor.PulseAll(this);
+		    return oldValue;
+	    }
+
+        /// <summary>
+        /// Waits until monitor value is set
+        ///  the value. Will wait forever
+        /// </summary>
+        /// <param name="maxDelay">the max amount of time in ms to wait.
+        /// If 0 is specified, we will wait forever.</param>
+        /// <returns>the current value of the monitor.</returns>
+        /// Exception:
+        ///     throws ThreadInterruptedException if we waited too long.
+        [MethodImpl( MethodImplOptions.Synchronized )]
+        private T WaitUntilSet( long maxDelay )
+		{
+            System.Threading.Monitor.Wait( this, (int) maxDelay );
+            return value;
+	    }
+
+
+        /// <summary>
+        /// Waits until value equals the desired value and
+        /// then sets the value. Will wait forever.
+        /// </summary>
+        /// <param name="desiredValue">the value we want</param>
+        /// <param name="newValue">the value to be set</param>
+        /// <returns>The old value</returns>
+        /// Exception: 
+        ///     throws Exception
+        public T WaitUntilEqAndSet( T desiredValue, T newValue )
+        {
+            return WaitUntilEqAndSet( desiredValue, 0, newValue );
+        }
+
+        /// <summary>
+        /// Waits until value equals the desired value and
+        /// then sets the value
+        /// </summary>
+        /// <param name="desiredValue">the value we want.</param>
+        /// <param name="maxDelay">the max amount of time in ms to wait
+        ///  If 0 is specified, we will wait forever.
+        /// </param>
+        /// <param name="newValue">the value to be set</param>
+        /// <returns>Old Value</returns>
+        /// Exception:  
+        ///     throws ThreadInterruptedException
+        [MethodImpl( MethodImplOptions.Synchronized )]
+        public T WaitUntilEqAndSet( T desiredValue, int maxDelay, T newValue )
+        {
+            WaitUntilEq(desiredValue, maxDelay);
+            return Set(newValue);
+        }
+
+        /// <summary>
+        /// Waits forever until the value is set to the specified value.
+        /// </summary>
+        /// <param name="desiredValue">The value we are waiting for.</param>
+        /// Exception:  
+        ///     throws ThreadInterruptedException
+        public void WaitUntilEq( T desiredValue )
+        { 
+            WaitUntilEq( desiredValue, 0 );
+        }
+
+        /// <summary>
+        /// Waits until the value equals the desired value
+        /// </summary>
+        /// <param name="desiredValue">The value we want</param>
+        /// <param name="maxDelay">the max amount of time in ms to wait.
+        /// If 0 is specified, we will wait forever.</param>
+        /// Exception:
+        ///     throws ThreadInterruptedException if we waited too long.
+        [MethodImpl(MethodImplOptions.Synchronized)]
+        public void WaitUntilEq(T desiredValue, int maxDelay)
+        {
+            CheckDelay(maxDelay);
+            
+            long now = HPTimer.Now(); 
+            long end = EndTime(now, maxDelay);
+ 
+            int d;
+            while (!Eq(value, desiredValue) && (d = RemTime(end, now)) > 0)
+            {
+                System.Threading.Monitor.Wait(this, d);
+                now = HPTimer.Now(); 
+            }
+
+            if (!Eq(value, desiredValue))
+                throw new ThreadInterruptedException("timeout");
+        }
+        
+        
+        /// <summary>
+        /// Waits until value does not equal the undesired value and then
+        /// sets the value. Will wait forever
+        /// </summary>
+        /// <param name="undesiredValue">the value we do not want</param>
+        /// <param name="newValue">the value to be set</param>
+        /// <returns>Old value</returns>
+        /// Exception:
+        ///     throws ThreadInterruptedException
+        public T WaitUntilNotEqAndSet( T undesiredValue, T newValue )
+        {
+            return WaitUntilNotEqAndSet( undesiredValue, 0, newValue );
+        }
+
+        /// <summary>
+        /// Waits until value does not equal the undesired value and then
+        /// sets the value. 
+        /// </summary>
+        /// <param name="undesiredValue">the value we do not want</param>
+        /// <param name="maxDelay">the max amount of time in ms to wait.
+        /// If 0 is specified, we will wait forever.</param>
+        /// <param name="newValue">New value</param>
+        /// <returns>The old value</returns>
+        /// Exception:
+        ///     throws ThreadInterrupedException
+        [MethodImpl( MethodImplOptions.Synchronized )]
+        public T WaitUntilNotEqAndSet( T undesiredValue,
+            int maxDelay, T newValue )
+        {
+            WaitUntilNotEq( undesiredValue, maxDelay );
+            return Set( newValue );
+        }
+
+        /// <summary>
+        /// Waits until value does not equal the undesired value. Will
+        /// wait forever
+        /// </summary>
+        /// <param name="undesiredValue">The value we do not want</param>
+        /// <returns>Curretn value of the monitor</returns>
+        /// Exception:
+        ///     throws ThreadInterruptedException if we waited too long.
+        public T WaitUntilNotEq( T undesiredValue )
+        {
+            return WaitUntilNotEq( undesiredValue, 0 );
+        }
+
+        /// <summary>
+        /// Waits until the value is not the specified value.
+        /// </summary>
+        /// <param name="undesiredValue">the value we do not want.</param>
+        /// <param name="maxDelay">the max amount of time in ms to wait.
+        /// If 0 is specified, we will wait forever.</param>
+        /// <returns>the current value of the monitor</returns>
+        /// Exception:
+        ///     throws ThreadInterruptedException if we waited too long.
+        [MethodImpl(MethodImplOptions.Synchronized)]
+        public T WaitUntilNotEq(T undesiredValue, int maxDelay)
+        {
+            CheckDelay(maxDelay);
+
+            long now = HPTimer.Now();
+            long end = EndTime(now, maxDelay);
+            
+            int d;
+            while (Eq(value, undesiredValue) && (d = RemTime(end, now)) > 0)
+            {
+                System.Threading.Monitor.Wait(this, d);
+                now = HPTimer.Now();              
+            }
+
+            if (Eq(value, undesiredValue))
+                throw new ThreadInterruptedException("timeout");
+
+            return value;
+        }
+
+        private void CheckDelay(int maxDelay)
+        {
+            if (maxDelay < 0)
+                throw new ArgumentException("maxDelay < 0");
+        }
+
+        private long EndTime(long now, int maxDelay)
+        {
+        	if (maxDelay == 0 || maxDelay == int.MaxValue)
+        		return long.MaxValue;
+            
+            return now + maxDelay * HPTimer.NS_PER_MILLISECOND;
+        }
+
+        private int RemTime(long end, long now)
+        {
+        	if (end == long.MaxValue)
+        		return int.MaxValue;
+        	
+        	long ms = (end - now) / HPTimer.NS_PER_MILLISECOND;
+        	if (ms > int.MaxValue)
+        		return int.MaxValue;
+            
+            return (int) ms;
+        }
+
+        /// <summary>
+        /// Compares the specified values.
+        /// </summary>
+        /// <param name="v1">a value to compare, which may be null.</param>
+        /// <param name="v2">another value to compare, which may be null.</param>
+        /// <returns>true if the values are equal, false otherwise. If both
+        /// values are null, they are considered equal.</returns>
+        private bool Eq( T v1, T v2 )
+        {
+            if ( v1 != null && v2 != null )
+                return v1.Equals(v2);
+
+            if ( v1 == null && v2 == null ) 
+                return true;
+
+            return false;
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/OutputStream.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/OutputStream.cs
new file mode 100644
index 0000000..7194d14
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/OutputStream.cs
@@ -0,0 +1,56 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public interface OutputStream
+    {
+        /// <summary>
+        /// Closes this output stream and releases any system resources associated with this stream.
+        /// </summary>
+        void Close();
+
+        /// <summary>
+        /// Writes b.length bytes from the specified byte array to this output stream.
+        /// </summary>
+        /// <param name="b">the data</param>
+        void Write(byte[] b);
+
+        /// <summary>
+        /// Writes len bytes from the specified byte array starting at offset off to this output stream.
+        /// </summary>
+        /// <param name="b">the data</param>
+        /// <param name="off">the start offset in the data.</param>
+        /// <param name="len">the number of bytes to write</param>
+        void Write(byte[] b, int off, int len);
+
+        /// <summary>
+        /// Writes the specified byte to this output stream.
+        /// </summary>
+        /// <param name="b">the byte</param>
+        void Write(int b);
+
+        /// <summary>
+        /// Get bytes from this output stream.
+        /// </summary>
+        /// <returns></returns>
+        byte[] GetBytes();
+    
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Packetizer.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Packetizer.cs
new file mode 100644
index 0000000..ab157bf
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Packetizer.cs
@@ -0,0 +1,297 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Diagnostics;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Packetizes a stream data source. Reads a packet header,
+    /// a 32-bit flag and a 32-bit length, little-endian, verifies
+    /// the flag, and then, using the length from the header,
+    /// reads the packet data and passes it to the packet handler.
+    /// As a packet source, accepts a packet and prepends a packet
+    /// header to it before delivering it to a data source.
+    /// </summary>
+    public class Packetizer : SessionData, TransportPacket
+    {
+
+        /// <summary>
+        /// URI term to specify max packet size
+        /// </summary>
+        public const String MAX_PKT_SIZE_TERM = "Packetizer.maxPktSize";
+
+        private const int SIG = unchecked( (int) 0xdeadbeef );
+
+	    private const int HEADER_SIZE = 8;
+        
+        /// <summary>
+        /// The default maximum packet size that will be accepted, 16376 bytes.
+        /// </summary>
+        public const int DEFAULT_MAX_PKT_SIZE = 16384 - HEADER_SIZE;
+
+        /// <summary>
+        /// Constructs the Packetizer with the specified transport
+        /// and the packet size. 
+        /// </summary>
+        /// <param name="transport">Transport to send data</param>
+        /// <param name="maxPktSize">the maximum packet size that will be accepted.
+        /// Must be >= 0. If maxPktSize == 0, the default will be used.</param>
+        private Packetizer( TransportData transport, int maxPktSize )
+        {
+            if ( maxPktSize < 0 )
+                throw new ArgumentOutOfRangeException( "maxPktSize < 0" );
+
+            this.transport = transport;
+            this.maxPktSize = maxPktSize;
+            
+            transport.SetSession(this);
+        }
+
+   
+
+        public Packetizer( TransportData transport, URL uri, Resources resources )
+            : this( transport, (int)uri.GetIntegerTerm( MAX_PKT_SIZE_TERM, DEFAULT_MAX_PKT_SIZE ) )
+        {
+            // nothing to do.
+        }
+
+        public Packetizer(TransportData transport, String uri, Resources resources)
+        	: this(transport, new URL(uri), resources)
+        {
+           // nothing to do.
+        }
+
+        private readonly TransportData transport;
+
+        private SessionPacket session;
+
+        private readonly int maxPktSize;
+
+        public override string ToString()
+        {
+            return String.Format("Packetizer / {0}", transport);
+        }
+
+        private bool wantHeader = true;
+
+        private int bodyLen;
+
+        private readonly FlexBuffer savedBuf = new FlexBuffer();
+
+        private int ProcessHeader( FlexBuffer buf, bool reset )
+        {
+            int sig = buf.GetInt();
+            if ( sig != SIG )
+                throw new Exception( "bad SIG" );
+
+            int pktSize = buf.GetInt();
+
+            if ( reset )
+                buf.Reset();
+
+            if ( pktSize < 0 || (maxPktSize > 0 && pktSize > maxPktSize) )
+                throw new Exception( "pktSize < 0 || (maxPktSize > 0 && pktSize > maxPktSize)" );
+
+            return pktSize;
+
+        }
+
+  
+
+        public int HeaderSize()
+        {
+            return HEADER_SIZE;
+        }
+
+       
+
+
+        public Object SessionQuery( Object query )
+        {
+            return session.SessionQuery( query );
+        }
+
+        public void SessionControl( Object control, Object value )
+        {
+            session.SessionControl( control, value );
+        }
+
+        public void SessionNotify( Object eventObj )
+        {
+            session.SessionNotify( eventObj );
+        }
+
+
+      
+       
+
+       
+
+        public Object TransportQuery( Object query )
+        {
+            return transport.TransportQuery( query );
+        }
+
+        public void TransportControl( Object control, Object value )
+        {
+            transport.TransportControl( control, value );
+        }
+
+        public void TransportNotify( Object eventObj )
+        {
+            transport.TransportNotify( eventObj );
+        }
+
+        #region TransportPacket Members
+
+        public void SetSession(SessionPacket session)
+        {
+            this.session = session;
+        }
+
+        public SessionPacket GetSession()
+        {
+            return this.session;
+        }
+
+        public void TransportPacket(Who recipient, FlexBuffer buf)
+        {
+            // Data-ize the packet
+
+            // assert index is at the start of the header.
+            int dataSize = buf.Avail();
+            if (dataSize < HEADER_SIZE)
+                throw new ArgumentException("dataSize < HEADER_SIZE");
+
+			int pktSize = dataSize - HEADER_SIZE;
+			if (maxPktSize > 0 && pktSize > maxPktSize)
+				throw new ArgumentException( "maxPktSize > 0 && pktSize > maxPktSize" );
+			
+            int index = buf.Index();
+            buf.PutInt(SIG);
+            buf.PutInt(pktSize);
+            buf.SetIndex(index);
+            transport.TransportData(recipient, buf);
+        }
+
+        #endregion
+
+        #region SessionData Members
+
+        public void SessionData(Who sender, FlexBuffer buf)
+        {
+            while (buf.Avail() > 0)
+            {
+                if (wantHeader)
+                {
+                    // do we have enough to make a header
+                    if ((savedBuf.Length() + buf.Avail()) >= HEADER_SIZE)
+                    {
+                        int pktSize;
+                        if (savedBuf.Length() == 0)
+                        {
+                            // savedBuf is empty, entire header in buf.
+                            pktSize = ProcessHeader(buf, false);
+                        }
+                        else   // header split across savedBuf and buf
+                        {
+                            // move just enough data from buf to savedBuf to have a header.
+
+                            int needFromBuf = HEADER_SIZE - savedBuf.Length();
+                            savedBuf.Put(buf, needFromBuf);
+                            savedBuf.SetIndex(0);
+
+                            pktSize = ProcessHeader(savedBuf, true);
+
+
+                        }
+                        if (pktSize == 0)
+                            continue;
+
+                        bodyLen = pktSize;
+                        wantHeader = false;
+                    }
+                    else     // want header but not enough space to make it
+                    {
+                        // save buf in savedBuf.
+
+                        savedBuf.SetIndex(savedBuf.Length());
+                        savedBuf.Put(buf);
+                    }
+                }
+                else if ((savedBuf.Length() + buf.Avail()) >= bodyLen)
+                {
+                    // want body, and there's enough to make it.
+
+                    // three possible cases: the body is entirely in savedBuf,
+                    // the body is split, or the body is entirely in buf. assert
+                    // that the body cannot entirely be in savedBuf, or else
+                    // we'd have processed it last time.
+
+                    Debug.Assert(savedBuf.Length() < bodyLen);
+
+                    if (savedBuf.Length() == 0)
+                    {
+                        // savedBuf is empty, entire body in buf.
+
+                        int length = buf.Length();
+                        int index = buf.Index();
+                        buf.SetLength(index + bodyLen);
+
+                      //  handler.Packet(sender, buf);
+                        session.SessionPacket(sender,buf);
+
+                        buf.SetLength(length);
+                        buf.SetIndex(index + bodyLen);
+
+                        wantHeader = true;
+                    }
+
+                    else    // body split across savedBuf and buf
+                    {
+                        // move just enough data from buf to savedBuf to have a body.
+
+                        int needFromBuf = bodyLen - savedBuf.Length();
+                        savedBuf.Put(buf, needFromBuf);
+                        savedBuf.SetIndex(0);
+
+               //         handler.Packet(sender, savedBuf);
+                        session.SessionPacket(sender,savedBuf);
+
+                        savedBuf.Reset();
+                        wantHeader = true;
+                    }
+                }
+
+                else     // want body, but there's not enough to make it.
+                {
+                    // save buf in savedBuf.
+
+                    savedBuf.Put(buf);
+                }
+            }
+            // buf is now empty, and there's nothing else to do.
+            Debug.Assert(buf.Avail() == 0);
+        }
+
+        #endregion
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/PerfTest.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/PerfTest.cs
new file mode 100644
index 0000000..61636f4
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/PerfTest.cs
@@ -0,0 +1,117 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Framework for running performance tests.
+    /// </summary>
+    public class PerfTest
+    {
+        private readonly String _descr;
+        private readonly int _runtime;
+        private readonly int _count;
+        private readonly RunTimes _r;
+
+        /// <summary>
+        /// Construct the perftest
+        /// </summary>
+        /// <param name="descr">description of the test</param>
+        /// <param name="runtime">the number of seconds to run each test cycle</param>
+        /// <param name="count">the number of test cycles to run</param>
+        public PerfTest( String descr, int runtime, int count, RunTimes rt )
+        {
+            _descr = descr;
+            _runtime = runtime;
+            _count = count;
+            _r = rt;
+        }
+
+        /// <summary>
+        /// Runs the PerfTest
+        /// </summary>
+        public void Run( )
+        {
+            
+            long oldn = 0;
+            long n = 1;
+            double t = 0;
+
+            while (t < 1)
+		    {
+			    if (t > 0.1)
+				    Console.WriteLine( "{0}: {1} took {2}, trying {3} to get >= 1 second\n", _descr, oldn, t, n );
+			    oldn = n;
+			    t = RunOne( n );
+			    n *= 2;
+		    }
+		    n = oldn;
+
+            int k = 2;
+		    n = (long) (k * n / t);
+		    Console.WriteLine( "{0}: {1} took {2}, trying {3} for {4} seconds\n", _descr, oldn, t, n, k );
+		    oldn = n;
+		    t = RunOne( n );
+
+            k = 4;
+		    n = (long) (k * n / t);
+		    Console.WriteLine( "{0}: {1} took {2}, trying {3} for {4} seconds\n", _descr, oldn, t, n, k );
+		    oldn = n;
+		    t = RunOne( n );
+    		
+		    n = (long) (_runtime * n / t);
+            Console.WriteLine( "{0}: {1} took {2}, using {3} for {4} seconds\n",
+			    _descr, oldn, t, n, _runtime );
+
+            List<double> list = new List<double>( _count );
+            double sum = 0;
+		    for (int i = 1; i <= _count; i++)
+		    {
+			    t = RunOne( n );
+			    double r = n/t;
+			    list.Add( r );
+			    sum += r;
+			    Console.WriteLine( "{0} {1}/{2}\t{3}\t{4}\t{5}\n",
+				    _descr, i, _count, n, t, r );
+		    }
+
+            list.Sort();
+            Console.WriteLine( "{0} min\t{1}\n", _descr, list[ 0 ] );
+            Console.WriteLine( "{0} median\t{1}\n", _descr, list[ _count/2 ] );
+		    Console.WriteLine( "{0} avg\t{1}\n", _descr, sum/_count );
+		    Console.WriteLine( "{0} max\t{1}\n", _descr, list[ _count-1 ] );
+        }
+
+        private double RunOne( long n )
+        {
+            long t0 = HPTimer.Now();
+            _r( n );
+            return HPTimer.SecondsSince(t0);
+        }
+
+        /// <summary>
+        /// Runs the test with the specific number of times.
+        /// </summary>
+        /// <param name="n"></param>
+        public delegate void RunTimes( long n );
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Resources.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Resources.cs
new file mode 100644
index 0000000..1e74ee3
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Resources.cs
@@ -0,0 +1,48 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public class Resources : Dictionary<String, Object>
+    {
+        public Resources()
+        {
+            // ignore
+        }
+
+        public Resources( Resources r )
+            : base( r )
+        { }
+
+        public Object Get( String key )
+        {
+            try
+            {
+                return this[ key ];
+            }
+            catch ( KeyNotFoundException )
+            {
+                return null;
+            }
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Runner.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Runner.cs
new file mode 100644
index 0000000..02df951
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Runner.cs
@@ -0,0 +1,134 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Threading;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Implementation of startable which creates a thread and runs.
+    /// </summary>
+    abstract public class Runner : AbstractStartable 
+    {
+        /// <summary>
+        /// Constructs the Runner.
+        /// </summary>
+        public Runner()
+        { 
+            // nothing to do.
+        }
+
+        /// <summary>
+        /// The handler is used to report started and stopped events.
+        /// </summary>
+        private RunnerHandler handler;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="handler">handler the handler to notify of started and stopped events.</param>
+        public void SetHandler(RunnerHandler handler)
+        {
+            this.handler = handler;
+        }
+
+        protected override void Start0()
+        {
+            thisThread = new Thread(new ThreadStart(Run));
+            thisThread.Start();
+        }
+
+        Thread thisThread;
+
+        protected override void Stop0()
+        {
+            Thread t = thisThread;
+            if (t != null)
+            {
+                thisThread = null;
+      //          t.Join( 30 );
+            }
+        }
+
+        public void Run()
+        {
+            FireStarted();
+
+            try
+            {
+                bool first = true;
+                while (IsStarted())
+                {
+                    if (!Run0(first))
+                        break;
+                    first = false;
+                }
+            }
+            catch (Exception e)
+            {
+                FireException("run", e);
+            }
+            finally
+            {
+                SetStopped();
+                FireStopped();
+            }
+        }
+
+        private void FireStarted()
+        {
+            handler.Started();
+        }
+
+        /// <summary>
+        /// Reports an exception caught by the thread managing the runnable.
+        /// </summary>
+        /// <param name="what"></param>
+        /// <param name="e"></param>
+        protected void FireException(String what, Exception e)
+        {
+            //Console.WriteLine( e );
+            try
+            {
+                handler.Exception(what, e);
+            }
+            catch (Exception x)
+            {
+                Console.WriteLine(e);
+                Console.WriteLine(x);
+            }
+        }
+
+        private void FireStopped()
+        {
+            handler.Stopped();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="first">true the first time we are called</param>
+        /// <returns>true if we should keep running.</returns>
+        /// Exception:
+        ///     throws Exception
+        abstract protected bool Run0(bool first);
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/RunnerHandler.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/RunnerHandler.cs
new file mode 100644
index 0000000..8e60cfe
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/RunnerHandler.cs
@@ -0,0 +1,48 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// RunnerHandler receives notification of runner events.
+    /// </summary>
+    public interface RunnerHandler
+    {
+        /// <summary>
+        /// Reports that the thread controlling the runner has started.
+        /// </summary>
+        void Started( );
+
+        /// <summary>
+        /// Reports that the thread controlling the runner has stopped.
+        /// </summary>
+        void Stopped();
+
+        /// <summary>
+        /// Reports that the thread controlling the runner has caught an
+        /// exception.
+        /// </summary>
+        /// <param name="what">A short description of the origin</param>
+        /// <param name="e">Exception that was caught</param>
+        void Exception( String what, Exception e );
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Session.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Session.cs
new file mode 100644
index 0000000..efbc579
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Session.cs
@@ -0,0 +1,81 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Out-of-band query, control, and notification interface for sessions.
+    /// </summary>
+    public interface Session
+    {
+        /// <summary>
+        /// Gets a configuration or operational value from the handler. The
+        /// request is passed up the chain of sessions until some session
+        /// recognises the query, whereupon it returns the requested value.
+        /// </summary>
+        /// <param name="query">an object representing a query, which could be as
+        /// simple as a string, integer, or enum, or more complex such as
+        /// a class with instance variables for query terms.</param>
+        /// <returns>the requested value, or null if not defined.</returns>
+        /// Exception:
+        ///     throws Exception if the query is not recognised
+        ///     by any session (which is to say, if the last session in the session
+        ///     chain does not recognise it, it should throw this exception). Typically
+        ///     this would be a service's client or server implementation.
+        ///     
+        Object SessionQuery( Object query );
+
+        /// <summary>
+        /// Sets a configuration or operational value in the session. The
+        /// request is passed up the chain of sessions until some session
+        /// recognises the control, whereupon it stores the specified value
+        /// and returns.
+        /// </summary>
+        /// <param name="control">an object representing a control, which could be as
+        /// simple as a string, integer, or enum, or more complex such as
+        /// a class with instance variables for control terms.</param>
+        /// <param name="value">the value to set</param>
+        /// Exception:
+        /// 
+        ///     throws ArgumentException if the value is not the right
+        ///     type or if the value is inappropriate.
+        /// 
+        ///     throws Exception if the query is not recognised
+        ///     by any session (which is to say, if the last session in the session
+        ///     chain does not recognise it, it should throw this exception). Typically
+        ///     this would be a service's client or server implementation.
+        ///     
+        void SessionControl( Object control, Object value );
+
+        /// <summary>
+        /// Notifies the chain of sessions of the specified event. Unlike query
+        /// and control operations above, events are always passed up to the
+        /// top to allow all sessions to notice them.
+        /// </summary>
+        /// <param name="eventObj">a class which represents the event, possibly with
+        /// parameters. The simplest event could be a string, integer,
+        /// or enum, but any class instance will do (as long as some session
+        /// in the chain expects it).</param>
+        /// 
+        void SessionNotify( Object eventObj );
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/SessionConsts.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/SessionConsts.cs
new file mode 100644
index 0000000..7a61b24
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/SessionConsts.cs
@@ -0,0 +1,41 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public class SessionConsts
+    {
+
+        #region WELL KNOWN EVENTS
+
+        /// <summary>
+        /// Session event reporting the transport is up.
+        /// </summary>
+        public const String UP = "UP";
+
+        /// <summary>
+        /// Session event reporting the transport is down.
+        /// </summary>
+        public const String DOWN = "DOWN";
+
+        #endregion
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/SessionData.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/SessionData.cs
new file mode 100644
index 0000000..e3dd305
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/SessionData.cs
@@ -0,0 +1,26 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public interface SessionData : Session
+    {
+        void SessionData(Who sender, FlexBuffer buf);
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/SessionListener.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/SessionListener.cs
new file mode 100644
index 0000000..019c455
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/SessionListener.cs
@@ -0,0 +1,30 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Interface used to deliver new connections to the session from the listener.
+    /// </summary>
+    /// <typeparam name="T">the type of the connection for the session.</typeparam>
+    public interface SessionListener<T> : Session
+    {
+        void SessionAccepted(T socket);
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/SessionPacket.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/SessionPacket.cs
new file mode 100644
index 0000000..db0ae8e
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/SessionPacket.cs
@@ -0,0 +1,26 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public interface SessionPacket : Session
+    {
+        void SessionPacket(Who sender, FlexBuffer buf);
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/SingleIterator.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/SingleIterator.cs
new file mode 100644
index 0000000..7ee7c76
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/SingleIterator.cs
@@ -0,0 +1,90 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// An iterator over a single object
+    /// </summary>
+    public class SingleIterator<E> : IEnumerator<E>
+    {
+        private E _obj;
+
+        public SingleIterator( Object obj )
+        {
+            _obj = ( E ) obj;
+        }
+
+        #region IEnumerator<E> Members
+
+        public E Current
+        {
+            get 
+            {
+                if ( _obj == null )
+                    throw new Exception( "No Such element" );
+
+                E o = _obj;
+                _obj = default(E);
+                return o;
+            }
+        }
+
+        #endregion
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            throw new Exception( "The method or operation is not implemented." );
+        }
+
+        #endregion
+
+        #region IEnumerator Members
+
+        object System.Collections.IEnumerator.Current
+        {
+            get
+            {
+                if ( _obj == null )
+                    throw new Exception( "No Such element" );
+
+                E o = _obj;
+                _obj = default( E );
+                return o;
+            }
+        }
+
+        public bool MoveNext()
+        {
+            return _obj != null;
+        }
+
+        public void Reset()
+        {
+            throw new Exception( "The method or operation is not implemented." );
+        }
+
+        #endregion
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Startable.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Startable.cs
new file mode 100644
index 0000000..38207be
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Startable.cs
@@ -0,0 +1,50 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Description of Startable
+    /// </summary>
+    public interface Startable
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        /// Exception:
+        ///     throws Exception
+        void Start();
+
+        /// Exception:
+        ///     throws Exception
+        void Stop();
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>true if started</returns>
+        bool IsStarted();
+
+        /// <summary>
+        /// Check the startable is started
+        /// </summary>
+        void CheckIsStarted();
+    
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StrIntHashMap.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StrIntHashMap.cs
new file mode 100644
index 0000000..4903da8
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StrIntHashMap.cs
@@ -0,0 +1,43 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System.Collections.Generic;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// A hashmap which is from string to integer
+    /// </summary>
+    public class StrIntHashMap : Dictionary<string, int?>
+    {
+        public StrIntHashMap()
+        {
+            // nothing to do .
+        }
+
+        /// <summary>
+        /// Constructs a StrIntHashMap initialized from another
+        /// </summary>
+        /// <param name="other"></param>
+        public StrIntHashMap( StrIntHashMap other )
+            : base( other )
+        { }
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StrIntHashMapSerializer.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StrIntHashMapSerializer.cs
new file mode 100644
index 0000000..f089cff
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StrIntHashMapSerializer.cs
@@ -0,0 +1,95 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// An etch serializer for StrIntHashMap.
+    /// </summary>
+    public class StrIntHashMapSerializer : ImportExportHelper
+    {
+        private static String FIELD_NAME = "keysAndValues";
+
+        /// <summary>
+        /// Defines custom fields in the value factory so that the importer
+        /// can find them.
+        /// </summary>
+        /// <param name="type"></param>
+        ///  <param name="class2type"></param>
+        public static void Init( XType type, Class2TypeMap class2type )
+        {
+            Field field = type.GetField( FIELD_NAME );
+            class2type.Add( typeof( StrIntHashMap ), type );
+            type.SetComponentType( typeof( StrIntHashMap ) );
+            type.SetImportExportHelper( new StrIntHashMapSerializer( type, field ) );
+            type.PutValidator( field, Validator_object.Get( 1 ) );
+            type.Lock();
+        }
+
+        public StrIntHashMapSerializer( XType type, Field field )
+        {
+            this.type = type;
+            this.field = field;
+        }
+
+        private readonly XType type;
+        private readonly Field field;
+
+        public override Object ImportValue( StructValue sv )
+        {
+            StrIntHashMap map = new StrIntHashMap();
+
+            Object[] keysAndValues = ( Object[] ) sv.Get( field );
+            int n = keysAndValues.Length;
+            int index = 0;
+            while ( index < n )
+            {
+                string key = ( String ) keysAndValues[ index++ ];
+                int? value = ( int? ) keysAndValues[ index++ ];
+                map.Add( key, value );
+            }
+            
+            return map;
+        }
+
+        public override StructValue ExportValue(ValueFactory vf, Object value)
+        {
+            StrIntHashMap map = ( StrIntHashMap ) value;
+
+            Object[] keysAndValues = new Object[ map.Count * 2 ];
+            int index = 0;
+
+            foreach( KeyValuePair<String, int?> me in map )
+            {
+                keysAndValues[ index++ ] = me.Key;
+                keysAndValues[ index++ ] = me.Value;
+            }
+
+            StructValue sv = new StructValue(type, vf);
+            sv.Add( field, keysAndValues );
+            return sv;
+
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StrStrHashMap.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StrStrHashMap.cs
new file mode 100644
index 0000000..4a046fb
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StrStrHashMap.cs
@@ -0,0 +1,43 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System.Collections.Generic;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// A hashmap which is from string to integer
+    /// </summary>
+    public class StrStrHashMap : Dictionary<string, string>
+    {
+        public StrStrHashMap()
+        {
+            // nothing to do .
+        }
+
+        /// <summary>
+        /// Constructs a StrStrHashMap initialized from another
+        /// </summary>
+        /// <param name="other"></param>
+        public StrStrHashMap( StrStrHashMap other )
+            : base( other )
+        { }
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StrStrHashMapSerializer.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StrStrHashMapSerializer.cs
new file mode 100644
index 0000000..a1c5741
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StrStrHashMapSerializer.cs
@@ -0,0 +1,97 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// An etch serializer for StrStrHashMap.
+    /// </summary>
+    public class StrStrHashMapSerializer : ImportExportHelper
+    {
+        private static String FIELD_NAME = "keysAndValues";
+
+        /// <summary>
+        /// Defines custom fields in the value factory so that the importer
+        /// can find them.
+        /// </summary>
+        /// <param name="type"></param>
+        /// <param name="class2type"></param>
+        public static void Init( XType type, Class2TypeMap class2type )
+        {
+            Field field = type.GetField( FIELD_NAME );
+            class2type.Add( typeof( StrStrHashMap ), type );
+            type.SetComponentType( typeof( StrStrHashMap ) );
+            type.SetImportExportHelper( new StrStrHashMapSerializer( type, field ) );
+            type.PutValidator( field, Validator_object.Get( 1 ) );
+            type.Lock();
+        }
+
+        public StrStrHashMapSerializer( XType type, Field field )
+        {
+            this.type = type;
+            this.field = field;
+        }
+
+        private readonly XType type;
+        private readonly Field field;
+
+
+        public override Object ImportValue( StructValue sv )
+        {
+            StrStrHashMap map = new StrStrHashMap();
+
+            Object[] keysAndValues = ( Object[] ) sv.Get( field );
+            int n = keysAndValues.Length;
+            int index = 0;
+            while ( index < n )
+            {
+                String key = ( String ) keysAndValues[ index++ ];
+                String value = ( String ) keysAndValues[ index++ ];
+                map.Add( key, value );
+            }
+
+            return map;
+        }
+
+        public override StructValue ExportValue(ValueFactory vf, Object value)
+        {
+            StrStrHashMap map = ( StrStrHashMap ) value;
+
+            Object[] keysAndValues = new Object[ map.Count * 2 ];
+            int index = 0;
+
+            foreach ( KeyValuePair<String, String> me in map )
+            {
+                keysAndValues[ index++ ] = me.Key;
+                keysAndValues[ index++ ] = me.Value;
+            }
+
+            StructValue sv = new StructValue(type, vf);
+            sv.Add( field, keysAndValues );
+            return sv;
+
+        }
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StringTokenizer.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StringTokenizer.cs
new file mode 100644
index 0000000..079d1dc
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StringTokenizer.cs
@@ -0,0 +1,87 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public class StringTokenizer
+    {
+        public StringTokenizer(string s, string seps)
+        {
+            this.s = s;
+            this.seps = seps;
+        }
+
+        private readonly string s;
+
+        private readonly string seps;
+
+        private int index = 0;
+
+        public bool HasMoreTokens()
+        {
+            if (token == null)
+                token = GetNextToken();
+
+            return token != null;
+        }
+
+        public string NextToken()
+        {
+            if (token == null)
+            {
+                token = GetNextToken();
+                if (token == null)
+                    throw new IndexOutOfRangeException("no more tokens");
+            }
+
+            string t = token;
+            token = null;
+            return t;
+        }
+
+        private string GetNextToken()
+        {
+            SkipSeps();
+
+            int i = index;
+            while (index < s.Length  &&  !IsSep(s[index]))
+                index++;
+
+            if (index > i)
+                return s.Substring(i, index - i);
+
+            return null;
+        }
+
+        private void SkipSeps()
+        {
+            while (index < s.Length && IsSep(s[index]))
+                index++;
+        }
+
+        private bool IsSep(char c)
+        {
+            return seps.IndexOf(c) >= 0;
+        }
+
+        private string token;
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StringUtil.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StringUtil.cs
new file mode 100644
index 0000000..7995643
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/StringUtil.cs
@@ -0,0 +1,121 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Miscellaneous string utility functions
+    /// </summary>
+    /// 
+    public class StringUtil
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="s"></param>
+        /// <param name="c"></param>
+        /// <returns>an array x of two elements containing s split in two by the
+        /// leftmost c. x[0] is the chars before c, x[1] is the chars after c.
+        /// If c is not in s, returns null.</returns>
+        /// 
+        public static String[] LeftSplit( String s, char c )
+        {
+            if ( s == null )
+                throw new ArgumentNullException( "Passed string is null" );
+
+            int i = s.IndexOf( c );
+            if ( i < 0 )
+                return null;
+
+            return new String[] { s.Substring( 0, i ), s.Substring( i+1 ) };
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="s"></param>
+        /// <param name="c"></param>
+        /// <returns>an array x of two elements containing s split in two by the
+        /// rightmost c. x[0] is the chars before c, x[1] is the chars after c.
+        /// If c is not in s, returns null.</returns>
+        public static String[] RightSplit( String s, Char c )
+        {
+            if ( s == null )
+                throw new ArgumentNullException( "Passed string is null" );
+
+            int i = s.LastIndexOf( c );
+            if ( i < 0 )
+                return null;
+
+            return new String[] { s.Substring( 0, i ), s.Substring( i+1 ) };
+        }
+
+        /// <summary>
+        /// Translates an int into a hex char.
+        /// </summary>
+        /// <param name="i">i an int (0-15)</param>
+        /// <returns>a hex char (0-9, a-f).</returns>
+        /// 
+        public static char ToHex( int i )
+        {
+            if ( i >= 0 && i <= 9 )
+                return ( char ) ( '0' + i );
+            if ( i >= 10 && i <= 15 )
+                return ( char ) ( 'a' + i - 10 );
+            throw new ArgumentException( "bad hex digit selector "+i );
+        }
+
+        /// <summary>
+        /// Translates a hex char into an int.
+        /// </summary>
+        /// <param name="c">a hex char (0-9, A-F, a-f).</param>
+        /// <returns>an int (0-15).</returns>
+        /// 
+        public static int FromHex( char c )
+        {
+            if ( c >= '0' && c <= '9' )
+                return c - '0';
+            if ( c >= 'A' && c <= 'F' )
+                return c - 'a' + 10;
+            if ( c >= 'a' && c <= 'f' )
+                return c - 'a' + 10;
+            throw new ArgumentException( "bad hex char "+c );
+        }
+
+        public static bool Eq(string a, string b)
+        {
+            if (ReferenceEquals(a, b))
+                return true;
+            if (a == null || b == null)
+                return false;
+            return a.Equals(b);
+        }
+
+        public static bool EqIgnoreCase(string a, string b)
+        {
+            if (ReferenceEquals(a, b))
+                return true;
+            if (a == null || b == null)
+                return false;
+            return a.Equals(b, StringComparison.CurrentCultureIgnoreCase);
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TcpConnection.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TcpConnection.cs
new file mode 100644
index 0000000..69bef89
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TcpConnection.cs
@@ -0,0 +1,107 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Implementation of connection which handles a tcp connection.
+    /// </summary>
+    public class TcpConnection : TcpTransport
+    {
+        public TcpConnection(Socket socket, string uri, Resources resources)
+            : this(socket, new URL(uri), resources)
+        {
+            // nothing to do.
+        }
+
+        public TcpConnection(Socket socket, URL uri, Resources resources)
+            : base(uri, resources)
+        {
+            if (socket == null)
+            {
+                if (uri.Host == null)
+                    throw new ArgumentNullException("host");
+                host = uri.Host;
+
+                if (uri.Port == null)
+                    throw new ArgumentNullException("port");
+                port = (int)uri.Port;
+
+                if (port <= 0 || port >= 65536)
+                    throw new ArgumentException("port <= 0 || port >= 65536");
+
+                this.socket = null;
+                //this.host = host;
+                //this.port = (int)port;
+            }
+            else
+            {
+                this.socket = socket;
+                host = null;
+                port = 0;
+            }
+        }
+
+        private readonly String host;
+
+        private readonly int port;
+
+        public override string ToString()
+        {
+            Socket s = socket;
+
+            if (s != null)
+                return String.Format("TcpConnection(up, {0}, {1})",
+                    s.LocalEndPoint, s.RemoteEndPoint);
+
+            return String.Format("TcpConnection(down, {0}, {1})", host, port);
+        }
+
+        protected override bool IsServer()
+        {
+            return host == null;
+        }
+
+        protected override Socket NewSocket()
+        {
+            IPAddress addr;
+
+            if (host != null)
+            {
+                IPAddress[] addrs = Dns.GetHostAddresses(host);
+                if (addrs == null || addrs.Length == 0)
+                    throw new ArgumentException("host is invalid");
+                addr = addrs[0];
+            }
+            else
+            {
+                addr = IPAddress.Any;
+            }
+
+            IPEndPoint ipe = new IPEndPoint(addr, port);
+            Socket socket = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+            socket.Connect(ipe);
+            return socket;
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TcpListener.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TcpListener.cs
new file mode 100644
index 0000000..0bbb021
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TcpListener.cs
@@ -0,0 +1,272 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Runtime.CompilerServices;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Implementation of a connection which handles a socket listener.
+    /// </summary>
+    public class TcpListener : Connection<SessionListener<Socket>>
+    {
+        /// <summary>
+        /// Constructs the TcpListener.
+        /// </summary>
+        /// <param name="backlog">max number of pending connection requests.</param>
+        /// <param name="host">address to listen to. Null means any local address.</param>
+        /// <param name="port">port to listen on. Port must be >= 0. Port of 0
+        /// means allocate an available port.</param>
+        /// <param name="delay">how long in milliseconds to wait before retrying a
+        /// failure. Delay must be >= 0. Delay of 0 means do not retry.</param>
+
+        private TcpListener( int backlog, String host, int port, int delay ) 
+        {
+            if ( backlog < 0 )
+                throw new ArgumentException( "backlog < 0" );
+
+            if ( port < 0 || port > 65535 )
+                throw new ArgumentException( "port < 0 || port > 65535" );
+
+            if ( delay < 0 )
+                throw new ArgumentException( "delay < 0" );
+
+            this.backlog = backlog;
+            this.host = host;
+            this.port = port;
+            this.delay = delay;
+        }
+
+        /// <summary>
+        /// Query term from URI to specify backlog value to ServerSocket. The
+        /// value is "TcpListener.backlog".
+        /// </summary>
+        public const String BACKLOG = "TcpListener.backlog";
+
+
+        public TcpListener(URL uri, Resources resources)
+            : this((int)uri.GetIntegerTerm(BACKLOG, 0), TranslateHost(uri.Host), uri.Port != null ? uri.Port.Value : 0, 0)
+        {
+            // nothing else.
+        }
+
+        /// <summary>
+        /// Constructs a TcpListener, initialized from the URI. Listens on the host
+        /// and port specified in the URI. To listen on all interfaces, specify
+        /// host as ALL_INTFS ("0.0.0.0"). If port is specified or defaulted to 0,
+        /// an unused port will be selected.
+        /// </summary>
+        /// <param name="uri"></param>
+
+        public TcpListener(string uri, Resources resources)
+            : this(new URL(uri), resources)
+        {
+            // nothing else.
+        }
+
+        private int backlog;
+	
+	    private String host;
+    	
+	    private int port;
+    	
+	    private int delay;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// Exception:
+        ///     throws Exception
+        
+        protected override void Stop0()
+        {
+            Close( true );
+            base.Stop0();
+        }
+        
+        /// <summary>
+        /// 
+        /// </summary>
+        /// Exception:
+        ///     throws Exception
+        /// <returns></returns>
+        private Socket CheckSocket()
+        {
+            Socket ss = serverSocket;
+            if ( ss == null )
+            {
+                //Console.WriteLine( "----socket was null----" );
+                throw new IOException("server socket is closed");
+            }
+            return ss;
+        }
+
+        private Socket serverSocket;
+
+        public override string ToString()
+        {
+            Socket ss = serverSocket;
+
+            if ( ss == null )
+                return String.Format("TcpListener (down, {0}:{1})", host, port);
+
+            return String.Format("TcpListener (up, {0})", ss.LocalEndPoint);
+        }
+
+        [MethodImpl (MethodImplOptions.Synchronized)]
+        protected override bool OpenSocket( bool reconnect )
+        {
+            bool first = true;
+            while ( IsStarted() )
+            {
+                if ( reconnect || !first )
+                {
+                    if ( delay == 0 )
+                        return false;
+
+                    System.Threading.Monitor.Wait(this, delay);
+
+                    if ( !IsStarted() )
+                        break;
+                }
+
+                try
+                {
+                    //IPHostEntry ipEntry = Dns.GetHostEntry( host );
+
+                    IPAddress addr;
+                    if ( host != null )
+                    {
+                        IPAddress[] addrs = Dns.GetHostAddresses( host );
+                        if ( addrs == null || addrs.Length == 0 )
+                            throw new ArgumentException( "host is invalid" );
+                        addr = addrs[ 0 ];
+                    }
+                    else 
+                    {
+                        addr = IPAddress.Any;
+                    }
+                    
+                    //IPAddress[] addr = ipEntry.AddressList;
+                    //string sIPAddress = addr[ 0 ].ToString();
+
+                    IPEndPoint ipe = new IPEndPoint( addr, port );
+                    
+                    serverSocket = new Socket( ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp );
+
+                    try
+                    {
+                        serverSocket.Bind(ipe);
+                    }
+                    catch (SocketException e)
+                    {
+                        throw new IOException("Could not bind address "+host+":"+port, e);
+                    }
+
+                    serverSocket.Listen( backlog );
+
+                    return true;
+                }
+                catch (Exception e)
+                {
+                    if ( first )
+                    {
+                        first = false;
+                        FireException( "open", e );
+                    }
+                }
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// Exception:
+        ///     throws Exception
+        protected override void SetUpSocket()
+        {
+            // nothing to do.
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// Exception:
+        ///     throws Exception
+        protected override void ReadSocket()
+        {
+            try
+            {
+                Socket ss = CheckSocket();
+                while (IsStarted())
+                {
+                    Socket s = ss.Accept();
+
+                    try
+                    {
+                        session.SessionAccepted(s);
+                    }
+                    catch (Exception e)
+                    {
+                        s.Close();
+                        FireException("accepted", e);
+                    }
+                }
+            }
+            catch (SocketException e)
+            {
+                if (e.Message != null && e.Message.Contains("interrupted"))
+                    return;
+                throw;
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="reset"></param>
+        /// Exception:
+        ///     throws Exception
+        public override void Close( bool reset )
+        {
+            Socket ss = serverSocket;
+            if ( ss != null )
+            {
+                serverSocket = null;
+                ss.Close();
+            }
+        }
+
+        public override EndPoint LocalAddress()
+        {
+            return CheckSocket().LocalEndPoint;
+        }
+
+        public override EndPoint RemoteAddress()
+        {
+            // ignore
+            return null;
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TcpOptions.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TcpOptions.cs
new file mode 100644
index 0000000..fd04bf1
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TcpOptions.cs
@@ -0,0 +1,168 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// TCP connection options.
+    /// </summary>
+    public class TcpOptions
+    {
+        /// <summary>
+        /// Constructs TcpOptions from uri and resources.
+        /// </summary>
+        /// <param name="uri"></param>
+        /// <param name="resources"></param>
+        public TcpOptions( URL uri, Resources resources )
+        {
+            autoFlush = uri.GetBooleanTerm(AUTO_FLUSH, false);
+            bufferSize = CheckBufferSize(uri.GetIntegerTerm(BUFFER_SIZE, 0));
+            keepAlive = uri.GetBooleanTerm(KEEP_ALIVE, false);
+            lingerTime = CheckLingerTime(uri.GetIntegerTerm(LINGER_TIME, 30));
+            noDelay = uri.GetBooleanTerm(NO_DELAY, true);
+            reconnectDelay = CheckReconnectDelay(uri.GetIntegerTerm(RECONNECT_DELAY, 0));
+            trafficClass = CheckTrafficClass(uri.GetIntegerTerm(TRAFFIC_CLASS, 0));
+        }
+
+        private static int CheckBufferSize(int bufferSize)
+        {
+            if (bufferSize < 0 || bufferSize > 65536)
+                throw new ArgumentException(
+                    "bufferSize < 0 || bufferSize > 65536");
+            return bufferSize;
+        }
+
+        private static int CheckLingerTime(int lingerTime)
+        {
+            if (lingerTime < -1 || lingerTime > 240)
+                throw new ArgumentException(
+                    "lingerTime < -1 || lingerTime > 240");
+            return lingerTime;
+        }
+
+        private static int CheckReconnectDelay(int reconnectDelay)
+        {
+            if (reconnectDelay < 0)
+                throw new ArgumentException(
+                    "reconnectDelay < 0");
+            return reconnectDelay;
+        }
+
+        private static int CheckTrafficClass(int trafficClass)
+        {
+            if (trafficClass < 0 || trafficClass > 255)
+                throw new ArgumentException(
+                    "trafficClass < 0 || trafficClass > 255");
+            return trafficClass;
+        }
+
+        /// <summary>
+        /// The auto flush setting for this connection. If true, each call to send
+        /// must automatically call flush.
+        /// </summary>
+        public bool autoFlush;
+
+        /// <summary>
+        /// The output buffer size to use for this connection. Bytes, 0 means
+        /// unbuffered output. If using buffered output, you'll want to disable
+        /// auto flush and call flush manually only when needed.
+        /// </summary>
+        public int bufferSize;
+
+        /// <summary>
+        /// The tcp keep alive setting for this connection.
+        /// </summary>
+        public bool keepAlive;
+
+        /// <summary>
+        /// The tcp linger time setting for this connection. Time in seconds, -1
+        /// means disable.
+        /// </summary>
+        public int lingerTime;
+
+        /// <summary>
+        /// The tcp no delay setting for this connection. True disables nagle's
+        /// algorithm and causes all sends to be made asap.
+        /// </summary>
+        public bool noDelay;
+
+        /// <summary>
+        /// The reconnect delay for this connection. Time in milliseconds, 0 means
+        /// do not reconnect.
+        /// </summary>
+        public int reconnectDelay;
+
+        /// <summary>
+        /// The traffic class for this connection. 0-255, 0 means normal handling.
+        /// Also called type of service or dscp.
+        /// </summary>
+        public int trafficClass;
+
+        /// <summary>
+        /// Term on the uri which specifies the auto flush flag. The term string is
+        /// "TcpTransport.autoFlush". The value is "true" or "false". The default
+        /// is "false".
+        /// </summary>
+        public const String AUTO_FLUSH = "TcpTransport.autoFlush";
+
+        /// <summary>
+        /// Term on the uri which specifies the buffer size in bytes. The term
+        /// string is "TcpTransport.bufferSize". The value is an integer between
+        /// 0 and 65536. The default is 0.
+        /// </summary>
+        public const String BUFFER_SIZE = "TcpTransport.bufferSize";
+
+        /// <summary>
+        /// Term on the uri which specifies the keep alive flag. The term string is
+        /// "TcpTransport.keepAlive". The value is "true" or "false". The default is
+        /// "false".
+        /// </summary>
+        public const String KEEP_ALIVE = "TcpTransport.keepAlive";
+
+        /// <summary>
+        /// Term on the uri which specifies the linger time in seconds. The term
+        /// string is "TcpTransport.lingerTime". The value is an integer between -1
+        /// and 240. The default is 30. -1 means disable.
+        /// </summary>
+        public const String LINGER_TIME = "TcpTransport.lingerTime";
+
+        /// <summary>
+        /// Term on the uri which specifies the no delay flag. The term string is
+        /// "TcpTransport.noDelay". The value is "true" or "false". The default is
+        /// "true".
+        /// </summary>
+        public const String NO_DELAY = "TcpTransport.noDelay";
+
+        /// <summary>
+        /// Term on the uri which specifies the reconnect delay in milliseconds. The
+        /// term string is "TcpTransport.reconnectDelay". The value is an integer >=
+        /// 0. The default is 0.
+        /// </summary>
+        public const String RECONNECT_DELAY = "TcpTransport.reconnectDelay";
+
+        /// <summary>
+        /// Term on the uri which specifies the traffic class. The term string is
+        /// "TcpTransport.trafficClass". The value is an integer between 0 and 255.
+        /// The default is 0.
+        /// </summary>
+        public const String TRAFFIC_CLASS = "TcpTransport.trafficClass";
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TcpTransport.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TcpTransport.cs
new file mode 100644
index 0000000..824c4aa
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TcpTransport.cs
@@ -0,0 +1,322 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Runtime.CompilerServices;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Constants and methods related to tcp transport.
+    /// </summary>
+    abstract public class TcpTransport : Connection<SessionData>, TransportData
+    {
+        /// <summary>
+        /// Constructs the TcpTransport. Pulls common parameters off the uri.
+        /// </summary>
+        /// <param name="uri"></param>
+        /// <param name="resources"></param>
+        protected TcpTransport(URL uri, Resources resources)
+        {
+            options = new TcpOptions(uri, resources);
+        }
+
+        private readonly TcpOptions options;
+
+        protected override void Stop0()
+        {
+            try
+            {
+                Close(false);
+            }
+            catch
+            {
+                // ignore
+            }
+            base.Stop0();
+        }
+
+        protected Socket socket;
+
+        /// <summary>
+        /// Checks the connection socket for being open.
+        /// </summary>
+        /// <returns>the connection socket</returns>
+        protected Socket CheckSocket()
+        {
+            Socket s = socket;
+
+            if (s == null)
+                throw new IOException("socket closed");
+
+            return s;
+        }
+
+        public override void Close(bool reset)
+        {
+            Socket s = socket;
+            if (s != null)
+            {
+                try
+                {
+                    try
+                    {
+                        if (reset)
+                            s.LingerState = new LingerOption(false, 0);
+                        else
+                        {
+                            Flush();
+                            ShutdownOutput();
+                        }
+                    }
+                    finally
+                    {
+                        s.Close();
+                    }
+                }
+                catch
+                {
+                    // ignore.
+                }
+                finally
+                {
+                    stream = null;
+                    socket = null;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Sends some data to the remote end. The output data is buffered
+        /// until the buffer is full or the buffer is flushed.
+        /// </summary>
+        /// <param name="buf">the bytes to be sent</param>
+        /// Exception:
+        ///     throws Exception if there is a problem transmitting the
+        ///     data. Such a problem causes the current connection to be
+        ///     reset.
+        /// <seealso cref="Flush()"/>
+        /// <seealso cref="TcpOptions.autoFlush"/>
+        public void Send(byte[] buf)
+        {
+            Send(buf, 0, buf.Length);
+        }
+
+        /// <summary>
+        /// Sends some data to the remote end. The output data is buffered
+        /// until the buffer is full or the buffer is flushed.
+        /// </summary>
+        /// <param name="buf">the bytes to be sent</param>
+        /// <param name="off">the offset into buf of the first byte to send</param>
+        /// <param name="len">the number of bytes to send</param>
+        public void Send(byte[] buf, int off, int len)
+        {
+            try
+            {
+                Stream s = checkStream();
+                s.Write(buf, off, len);
+                if (options.autoFlush)
+                {
+                    s.Flush();
+                }
+            }
+            catch (Exception)
+            {
+                Close(true);
+                throw;
+            }
+        }
+
+        public void Flush()
+        {
+            try
+            {
+                checkStream().Flush();
+            }
+            catch (Exception)
+            {
+                Close(true);
+                throw;
+            }
+        }
+
+        protected Stream checkStream()
+        {
+            Stream ns = stream;
+            if (ns == null)
+                throw new IOException("net stream closed");
+            return ns;
+        }
+
+        private void FireData(FlexBuffer buf)
+        {
+            session.SessionData(null, buf);
+        }
+
+        protected Stream stream;
+
+        public override EndPoint LocalAddress()
+        {
+            return CheckSocket().LocalEndPoint;
+        }
+
+        public override EndPoint RemoteAddress()
+        {
+            return CheckSocket().RemoteEndPoint;
+        }
+
+        public void TransportData(Who recipient, FlexBuffer buf)
+        {
+            Send(buf.GetBuf(), buf.Index(), buf.Avail());
+        }
+
+        protected override void SetUpSocket()
+        {
+            Socket s = CheckSocket();
+
+            s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, options.keepAlive);
+            s.LingerState = new LingerOption(options.lingerTime >= 0, options.lingerTime >= 0 ? options.lingerTime : 0);
+            s.NoDelay = options.noDelay;
+            //s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TypeOfService, trafficClass);
+
+            stream = new NetworkStream(socket);
+            // TODO do something about buffering this stream.
+        }
+
+        public void ShutdownInput()
+        {
+            CheckSocket().Shutdown(SocketShutdown.Receive);
+        }
+
+        public void ShutdownOutput()
+        {
+            CheckSocket().Shutdown(SocketShutdown.Send);
+        }
+
+        abstract protected Socket NewSocket();
+
+        abstract protected bool IsServer();
+
+        public override object TransportQuery(object query)
+        {
+            if (query.Equals(TransportConsts.IS_SERVER))
+                return IsServer();
+
+            return base.TransportQuery(query);
+        }
+
+        [MethodImpl(MethodImplOptions.Synchronized)]
+        protected override bool OpenSocket(bool reconnect)
+        {
+            // if a one time connection from a server socket listener, just
+            // return the existing socket.
+            if (!reconnect && socket != null)
+                return true;
+
+            // if a one time connection from a server socket listener, and
+            // this is a reconnect, then bail.
+            if (reconnect && IsServer())
+                return false;
+
+            // if a reconnect but no retries allowed, then bail.
+            if (reconnect && options.reconnectDelay == 0)
+                return false;
+
+            // ok, we don't have an existing socket, and this is either the first
+            // connection attempt or a reconnect with delay > 0.
+
+            bool first = true;
+
+            while (IsStarted())
+            {
+                // if reconnect is false and first is true, this is our
+                // very first attempt to connect. otherwise, we are trying
+                // to reconnect a broken link or establish a link where we
+                // have already failed at least once.
+
+                if (reconnect || !first)
+                {
+                    if (options.reconnectDelay == 0)
+                        return false;
+
+                    System.Threading.Monitor.Wait(this, options.reconnectDelay);
+
+                    if (!IsStarted())
+                        break;
+                }
+
+                // try to open a socket.
+
+                try
+                {
+                    socket = NewSocket();
+                    return true;
+                }
+                catch (Exception e)
+                {
+                    if (first)
+                    {
+                        first = false;
+                        FireException("open", e);
+                    }
+                }
+            }
+
+            return false;
+        }
+
+        protected override void ReadSocket()
+        {
+            Stream ns = checkStream();
+            FlexBuffer buf = new FlexBuffer(new byte[8192]);
+
+            try
+            {
+                while (IsStarted())
+                {
+                    int n = ns.Read(buf.GetBuf(), 0, buf.Length());
+
+                    if (n <= 0)
+                        break;
+
+                    buf.SetLength(n);
+                    buf.SetIndex(0);
+                    FireData(buf);
+                }
+            }
+            catch (Exception e)
+            {
+                if (e.Message == null)
+                    throw;
+                if (e.Message.Contains("connection was aborted"))
+                    return;
+                if (e.Message.Contains("blocking operation"))
+                    return;
+                if (e.Message.Contains("socket closed"))
+                    return;
+                if (e.Message.Contains("read operation failed"))
+                    return;
+                throw;
+            }
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Timer.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Timer.cs
new file mode 100644
index 0000000..aa36a30
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Timer.cs
@@ -0,0 +1,240 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Timer enables making high precision interval tests. In the usual
+    /// scenario, some code is going to be bracketed by calls to
+    /// initialize a timer and later get the elapsed time since the init.
+    /// 
+    /// Trying to use the system clock (System.currentTimeMillis) is
+    /// problematic because periodic system time adjustments (by ntp,
+    /// windows time, etc.) will invalidate any interval testing based
+    /// on the system clock. Also, the system clock resolution is not
+    /// all that good (15 ms typically on a windows box).
+    /// 
+    /// Timer tmr = new Timer().init();
+    /// foo();
+    /// long ns = tmr.elapsedNanos();
+    /// System.out.println( "foo() took "+ns+" nanos" );
+    /// 
+    /// Timer keeps state, initialized by init(), and used by elapsedBlah()
+    /// and thus is thread safe as long as calls to init() are serialized.
+    /// 
+    /// For lower cost timing needs, Timer supports a set of static interfaces.
+    /// 
+    /// long t0 = Timer.getStartTime();
+    /// foo();
+    /// long ns = Timer.getNanosSince( t0 );
+    /// System.out.println( "foo() took "+ns+" nanos" );
+    /// 
+    /// Note: reading the high precision clock (which all these methods
+    /// ultimately do) takes about 1,487 nanoseconds on Windows XP Pro
+    /// running on a Dell Precision 370 workstation using jdk 1.5.0_04.
+    /// By comparison, a method call takes about 1.97 nanoseconds. Also,
+    /// on the above platform, the resolution of the timer is 1,396 ns.
+    /// Could be that the resolution is smaller, but we'll never know it
+    /// because just getting the value from the OS is the dominant factor.
+    /// </summary>
+
+    public class Timer
+    {
+        /// <summary>
+        /// Constructs the Timer. The timer is not started.
+        /// </summary>
+        public Timer()
+        {
+            // nothing to do.
+        }
+
+        /// <summary>
+        /// Initializes the startTime of this timer.
+        /// </summary>
+        /// <returns>returns this timer.</returns>
+        public Timer Init()
+        {
+            startTime = Nanos;
+            return this;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the elapsed time in nanos since the last init.</returns>
+        public long ElapsedNanos()
+        {
+            if ( startTime == long.MinValue)
+                throw new Exception( "Timer not started" );
+            return GetNanosSince( startTime );
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the elapsed time in micros since the last init.</returns>
+        public long ElapsedMicros()
+        {
+            return ElapsedNanos() / NANOS_PER_MICRO;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the elapsed time in millis since the last init.</returns>
+        public long ElapsedMillis()
+        {
+            return ElapsedNanos() / NANOS_PER_MILLI;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the elapsed time in seconds since the last init.</returns>
+        public double ElapsedSeconds()
+        {
+            return ElapsedNanos() / NANOS_PER_SECOND;
+        }
+
+        private long startTime = long.MinValue;
+
+        /// <summary>
+        /// Number of nanoseconds per microsecond.
+        /// </summary>
+        public const long NANOS_PER_MICRO = 1000;
+
+        /// <summary>
+        /// Number of nanoseconds per milliseconds.
+        /// </summary>
+        public const long NANOS_PER_MILLI = 1000000;
+        
+        public const long TICKS_PER_MILLI = 10000; // 100 ns per tick
+        
+        public const long NANOS_PER_TICK = 100; // 100 ns per tick
+
+        /// <summary>
+        /// Number of nanoseconds per second.
+        /// </summary>
+        public const double NANOS_PER_SECOND = 1000000000.0;
+
+        //////////////////////
+        // STATIC INTERFACE //
+        //////////////////////
+
+        public static long Nanos
+        {
+            get
+            {
+                return DateTime.Now.Ticks * NANOS_PER_TICK;
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the starting point of a timing test in millis.</returns>
+        public static long currentTimeMillis()
+        {
+            return DateTime.Now.Ticks / TICKS_PER_MILLI;
+        }
+        
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="startTime">a value returned by getStartTime.</param>
+        /// <returns>the number of nanos which have passed since startTime.</returns>
+        /// <see cref="Nanos"/>
+        public static long GetNanosSince( long startTime )
+        {
+            return Nanos - startTime;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="startTime">a value returned by getStartTime.</param>
+        /// <returns>the number of micros which have passed since startTime.</returns>
+        /// <see cref="Nanos"/>
+        public static long GetMicrosSince( long startTime )
+        {
+            return GetNanosSince( startTime ) / NANOS_PER_MICRO;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="startTime">a value returned by getStartTime.</param>
+        /// <returns>the number of millis which have passed since startTime.</returns>
+        /// <see cref="Nanos"/>
+        public static long GetMillisSince( long startTime )
+        {
+            return GetNanosSince( startTime ) / NANOS_PER_MILLI;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="startTime">a value returned by getStartTime.</param>
+        /// <returns>the number of seconds which have passed since startTime.</returns>
+        /// <see cref="Nanos"/>
+        public static double GetSecondsSince( long startTime )
+        {
+            return GetNanosSince( startTime ) / NANOS_PER_SECOND;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>returns the minimum value of many invocations of
+        /// getNanosSince( getStartTime() ).</returns>
+        public static long GetResolution()
+        {
+            long r = long.MaxValue;
+            for ( int i = 0; i < 100000; i++ )
+            {
+                r = Math.Min( r, GetNanosSince( Nanos ) );
+            }
+            return r;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="s">the number of seconds</param>
+        /// <returns>a nice text description of the amount of time</returns>
+        public static String HowLong( int s )
+        {
+            if ( s < 60 )
+                return s.ToString() + "s";
+
+            int m = s / 60;
+            if ( m < 60 )
+                return m.ToString() + "m" + ( s%60 ) + "s";
+
+            int h = m / 60;
+		    if (h < 24)
+                return h.ToString() + "h " + ( m%60 ) + "m";
+
+            int h_ = h / 24;
+            return h_.ToString() + "d " + ( h%24 ) + "h";
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TlsConnection.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TlsConnection.cs
new file mode 100644
index 0000000..476e725
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TlsConnection.cs
@@ -0,0 +1,201 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Net;
+using System.Net.Security;
+using System.Net.Sockets;
+using System.Security.Authentication;
+using System.Security.Cryptography.X509Certificates;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public class TlsConnection : TcpTransport
+    {
+        /// <summary>
+        /// Term on uri which specifies whether server certificate should be authenticated. 
+        /// </summary>
+        public const string AUTH_REQD = "TlsConnection.authReqd";
+
+        /// <summary>
+        /// Term on uri which specifies the certificate name of the server.
+        /// </summary>
+        public const string CERT_NAME = "TlsConnection.certName";
+
+        public TlsConnection(Socket socket, string uri, Resources resources)
+            : this(socket, new URL(uri), resources)
+        {
+            // nothing to do.
+        }
+
+        public TlsConnection(Socket socket, URL uri, Resources resources)
+            : base(uri, resources)
+        {
+            SetCertificateName(uri.GetTerm(CERT_NAME, "default"));
+            SetAuthReqd(uri.GetBooleanTerm(AUTH_REQD, true));
+
+            if (socket == null)
+            {
+                String host = uri.Host;
+                if (host == null)
+                    throw new ArgumentNullException("host == null");
+
+                int? port = uri.Port;
+                if (port == null)
+                    throw new ArgumentNullException("port == null");
+
+                if (port <= 0 || port >= 65536)
+                    throw new ArgumentOutOfRangeException("port <= 0 || port >= 65536");
+
+                this.socket = null;
+                this.host = host;
+                this.port = (int)port;
+            }
+            else
+            {
+                this.socket = socket;
+                this.host = null;
+                this.port = 0;
+            }
+        }
+
+        private readonly String host;
+
+        private readonly int port;
+
+        public override string ToString()
+        {
+            Socket s = socket;
+
+            if (s != null)
+                return String.Format("TlsConnection(up, {0}, {1})",
+                    s.LocalEndPoint, s.RemoteEndPoint);
+
+            return String.Format("TlsConnection(down, {0}, {1})", host, port);
+        }
+
+        protected override bool IsServer()
+        {
+            return host == null;
+        }
+
+        protected override Socket NewSocket()
+        {
+            IPAddress addr;
+
+            if (host != null)
+            {
+                IPAddress[] addrs = Dns.GetHostAddresses(host);
+                if (addrs == null || addrs.Length == 0)
+                    throw new ArgumentException("host is invalid");
+                addr = addrs[0];
+            }
+            else
+            {
+                addr = IPAddress.Any;
+            }
+
+            IPEndPoint ipe = new IPEndPoint(addr, port);
+            Socket socket = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+            socket.Connect(ipe);
+            return socket;
+        }
+
+        protected override void SetUpSocket()
+        {
+            base.SetUpSocket();
+
+            if (IsServer())
+            {
+                stream = new SslStream(stream, false);
+                try
+                {
+                    ((SslStream)stream).AuthenticateAsServer(GetServerCert(certName));
+                }
+                catch (AuthenticationException e)
+                {
+                    //Console.WriteLine(" Exception in authenticating certificate ");
+                    FireException("Certificate Authentication", e);
+                }
+            }
+            else
+            {
+                stream = new SslStream(stream, false,
+                     new RemoteCertificateValidationCallback(ValidateServerCertificate),
+                     null);
+
+                // The server name must match the name on the server certificate.
+
+                try
+                {
+                    ((SslStream)stream).AuthenticateAsClient(certName);
+                }
+                catch (AuthenticationException e)
+                {
+                    AuthenticationException e1 = new AuthenticationException(
+                        "Remote Certificate Mismatch Error. Problem in setting up"
+                        + " SSL Connection. Either disable server authentication by using"
+                        + " term TlsConnection.authReqd=false on uri or provide a valid"
+                        + " certificate name using term TlsConnection.certName=name on uri.", e);
+                    throw e1;
+                }
+            }
+        }
+
+        private void SetCertificateName(string certName)
+        {
+            this.certName = certName;
+        }
+
+        private string certName;
+
+        private void SetAuthReqd(bool authReqd)
+        {
+            this.authReqd = authReqd;
+        }
+
+        private bool authReqd;
+
+        public  bool ValidateServerCertificate(
+           object sender,
+           X509Certificate certificate,
+           X509Chain chain,
+           SslPolicyErrors sslPolicyErrors)
+        {
+            if (!authReqd)
+                return true;
+
+            if (sslPolicyErrors == SslPolicyErrors.None)
+                return true;
+
+            //Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
+
+            // Do not allow this client to communicate with unauthenticated servers.
+            return false;
+        }
+
+        private  X509Certificate GetServerCert(string certName)
+        {
+            X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
+            store.Open(OpenFlags.ReadOnly);
+            X509CertificateCollection coll = store.Certificates.Find(X509FindType.FindBySubjectName, certName, true);
+            return coll[0];
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Todo.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Todo.cs
new file mode 100644
index 0000000..11f7d32
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Todo.cs
@@ -0,0 +1,45 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// A TODO is used to perform a lightweight action
+    /// </summary>
+    public interface Todo
+    {
+        ///<summary>
+        /// Performs the action
+        /// </summary>
+        /// <param name="mgr">the todo manager where this todo was queued</param>
+        /// Exception:
+        ///     throws Exception
+        ///     
+        void Doit(TodoManager mgr);
+
+        /// <summary>
+        /// Reports an exception that occurred while running the todo.
+        /// </summary>
+        /// <param name="mgr">the todo manager where this todo was queued.</param>
+        /// <param name="e">the exception that the todo threw.</param>
+        void Exception(TodoManager mgr, Exception e);
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TodoDelegateImpl.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TodoDelegateImpl.cs
new file mode 100644
index 0000000..ece4769
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TodoDelegateImpl.cs
@@ -0,0 +1,75 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// This class defines delegate for the methods
+    /// defined in Todo Interface. 
+    /// </summary>
+    public class TodoDelegateImpl : Todo
+    {
+        private DoitDelegate doIt = null;
+        private ExceptionToDoDelegate exc = null;
+
+
+
+        public TodoDelegateImpl(DoitDelegate d, ExceptionToDoDelegate e)
+        {
+            this.doIt = d;
+            this.exc = e;
+        }
+
+        public virtual void Doit(TodoManager mgr)
+        {
+            if (doIt == null)
+                throw new Exception("Doit method not defined");
+
+            doIt(mgr);
+        }
+
+        public virtual void Exception(TodoManager mgr, Exception e)
+        {
+            if (exc == null)
+                throw new Exception("Exception method not defined");
+
+            exc(mgr, e);
+
+        }
+
+
+        /// <summary>
+        /// Performs the action
+        /// </summary>
+        /// <param name="mgr">the todo manager where this todo was queued</param>
+
+        public delegate void DoitDelegate(TodoManager mgr);
+
+        /// <summary>
+        /// Reports an exception that occurred while running the todo.
+        /// </summary>
+        /// <param name="mgr">the todo manager where this todo was queued.</param>
+        /// <param name="e">the exception that the todo threw.</param>
+        /// 
+        public delegate void ExceptionToDoDelegate(TodoManager mgr, Exception e);
+
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TodoManager.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TodoManager.cs
new file mode 100644
index 0000000..dbac3c2
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TodoManager.cs
@@ -0,0 +1,375 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Runtime.CompilerServices;
+using System.Threading;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// A standalone version of a processor for todo items
+    /// </summary>
+    public class TodoManager : AbstractStartable
+    {
+        /// <summary>
+        /// Constructs the TodoManager
+        /// </summary>
+        /// <param name="maxEntries">the maximum number of entries in the queue</param>
+        /// <param name="entryDelay">milliseconds to delay a caller who tries to
+        /// add a entry over the limit.</param>
+        /// <param name="minWorkers">the minimum number of workers to keep waiting</param>
+        /// <param name="maxWorkers">the maximum number of workers to allow.</param>
+        /// <param name="workerLinger">milliseconds a worker will wait for a Todo
+        /// before considering quitting.</param>
+        /// <param name="threshold">the per worker threshold for queue length. if
+        /// queue length exceeds this amount, a new worker is added if allowed.</param>
+        /// 
+        public TodoManager( int maxEntries, int entryDelay, int minWorkers,
+            int maxWorkers, int workerLinger, int threshold )
+        {
+            if ( maxEntries < 1 )
+                throw new ArgumentException( "maxEntries < 1" );
+
+            if ( minWorkers < 0 )
+                throw new ArgumentException( "minWorkers < 0" );
+
+            if ( maxWorkers < minWorkers )
+                throw new ArgumentException( "maxWorkers < minWorkers" );
+
+            if ( maxWorkers < 1 )
+                throw new ArgumentException( "maxWorkers < 1" );
+
+            if ( workerLinger < 1 )
+                throw new ArgumentException( "workerLinger < 1" );
+
+            this.maxEntries = maxEntries;
+            this.entryDelay = entryDelay;
+            this.minWorkers = minWorkers;
+            this.maxWorkers = maxWorkers;
+            this.workerLinger = workerLinger;
+            this.threshold = threshold;
+        }
+
+        private int maxEntries;
+    	
+	    private int entryDelay;
+    	
+	    private int minWorkers;
+    	
+	    private int maxWorkers;
+    	
+	    private int workerLinger;
+    	
+	    private int threshold;
+
+        protected override void Start0()
+        {
+            // nothing to do
+        }
+     
+        protected override void Stop0()
+        {
+            lock (this)
+            {
+                Monitor.PulseAll(this);
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="todo"></param>
+        /// Exception:
+        ///     throws ThreadInterruptedException
+        [ MethodImpl ( MethodImplOptions.Synchronized ) ]
+        public void Add( Todo todo )
+        {
+            CheckIsStarted();
+
+            int n = AddEntry( todo );
+            Monitor.Pulse( this );
+
+            ConsiderStartingAWorker( n ) ;
+
+            if ( n > maxEntries )
+                Thread.Sleep( entryDelay );
+        }
+
+        public void Run()
+        {
+            bool needAdjust = true;
+            try
+            {
+                Todo todo;
+                while ( ( todo = GetNextTodo() ) != null )
+                {
+                    try
+                    {
+                        todo.Doit( this );
+                    }
+                    catch ( Exception e )
+                    {
+                        todo.Exception( this, e );
+                    }
+                }
+                needAdjust = false;
+            }
+            finally
+            {
+                if ( needAdjust )
+                    workers.Adjust( -1 );
+            }
+        }
+
+        # region Workers
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>number of workers</returns>
+        public int NumWorkers()
+        {
+            return workers.Get();
+        }
+
+        [MethodImpl( MethodImplOptions.Synchronized )]
+        private void ConsiderStartingAWorker( int qlen )
+        {
+            int n = NumWorkers();
+
+            if ( n >= maxWorkers )
+                return;
+
+            // Start a new worker if there are none or if the 
+            // queue length per worker has exceeded the threshold
+            if ( n == 0 || ( (qlen + n-1) / n ) > threshold )
+                StartAWorker();
+        }
+
+        private void StartAWorker()
+        {
+            workers.Adjust( 1 );
+            Thread t = new Thread(Run);
+            t.Start();
+        }
+
+        private IntCounter workers = new IntCounter();
+
+        # endregion Workers
+
+        # region Queue
+
+        private Entry head;
+        private Entry tail;
+        private IntCounter entries = new IntCounter();
+
+        /// <summary>
+        /// Adds the todo to the tail of the queue.
+        /// </summary>
+        /// <param name="todo">the todo to add.</param>
+        /// <returns>the current queue length.</returns>
+        /// 
+        [MethodImpl( MethodImplOptions.Synchronized )]
+        private int AddEntry( Todo todo )
+        {
+            Entry e = new Entry();
+
+            e.todo = todo;
+
+            if ( tail != null )
+                tail.next = e;
+            else
+                head = e;   // first instance
+
+            tail = e;
+
+            return entries.Adjust( 1 );
+        }
+
+        /// <summary>
+        /// Remove an entry from the queue.
+        /// </summary>
+        /// <returns>a todo from the head of the queue, or 
+        /// null if empty</returns>
+        /// 
+        [MethodImpl( MethodImplOptions.Synchronized )]
+        private Todo RemoveEntry()
+        {
+            if ( head == null )
+                return null;
+
+            Entry e = head;
+            head = e.next;
+
+            if ( head == null )
+                tail = null;
+
+            entries.Adjust( -1 );
+
+            return e.todo;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>number of TODOs</returns>
+        public int NumEntries()
+        {
+            return entries.Get();
+        }
+
+        /// <summary>
+        /// An entry in the todo queue
+        /// </summary>
+        public class Entry
+        {
+            /// <summary>
+            /// The todo to be performed
+            /// </summary>
+            public Todo todo;
+
+            /// <summary>
+            /// The next todo in the queue
+            /// </summary>
+            public Entry next;
+        }
+
+        # endregion Queue
+
+        # region BLAH
+
+        [MethodImpl( MethodImplOptions.Synchronized )]
+        private Todo GetNextTodo()
+        {
+            Todo todo = null;
+            bool lingered = false;
+
+            while ( IsStarted() && ( todo = RemoveEntry() ) == null )
+            {
+                try
+                {
+                    if ( lingered && workers.Get() > minWorkers )
+                    {
+                        workers.Adjust( -1 );
+                        return null;
+                    }
+
+                    Monitor.Wait( this, workerLinger );
+
+                    // we lingered. we might have been woken because
+                    // we're stopping, or a todo might have been
+                    // queued.
+
+                    lingered = true;
+                }
+                catch ( ThreadInterruptedException )
+                {
+                    workers.Adjust( -1 );
+                    return null;
+                }
+            }
+            return todo;
+        }
+
+        # endregion BLAH
+
+        # region Static Stuff
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="todo"></param>
+        /// Exception: 
+        ///     throws Exception
+        ///     
+        public static void AddTodo( Todo todo )
+        {
+            try
+            {
+                GetTodoManager().Add(todo);
+            }
+            catch(Exception e)
+            {
+                todo.Exception(null,e);
+            }
+            
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the configured TodoManager. If there isn't one, it makes
+        /// one with one worker thread.</returns>
+        /// Exception: 
+        ///     if there is a problem creating the TodoManager
+        public static TodoManager GetTodoManager()
+        {
+            if ( todomanager == null )
+            {
+                lock ( lockObject  )
+                {
+                    if ( todomanager == null )
+                    {
+                        todomanager = new TodoManager( 50, 10, 0, 5, 5000, 0 );
+                        todomanager.Start();
+                    }
+                }
+            }
+            return todomanager;
+        }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="newTodoManager"></param>
+        /// <returns>the old todo manager</returns>
+        /// 
+        [MethodImpl( MethodImplOptions.Synchronized )]
+        public static TodoManager SetTodoManager( TodoManager newTodoManager )
+        {
+            TodoManager oldTodoManager = todomanager;
+            todomanager = newTodoManager;
+            return oldTodoManager;
+        }
+
+        /// <summary>
+        /// Shuts down the currently configured static todo manager if any.
+        /// </summary>
+        /// Exception:
+        ///     throws Exception
+        public static void ShutDown()
+        {
+            TodoManager oldTodoManager = SetTodoManager( null );
+            if ( oldTodoManager != null )
+                oldTodoManager.Stop();
+        }
+
+        private static TodoManager todomanager; 
+
+        /// <summary>
+        /// Since C# doesn't allow locking on an entire class, the substitute 
+        /// here is locking a static variable of the class.
+        /// </summary>
+        private static object lockObject = new Object() ;
+
+        # endregion Static Stuff
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Transport.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Transport.cs
new file mode 100644
index 0000000..e5b6cab
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Transport.cs
@@ -0,0 +1,89 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Out-of-band query, control, and notification interface for transports.
+    /// </summary>
+    public interface Transport<S> where S:Session 
+    {
+        /// <summary>
+        /// Gets a configuration or operational value from the transport. The
+        /// request is passed down the chain of transports until some transport
+        /// recognises the query, whereupon it returns the requested value.
+        /// </summary>
+        /// <param name="query">an object representing a query, which could be as
+        /// simple as a string, integer, or enum, or more complex such as
+        /// a class with instance variables for query terms.</param>
+        /// <returns>the requested value, or null if not defined.</returns>
+        /// Exception:
+        ///     throws Exception if the query is not recognised
+        ///     by any transport (which is to say, if the last transport in the transport
+        ///     chain does not recognise it, it should throw this exception). Typically
+        ///     this would be some sort of transport mechanism such as tcp, udp, jms,\
+        ///     http, sip, etc.
+        ///     
+        Object TransportQuery( Object query );
+
+        /// <summary>
+        /// Sets a configuration or operational value in the transport. The
+        /// request is passed down the chain of transports until some transport
+        /// recognises the control, whereupon it stores the specified value
+        /// and returns.
+        /// </summary>
+        /// <param name="control">an object representing a control, which could be as
+        /// simple as a string, integer, or enum, or more complex such as
+        /// a class with instance variables for control terms.</param>
+        /// <param name="value">the value to be set</param>
+        /// Exception:
+        ///     throws ArgumentException if the value is not the right
+        ///     type or if the value is inappropriate.
+        ///     
+        ///     throws Exception if the query is not recognised
+        ///     by any transport (which is to say, if the last transport in the transport
+        ///     chain does not recognise it, it should throw this exception). Typically
+        ///     this would be some sort of transport mechanism such as tcp, udp, jms,\
+        ///     http, sip, etc.
+        ///     
+        void TransportControl( Object control, Object value );
+
+        /// <summary>
+        /// Notifies the chain of transports of the specified event. Unlike query
+        /// and control operations above, events are always passed down to the
+        /// bottom to allow all transports to notice them (though it is possible
+        /// that an event might be delayed for a bit).
+        /// </summary>
+        /// <param name="eventObj">a class which represents the event, possibly with
+        /// parameters. The simplest event could be a string, integer, or enum,
+        /// but any class instance will do (as long as some transport in the
+        /// chain expects it).</param>
+        /// 
+        void TransportNotify( Object eventObj );
+
+
+        void SetSession(S session);
+
+        S GetSession();
+
+        
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TransportConsts.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TransportConsts.cs
new file mode 100644
index 0000000..a9539ce
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TransportConsts.cs
@@ -0,0 +1,112 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public class TransportConsts
+    {
+        #region Well-known queries, controls, and events.
+
+        /// <summary>
+        /// Name of value factory in resources. The value is "Transport.valueFactory".
+        /// The result of looking up this name should be a {@link ValueFactory} for
+        /// the service.
+        /// </summary>
+        public const String VALUE_FACTORY = "Transport.valueFactory";
+
+        /// <summary>
+        /// Transport control which starts the transport stack. The argument
+        /// should be null
+        /// </summary>
+        public const String START = "START";
+
+        /// <summary>
+        /// Transport control which starts the transport stack and waits
+        /// for it to come up. The argument should be the integer number of
+        /// milliseconds to wait before giving up.
+        /// </summary>
+        public const String START_AND_WAIT_UP = "START_AND_WAIT_UP";
+
+        /// <summary>
+        /// Transport query which waits for the transport stack to come up.
+        /// </summary>
+        public class WaitUp
+        {
+            public readonly int _maxDelay;
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <param name="maxDelay">delay in milliseconds</param>
+            public WaitUp( int maxDelay )
+            {
+                _maxDelay = maxDelay;
+            }
+        }
+
+        /// <summary>
+        /// Transport control which stops the transport stack. The argument
+        /// should be null, or a Boolean reset (true for instant close,
+        /// false for a nicer, gentler close).
+        /// </summary>
+        public const String STOP = "STOP";
+
+        /// <summary>
+        /// Transport control which stops the transport stack and waits
+        /// for it to go down. The argument should be the integer number of
+        /// milliseconds to wait before giving up.
+        /// </summary>
+        public const String STOP_AND_WAIT_DOWN = "STOP_AND_WAIT_DOWN";
+
+        /// <summary>
+        /// Transport control which resets the transport stack (e.g., closes the
+        /// socket) without stopping it. If it is set to reconnect, then it will do
+        /// that. Only meaningful for connection oriented transports. Others types
+        /// will ignore this.
+        /// </summary>
+        public const String RESET = "RESET";
+
+        /// <summary>
+        /// Transport query which asks is this a listener initiated connection or
+        /// is this a client initiated connection.
+        /// </summary>
+        public const String IS_SERVER = "IS_SERVER";
+
+        /// <summary>
+        /// Transport query which waits for the transport stack to go down.
+        /// </summary>
+        public class WaitDown
+        {
+            public readonly int _maxDelay;
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <param name="maxDelay">delay in milliseconds</param>
+            public WaitDown( int maxDelay )
+            {
+                _maxDelay = maxDelay;
+            }
+        }
+
+        #endregion
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TransportData.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TransportData.cs
new file mode 100644
index 0000000..a149709
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TransportData.cs
@@ -0,0 +1,27 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public interface TransportData : Transport<SessionData>
+    {
+
+        void TransportData(Who recipient, FlexBuffer buf);
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TransportPacket.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TransportPacket.cs
new file mode 100644
index 0000000..5b0e158
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/TransportPacket.cs
@@ -0,0 +1,28 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public interface TransportPacket : Transport<SessionPacket>
+    {
+
+        int HeaderSize();
+        void TransportPacket(Who recipient, FlexBuffer buf);
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/URL.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/URL.cs
new file mode 100644
index 0000000..79ec874
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/URL.cs
@@ -0,0 +1,1282 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    /// <summary>
+    /// Models a url of the form scheme://user:password@host:port/uri;parms?terms#fragment
+    /// </summary>
+    public class URL
+    {
+        #region MEMBER VARIABLES
+
+        private string scheme;
+        private string user;
+        private string password;
+        private string host;
+        private int? port;
+        private string uri;
+        private List<string> parms;
+        private Dictionary<string, object> terms;
+        private string fragment;
+
+        #endregion
+
+        #region CONSTRUCTORS
+
+        /// <summary>
+        /// Constructs a url from a string.
+        /// </summary>
+        /// <param name="urlString"></param>
+        public URL( string urlString )
+        {
+            Parse( urlString );
+        }
+
+        /// <summary>
+        /// Constructs a URL from another URL
+        /// </summary>
+        /// <param name="other"></param>
+        public URL( URL other )
+        {
+            scheme = other.scheme;
+            user = other.user;
+            password = other.password;
+            host = other.host;
+            port = other.port;
+            uri = other.uri;
+            parms = CopyList( other.parms );
+            terms = CopyTerms( other.terms );
+            fragment = other.fragment;
+        }
+
+        /// <summary>
+        /// Constructs an empty URL
+        /// </summary>
+        public URL()
+        {
+            // nothing to do.
+        }
+
+        #endregion
+
+        private void Parse( string s )
+        {
+            // s is scheme:[//[user[:password]@]host[:port]/]uri[;params][?terms][#fragment]
+
+            string[] x = StringUtil.LeftSplit( s, ':' );
+            if ( x == null )
+                throw new ArgumentNullException( "missing scheme" );
+
+            Scheme = Unescape( x[ 0 ] );
+            s = x[ 1 ];
+
+            // s is [//[user[:password]@]host[:port]/]uri[;params][?terms][#fragment]
+
+            x = StringUtil.LeftSplit( s, '#' );
+            if ( x!=null )
+            {
+                Fragment = Unescape( x[ 1 ] );
+                s = x[ 0 ];
+            }
+
+            // s is [//[user[:password]@]host[:port]/]uri[;params][?terms]
+
+            x = StringUtil.LeftSplit( s, '?' );
+            if ( x != null )
+            {
+                ParseTerms( x[ 1 ] );
+                s = x[ 0 ];
+            }
+
+            // s is [//[user[:password]@]host[:port]/]uri[;params]
+
+            x = StringUtil.LeftSplit( s, ';' );
+            if ( x != null )
+            {
+                ParseParams( x[ 1 ] );
+                s = x[ 0 ];
+            }
+
+            // s is [//[user[:password]@]host[:port]/]uri
+
+            if ( s.StartsWith( "//" ) )
+            {
+                s = s.Substring( 2 );
+                // s is [user[:password]@]host[:port]/uri
+                x = StringUtil.LeftSplit( s, '/' );
+                if ( x != null )
+                {
+                    // s is [user[:password]@]host[:port]/uri
+                    ParseHost( x[ 0 ] );
+                    s = x[ 1 ];
+                }
+                else
+                {
+                    // s is [user[:password]@]host[:port]
+                    ParseHost( s );
+                    s = "";
+                }
+            }
+            Uri = Unescape( s );
+        }
+
+        private void ParseHost( string s )
+        {
+            // s is [user[:password]@]host[:port]
+            string[] x = StringUtil.LeftSplit( s, '@' );
+            if ( x != null )
+            {
+                ParseUserPassword( x[ 0 ] );
+                ParseHostPort( x[ 1 ] );
+            }
+            else
+            {
+                ParseHostPort( s );
+            }
+        }
+
+        private void ParseUserPassword( string s )
+        {
+            // s is user[:password]
+            string[] x = StringUtil.LeftSplit( s, ':' );
+            if ( x != null )
+            {
+                User = Unescape( x[ 0 ] );
+                Password = Unescape( x[ 1 ] );
+            }
+            else
+            {
+                User = Unescape( s );
+            }
+        }
+
+        private void ParseHostPort( string s )
+        {
+            // s is host[:port]
+            string[] x = StringUtil.LeftSplit( s, ':' );
+            if ( x != null )
+            {
+                Host = Unescape( x[ 0 ] );
+                string p = Unescape(x[1]);
+                CheckNotInteger("port", p);
+                Port = int.Parse(p);
+            }
+            else
+            {
+                Host = Unescape( s );
+            }
+        }
+
+        private void ParseParams( string s )
+        {
+            // s is param[;param]*
+            if ( s.Length == 0 )
+                return;
+
+            EnsureParams();
+
+            string[] x;
+            while ( ( x = StringUtil.LeftSplit( s, ';' ) ) != null )
+            {
+                AddParam( Unescape( x[ 0 ] ) );
+                s = x[ 1 ];
+            }
+            AddParam( Unescape( s ) );
+        }
+
+        private void ParseTerms( string s )
+        {
+            // s is term[&term]*
+
+            if ( s.Length == 0 )
+                return;
+
+            string[] x;
+            while ( ( x = StringUtil.LeftSplit( s, '&' ) ) != null )
+            {
+                ParseTerm( x[ 0 ] );
+                s = x[ 1 ];
+            }
+            ParseTerm( s );
+        }
+
+        private void ParseTerm( string s )
+        {
+            // s is name[=value]
+
+            if ( s.Length == 0 )
+                return;
+
+            EnsureTerms();
+
+            string[] x = StringUtil.LeftSplit( s, '=' );
+            if ( x != null )
+                AddTerm( Unescape( x[ 0 ] ), Unescape( x[ 1 ] ) );
+            else
+                AddTerm( Unescape( s ), "" );
+        }
+
+        #region SCHEME
+        
+        /// <summary>
+        /// Gets and Sets the scheme. 
+        /// Return the scheme which may be null but not blank.
+        /// </summary>
+        public string Scheme
+        {
+            get 
+            {
+                return scheme;
+            }
+            set
+            {
+                CheckNotBlank( "scheme", value );
+                scheme = value;
+            }
+        }
+
+        /// <summary>
+        /// Tests the scheme for a match. The schemes are case-insensitive.
+        /// </summary>
+        /// <param name="testScheme">a scheme to test against.</param>
+        /// <returns>true if the schemes match, false otherwise.</returns>
+        public bool IsScheme( string testScheme )
+        {
+            return testScheme.Equals( scheme, StringComparison.CurrentCultureIgnoreCase );
+        }
+
+        #endregion
+
+        #region USER
+
+        public string User
+        {
+            get
+            {
+                return user;
+            }
+            set
+            {
+                CheckNotBlank( "user", value );
+                user = value;
+            }
+        }
+
+        #endregion
+
+        #region PASSWORD
+
+        public string Password
+        {
+            get
+            {
+                return password;
+            }
+            set
+            {
+                //CheckNotBlank( "password", value );
+                password = value;
+            }
+        }
+
+        #endregion
+
+        #region HOST
+
+        public string Host
+        {
+            get
+            {
+                return host;
+            }
+            set
+            {
+                CheckNotBlank( "host", value );
+                host = value;
+            }
+        }
+
+        #endregion
+
+        #region PORT
+
+        public int? Port
+        {
+            get
+            {
+                return port;
+            }
+            set
+            {
+                if ( value != null && value < 0 || value > 65535 )
+                    throw new ArgumentOutOfRangeException( "port < 0 || port > 65535 " );
+                port = value;
+            }
+        }
+
+        public bool HasPort()
+        {
+            return port != null;
+        }
+
+        #endregion
+
+        #region URI
+
+        public string Uri
+        {
+            get
+            {
+                return uri;
+            }
+            set
+            {
+                uri = value;
+            }
+        }
+
+        #endregion
+
+        #region PARAMS
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>true if there is atleast one param</returns>
+        public bool HasParams()
+        {
+            return ( ( parms!=null ) && ( parms.Count > 0 ) );
+        }
+
+        /// <summary>
+        /// Fetches the first param found which starts with the given prefix. The
+        /// search order is not specified, and the params are not maintained in any
+        /// specific order.
+        /// </summary>
+        /// <param name="prefix">the prefix of the param to fetch (e.g., "transport=").</param>
+        /// <returns>the param which starts with the specified prefix.</returns>
+        /// 
+        public string GetParam( string prefix )
+        {
+            CheckNotNull( prefix, "prefix == null");
+
+            if (parms == null)
+                return null;
+
+            foreach (string p in parms)
+                if (p.StartsWith(prefix))
+                    return p;
+
+            return null;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>an iterator over all the params. The params are strings, generally
+        /// of the form "transport=tcp". But they can be anything you like, really.
+        /// The iterator might be empty.</returns>
+        /// 
+        public string[] GetParams()
+        {
+            if ( parms == null )
+                return new string[] {};
+
+            return parms.ToArray();
+        }
+
+        /// <summary>
+        /// Adds a param to the set of params for this url. Only the set of unique
+        /// params is maintained. Duplicate param values are suppressed.
+        /// </summary>
+        /// <param name="param">a param (e.g., "transport=tcp" or "01831864574898475").</param>
+        /// 
+        public void AddParam( string param )
+        {
+            CheckNotNull(param, "param == null");
+            EnsureParams();
+            parms.Add( param );
+        }
+
+        /// <summary>
+        /// Removes the first param found which starts with the given prefix. The
+        /// search order is not specified, and the params are not maintained in any
+        /// specific order.
+        /// 
+        /// </summary>
+        /// <param name="prefix">the prefix of the param to remove (e.g., "transport=").</param>
+        /// <returns>the param removed.</returns>
+        /// 
+        public string RemoveParam( string prefix )
+        {
+            CheckNotNull(prefix, "prefix == null");
+
+            if ( parms == null )
+                return null;
+
+            foreach ( string p in GetParams() )
+            {
+                if ( p.StartsWith( prefix ) )
+                {
+                    parms.Remove( p );
+                    return p;
+                }
+            }
+            return null;
+        }
+
+        /// <summary>
+        /// Clear all params
+        /// </summary>
+        public void ClearParams()
+        {
+            if ( parms != null )
+                parms.Clear();
+        }
+
+        public void EnsureParams()
+        {
+            if ( parms == null )
+                parms = new List<string>();
+        }
+
+        #endregion
+
+        #region QUERY TERMS
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>true if there is at least one query term. Query terms
+        /// are of the form name=value</returns>
+        public bool HasTerms()
+        {
+            return terms != null && terms.Count > 0;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns>true if there is at least one query term with the specified
+        /// name</returns>
+        public bool HasTerm( string name )
+        {
+            CheckName(name);
+
+            if ( terms == null )
+                return false;
+
+            return terms.ContainsKey( name );
+        }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="value"></param>
+        /// <returns>if there is a query term with the specified value.</returns>
+        public bool HasTerm( string name, string value )
+        {
+            CheckName(name);
+
+            if ( terms == null )
+                return false;
+
+            if (value == null)
+                return HasTerm(name);
+
+            object obj;
+            if (!terms.TryGetValue(name, out obj))
+                return false;
+
+            if ( obj is List<string> )
+                return ( ( List<string> ) obj ).Contains( value );
+
+            return obj.Equals( value );
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="value"></param>
+        /// <returns>if there is a query term with the specified value.</returns>
+        public bool HasTerm( string name, int? value )
+        {
+            return HasTerm( name, ToString(value) );
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="value"></param>
+        /// <returns>if there is a query term with the specified value.</returns>
+        public bool HasTerm(string name, double? value)
+        {
+            return HasTerm(name, ToString(value));
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="value"></param>
+        /// <returns>if there is a query term with the specified value.</returns>
+        public bool HasTerm(string name, bool? value)
+        {
+            return HasTerm(name, ToString(value));
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns>true if the query term specified by name has multiple values.</returns>
+        public bool HasMultipleValues(string name)
+        {
+            CheckName(name);
+
+            if ( terms == null )
+                return false;
+
+            object obj;
+            if (!terms.TryGetValue(name, out obj))
+                return false;
+
+            if ( obj is List<string> )
+                return ( ( List<string> ) obj ).Count > 1;
+
+            return false;
+        }
+
+        /// <summary>
+        /// Gets the value of the specified query term.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns>the value of the specified term, or null if not found.</returns>
+        public string GetTerm(string name)
+        {
+            CheckName(name);
+
+            if (terms == null)
+                return null;
+
+            object obj;
+            if (!terms.TryGetValue(name, out obj))
+                return null;
+
+            if (obj is List<string>)
+            {
+                IEnumerator<string> i = ((List<string>)obj).GetEnumerator();
+
+                if (!i.MoveNext())
+                    return null;
+
+                string v = i.Current;
+
+                if (i.MoveNext())
+                    throw new Exception(string.Format("term {0} has multiple values", name));
+
+                return v;
+            }
+
+            return (string)obj;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="defaultValue"></param>
+        /// <returns>the value of the specified term, or defaultValue if not found.</returns>
+        public string GetTerm( string name, string defaultValue )
+        {
+            string value = GetTerm( name );
+            if ( value == null )
+                return defaultValue;
+            return value;
+        }
+
+        /// <summary>
+        /// Gets the integer value of the specified query term.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns>the integer value, or null if not found.</returns>
+        /// 
+        public int? GetIntegerTerm(string name)
+        {
+            string s = GetTerm(name);
+            if (s == null)
+                return null;
+            return int.Parse(s);
+        }
+
+        /// <summary>
+        /// Gets the integer value of the specified query term.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="defaultValue">the value to return if the term is not found.</param>
+        /// <returns>the integer value, or defaultValue if not found.</returns>
+        /// <see cref="GetTerm( string )"/>
+        /// 
+        public int GetIntegerTerm(string name, int defaultValue)
+        {
+            int? v = GetIntegerTerm(name);
+            if (v == null)
+                return defaultValue;
+            return v.Value;
+        }
+
+        /// <summary>
+        /// Gets the double value of the specified query term.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns>the double value, or null if not found.</returns>
+        /// 
+        public double? GetDoubleTerm(string name)
+        {
+            string s = GetTerm(name);
+            if (s == null)
+                return null;
+            return double.Parse(s);
+        }
+
+        /// <summary>
+        /// Gets the double value of the specified query term.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="defaultValue">the value to return if the term is not found.</param>
+        /// <returns>the double value, or defaultValue if not found.</returns>
+        /// <see cref="GetTerm( string )"/>
+        /// 
+        public double GetDoubleTerm(string name, double defaultValue)
+        {
+            double? v = GetDoubleTerm(name);
+            if (v == null)
+                return defaultValue;
+            return v.Value;
+        }
+
+        /// <summary>
+        /// Gets the boolean value of the specified query term.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns>the boolean value, or null if not found.</returns>
+        /// <see cref="GetTerm(string)"/>
+        public bool? GetBooleanTerm(string name)
+        {
+            string s = GetTerm(name);
+            if (s == null)
+                return null;
+            return s.Equals("true", StringComparison.CurrentCultureIgnoreCase);
+        }
+
+        /// <summary>
+        /// Gets the bool value of the specified query term.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="defaultValue">the value to return if the term is not found.</param>
+        /// <returns>the bool value, or defaultValue if not found.</returns>
+        /// <see cref="GetTerm( string )"/>
+        /// 
+        public bool GetBooleanTerm(string name, bool defaultValue)
+        {
+            bool? v = GetBooleanTerm(name);
+            if (v == null)
+                return defaultValue;
+            return v.Value;
+        }
+
+        /// <summary>
+        /// Gets the values of the specified query term.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns>an iterator over the string values of the query term. May be empty.</returns>
+        public string[] GetTerms( string name )
+        {
+            CheckName(name);
+
+            if ( terms == null )
+                return new string[] {};
+
+            object obj;
+            if (!terms.TryGetValue(name, out obj))
+                return new string[] { };
+
+            if ( obj is List<string> )
+                return ( ( List<string> ) obj ).ToArray();
+
+            return new string[] { (string)obj };
+        }
+
+        /// <summary>
+        /// Gets the names of the query terms.
+        /// </summary>
+        /// <returns>an iterator over the string names.</returns>
+        public string[] GetTermNames()
+        {
+            if ( terms == null )
+                return new string[] { };
+
+            return ToArray(terms.Keys);
+        }
+
+        /// <summary>
+        /// Adds the specified query term to the set of query terms. Duplicate
+        /// name/value pairs are suppressed.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="value"></param>
+        public void AddTerm(string name, string value)
+        {
+            CheckName(name);
+
+            if (value == null)
+                return;
+
+            EnsureTerms();
+
+            object obj;
+
+            if (!terms.TryGetValue(name, out obj))
+            {
+                terms.Add( name, value );
+                return;
+            }
+
+            if ( obj is List<string> )
+            {
+                List<string> values = (List<string>)obj;
+                if (!values.Contains(value))
+                    values.Add(value);
+                return;
+            }
+
+            // obj is not a list but we need one, so replace obj in terms with a
+            // list, then add value to the list.
+
+            List<string> nvalues = new List<string>();
+            terms[name] = nvalues;
+            nvalues.Add( ( string ) obj );
+
+            nvalues.Add( value );
+        }
+
+        /// <summary>
+        /// Adds the specified query term to the set of query terms. Duplicate
+        /// name/value pairs are suppressed.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="value"></param>
+        public void AddTerm( string name, int? value )
+        {
+            AddTerm(name, ToString(value));
+        }
+
+        /// <summary>
+        /// Adds the specified query term to the set of query terms. Duplicate
+        /// name/value pairs are suppressed.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="value"></param>
+        public void AddTerm(string name, double? value)
+        {
+            AddTerm(name, ToString(value));
+        }
+
+        /// <summary>
+        /// Adds the specified query term to the set of query terms. Duplicate
+        /// name/value pairs are suppressed.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="value"></param>
+        public void AddTerm(string name, bool? value)
+        {
+            AddTerm(name, ToString(value));
+        }
+
+        /// <summary>
+        /// Removes all the values associated with the specified query term.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns>true if something was removed, false otherwise.</returns>
+        public bool RemoveTerm( string name )
+        {
+            CheckName(name);
+
+            if (terms == null)
+                return false;
+
+            return terms.Remove(name);
+        }
+
+        /// <summary>
+        /// Removes the specified name/value pair from the set of query terms.
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="value"></param>
+        /// <returns>true if the name/value pair was found and removed.</returns>
+        /// 
+        public bool RemoveTerm( string name, string value )
+        {
+            CheckName(name);
+
+            if ( terms == null )
+                return false;
+
+            if (value == null)
+                return RemoveTerm(name);
+
+            object obj;
+            if (!terms.TryGetValue(name, out obj))
+                return false;
+
+            if ( obj is List<string> )
+            {
+                List<string> x = ( List<string> ) obj;
+                bool ok = x.Remove( value );
+                if (x.Count == 0)
+                    terms.Remove(name);
+                return ok;
+            }
+
+            if (obj.Equals(value))
+            {
+                terms.Remove(name);
+                return true;
+            }
+
+            return false;
+        }
+
+        public Boolean RemoveTerm(string name, int? value)
+        {
+            return RemoveTerm(name, ToString(value));
+        }
+
+        public Boolean RemoveTerm(string name, double? value)
+        {
+            return RemoveTerm(name, ToString(value));
+        }
+
+        public Boolean RemoveTerm(string name, bool? value)
+        {
+            return RemoveTerm(name, ToString(value));
+        }
+
+        /// <summary>
+        /// Removes all query terms
+        /// </summary>
+        public void ClearTerms()
+        {
+            if ( terms != null )
+                terms.Clear();
+        }
+
+        private void EnsureTerms()
+        {
+            if ( terms == null )
+                terms = new Dictionary<string, object>();
+        }
+
+
+        #endregion
+
+        #region FRAGMENT
+
+        public string Fragment
+        {
+            get
+            {
+                return fragment;
+            }
+            set
+            {
+                CheckNotBlank( "fragment", value );
+                fragment = value;
+            }
+        }
+
+        #endregion
+
+        #region UTIL
+
+        public override string ToString()
+        {
+            StringBuilder sb = new StringBuilder();
+
+            Escape( sb, scheme );
+            sb.Append( ':' );
+
+            if ( host != null )
+            {
+                sb.Append( "//" );
+                if ( user != null )
+                {
+                    Escape( sb, user );
+                    if ( password != null )
+                    {
+                        sb.Append( ':' );
+                        Escape( sb, password );
+                    }
+                    sb.Append( '@' );
+                }
+                Escape( sb, host );
+                if ( port != null )
+                {
+                    sb.Append( ':' );
+                    sb.Append( port );
+                }
+                sb.Append( '/' );
+            }
+
+            if ( uri != null )
+                Escape( sb, uri );
+
+            if ( HasParams() )
+                ParamsToString( sb );
+
+            if ( HasTerms() )
+                TermsToString( sb );
+
+            if ( fragment != null )
+            {
+                sb.Append( '#' );
+                Escape( sb, fragment );
+            }
+
+            return sb.ToString();
+        }
+
+        public override int GetHashCode()
+        {
+            int code = 23547853;
+		    code ^= hc( scheme );
+		    code ^= hc( user );
+		    code ^= hc( password );
+		    code ^= hc( host );
+		    code ^= hc( port );
+		    code ^= hc( uri );
+		    code ^= hc( parms );
+		    code ^= hc( terms );
+		    code ^= hc( fragment );
+		    return code;
+        }
+
+        private int hc( Dictionary<string,object> m )
+	    {
+		    return m != null ? m.GetHashCode() : 793;
+	    }
+
+	    private int hc( List<string> s )
+	    {
+		    return s != null ? s.GetHashCode() : 161;
+	    }
+
+	    private int hc( int? i )
+	    {
+		    return i != null ? i.GetHashCode() : 59;
+	    }
+
+	    private int hc( string s )
+	    {
+		    return s != null ? s.GetHashCode() : 91;
+	    }
+
+
+        public override bool Equals( object obj )
+        {
+            if ( obj == this )
+                return true;
+
+            if (obj == null)
+                return false;
+
+            if (obj.GetType() != typeof(URL))
+                return false;
+
+            URL other = ( URL ) obj;
+
+            if ( !StringUtil.EqIgnoreCase(scheme, other.scheme) )
+                return false;
+
+            if (!StringUtil.Eq(user, other.user))
+                return false;
+
+            if (!StringUtil.Eq(password, other.password))
+                return false;
+
+            if (!StringUtil.Eq(host, other.host))
+                return false;
+
+            if (!Eq(port, other.port))
+                return false;
+
+            if (!StringUtil.Eq(uri, other.uri))
+                return false;
+
+            if ( !Eq( parms, other.parms ) )
+                return false;
+
+            if ( !Eq( terms, other.terms ) )
+                return false;
+
+            if (!StringUtil.Eq(fragment, other.fragment))
+                return false;
+
+            return true;
+        }
+
+        private static bool Eq(object a, object b)
+        {
+            if (ReferenceEquals(a, b))
+                return true;
+
+            if (a == null || b == null)
+                return false;
+
+            return a.Equals(b);
+        }
+
+        private void ParamsToString( StringBuilder sb )
+        {
+            foreach (string param in GetParams())
+            {
+                sb.Append( ';' );
+                Escape( sb, param );
+            }
+        }
+
+        private void TermsToString( StringBuilder sb )
+        {
+            char sep = '?';
+            foreach (string name in GetTermNames())
+            {
+                foreach (string value in GetTerms(name))
+                {
+                    sb.Append(sep);
+                    Escape(sb, name);
+                    sb.Append('=');
+                    Escape(sb, value);
+                    sep = '&';
+                }
+            }
+        }
+
+        /// <summary>
+        /// Dumps URL contents for easy viewing
+        /// </summary>
+        public void Dump()
+	    {
+		    Console.WriteLine( "---------------" );
+		    Console.WriteLine( "scheme = "+scheme );
+		    Console.WriteLine( "user = "+user );
+		    Console.WriteLine( "password = "+password );
+		    Console.WriteLine( "host = "+host );
+		    Console.WriteLine( "port = "+port );
+		    Console.WriteLine( "uri = "+uri );
+		    Console.WriteLine( "params = "+parms );
+		    Console.WriteLine( "terms = "+terms );
+		    Console.WriteLine( "fragment = "+fragment );
+        }
+
+        private static void Escape( StringBuilder sb, string s )
+        {
+            if (s == null)
+            {
+                sb.Append("null");
+                return;
+            }
+
+            CharIterator i = new CharIterator( s );
+            while ( i.MoveNext() )
+            {
+                char c = i.Current;
+                if ( IsEscaped( c ) )
+                {
+                    sb.Append( '%' );
+                    sb.Append( StringUtil.ToHex( ( c >> 4 )& 15 ) );
+                    sb.Append( StringUtil.ToHex( c & 15 ) );
+                }
+                else if ( c == ' ' )
+                {
+                    sb.Append( '+' );
+                }
+                else
+                {
+                    sb.Append( c );
+                }
+            }
+        }
+
+        private static bool IsEscaped( char c )
+        {
+            if ( c >= '0' && c <= '9' )
+                return false;
+            if ( c >= 'A' && c <= 'Z' )
+                return false;
+            if ( c >= 'a' && c <= 'z' )
+                return false;
+            if ( c == ' ' )
+                return false;
+            if ( c == ',' )
+                return false;
+            if ( c == '.' )
+                return false;
+            if ( c == '/' )
+                return false;
+            if ( c == '!' )
+                return false;
+            if ( c == '$' )
+                return false;
+            if ( c == '^' )
+                return false;
+            if ( c == '*' )
+                return false;
+            if ( c == '(' )
+                return false;
+            if ( c == ')' )
+                return false;
+            if ( c == '_' )
+                return false;
+            if ( c == '-' )
+                return false;
+            if ( c == '{' )
+                return false;
+            if ( c == '}' )
+                return false;
+            if ( c == '[' )
+                return false;
+            if ( c == ']' )
+                return false;
+            if ( c == '|' )
+                return false;
+            if ( c == '\\' )
+                return false;
+            return true;
+        }
+
+        private static string Unescape( string s )
+        {
+            StringBuilder sb = new StringBuilder();
+            CharIterator i = new CharIterator( s );
+            while ( i.MoveNext() )
+            {
+                char c = i.Current;
+                if ( c == '%')
+                {
+                    i.MoveNext();
+                    char c1 = i.Current;
+                    i.MoveNext();
+                    char c2 = i.Current;
+                    sb.Append( ( char ) ( ( StringUtil.FromHex( c1 ) << 4 ) | StringUtil.FromHex( c2 ) ) );
+                }
+                else if ( c == '+' )
+                {
+                    sb.Append( ' ' );
+                }
+                else
+                {
+                    sb.Append( c );
+                }
+            }
+            return sb.ToString();
+        }
+
+        private static void CheckName(string name)
+        {
+            if (name == null || name.Length == 0)
+                throw new ArgumentException("name null or empty");
+        }
+
+        private static string ToString(object value)
+        {
+            return value != null ? value.ToString() : null;
+        }
+
+        private static string[] ToArray(Dictionary<string, object>.KeyCollection keyCollection)
+        {
+            string[] a = new string[keyCollection.Count];
+            keyCollection.CopyTo(a, 0);
+            return a;
+        }
+
+        private void CheckNotNull(string value, string msg)
+        {
+            if (value == null)
+                throw new NullReferenceException(msg);
+        }
+
+        private static void CheckNotBlank( string name, string value )
+        {
+            if ( value != null && value.Length == 0 )
+                throw new ArgumentException( name + " is blank" );
+        }
+
+        private static void CheckNotInteger(string name, string value)
+        {
+            CheckNotBlank(name, value);
+            try
+            {
+                int.Parse(value);
+            }
+            catch (FormatException)
+            {
+                throw new ArgumentException(name + " is not integer");
+            }
+        }
+
+        private static List<string> CopyList( List<string> parms )
+        {
+            // just goes one level deep.
+
+            if (parms == null)
+                return null;
+
+            return new List<string>(parms);
+        }
+
+        private static Dictionary<string, object> CopyTerms( Dictionary<string, object> terms )
+        {
+            if ( terms == null )
+                return null;
+
+            Dictionary<string, object> nterms = new Dictionary<string, object>();
+            foreach (KeyValuePair<string, object> me in terms)
+            {
+                string name = me.Key;
+                object value = me.Value;
+                if (value is List<string>)
+                    value = CopyList((List<string>) value);
+                nterms.Add(name, value);
+            }
+            return nterms;
+        }
+
+        #endregion
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/URLSerializer.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/URLSerializer.cs
new file mode 100644
index 0000000..e3d1d34
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/URLSerializer.cs
@@ -0,0 +1,61 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    public class URLSerializer : ImportExportHelper
+    {
+        private const String FIELD_NAME = "urlStr";
+
+        public static void Init( XType type, Class2TypeMap class2type )
+        {
+            Field field = type.GetField( FIELD_NAME );
+            class2type.Add( typeof( URL ), type );
+            type.SetComponentType( typeof( URL ) );
+            type.SetImportExportHelper( new URLSerializer( type, field ) );
+            type.PutValidator( field, Validator_string.Get( 0 ) );
+            type.Lock();
+        }
+
+        public URLSerializer( XType type, Field field )
+        {
+            this.type = type;
+            this.field = field;
+        }
+
+        private readonly XType type;
+        private readonly Field field;
+
+        public override Object ImportValue( StructValue sv )
+	    {
+		    return new URL( (String) sv.Get( field ) );
+	    }
+
+        public override StructValue ExportValue(ValueFactory vf, Object value)
+	    {
+            StructValue sv = new StructValue(type, vf);
+		    sv.Add( field, ((URL) value).ToString() );
+		    return sv;
+	    }
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Who.cs b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Who.cs
new file mode 100644
index 0000000..f01b555
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Org.Apache.Etch.Bindings.Csharp/Util/Who.cs
@@ -0,0 +1,27 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{   
+    /// <summary>Abstraction of sender used by the various sources of data, packets, or messages.</summary>
+    public interface Who
+    {
+        //nothing defined
+    }
+}
diff --git a/binding-csharp/runtime/src/main/csharp/Properties/AssemblyInfo.cs b/binding-csharp/runtime/src/main/csharp/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..fc002d3
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Properties/AssemblyInfo.cs
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Etch")]
+[assembly: AssemblyDescription("Apache Etch C# Binding Runtime DLL")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Apache Etch (incubating)")]
+[assembly: AssemblyCopyright("Copyright © Apache Software Foundation 2009")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("dfb6c903-751f-4473-8400-d50c1f0968f8")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.1.0")]
+[assembly: AssemblyFileVersion("1.1.0")]
diff --git a/binding-csharp/runtime/src/main/csharp/Properties/AssemblyInfo.cs.tmpl b/binding-csharp/runtime/src/main/csharp/Properties/AssemblyInfo.cs.tmpl
new file mode 100644
index 0000000..0bfeffc
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/Properties/AssemblyInfo.cs.tmpl
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Etch")]
+[assembly: AssemblyDescription("Apache Etch C# Binding Runtime DLL")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Apache Etch (incubating)")]
+[assembly: AssemblyCopyright("Copyright © Apache Software Foundation 2009")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("dfb6c903-751f-4473-8400-d50c1f0968f8")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("@EtchVersion@")]
+[assembly: AssemblyFileVersion("@EtchVersion@")]
diff --git a/binding-csharp/runtime/src/main/csharp/etch.snk b/binding-csharp/runtime/src/main/csharp/etch.snk
new file mode 100644
index 0000000..e9e2800
--- /dev/null
+++ b/binding-csharp/runtime/src/main/csharp/etch.snk
Binary files differ
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestComboValidator.cs b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestComboValidator.cs
new file mode 100644
index 0000000..0b149e5
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestComboValidator.cs
@@ -0,0 +1,154 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+    [TestFixture]
+    public class TestComboValidator
+    {
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestComboValidator" );
+        }
+
+        [Test]
+        public void Test()
+        {
+            Test(0, "(int[0] OR boolean[0])", true, 123456789012L);
+            Test(0, "(int[0] OR boolean[0])", false, -123456789012L);
+		//    Test( 0, "(int[0] OR boolean[0])", Etch.Transport.Fmt.TypeCode.INT1, 0, (long) 3 );
+		    Test( 0, "(int[0] OR boolean[0])",  1, (float) 4 );
+		    Test( 0, "(int[0] OR boolean[0])",  -1, (double) 5 );
+		    Test( 0, "(int[0] OR boolean[0])",  127, "abc" );
+		    Test( 0, "(int[0] OR boolean[0])",  -128, new Object() );
+		    Test( 0, "(int[0] OR boolean[0])",  32767, new int[] {} );
+		    Test( 0, "(int[0] OR boolean[0])",  -32768, new Boolean[] {} );
+		    Test( 0, "(int[0] OR boolean[0])",  1000000000, new DateTime() );
+            Test( 0, "(int[0] OR boolean[0])",  -1000000000, typeof( int ) );
+		    Test( 1, "(int[1] OR boolean[1])",  new int[] {}, 0 );
+		    Test( 1, "(int[1] OR boolean[1])", new Boolean[] {}, true );
+        }
+
+        private void Test( int n, String s, Object good, Object bad )
+        {
+            Validator_int v1 = Validator_int.Get( n );
+            Validator_boolean v2 = Validator_boolean.Get( n );
+            ComboValidator v = new ComboValidator( v1, v2 );
+
+            Assert.AreEqual( s, v.ToString() );
+            Assert.IsTrue( v.Validate( good ) );
+            Assert.IsFalse( v.Validate( bad ) );
+            
+            if ( n > 0 )
+            {
+                v.ElementValidator();
+            }
+        }
+
+        [Test]
+	    public void Test2()  
+	    {
+		    Validator v1 = Validator_int.Get( 1 );
+		    Validator v2 = Validator_boolean.Get( 0 );
+		    Validator v = new ComboValidator( v1, v2 );
+
+		    Assert.IsTrue( v.Validate( new int[] {} ) );
+		    Assert.IsTrue( v.Validate( true ) );
+		    Assert.IsTrue( v.Validate( false ) );
+		    Assert.IsFalse( v.Validate( 0 ) );
+    		
+		    v = v.ElementValidator();
+
+		    Assert.IsFalse( v.Validate( new int[] {} ) );
+		    Assert.IsFalse( v.Validate( true ) );
+		    Assert.IsFalse( v.Validate( false ) );
+		    Assert.IsTrue( v.Validate( 0 ) );
+	    }
+    	
+	    [Test]
+	    public void Test3()  
+	    {
+		    Validator v1 = Validator_boolean.Get( 0 );
+		    Validator v2 = Validator_int.Get( 1 );
+		    Validator v = new ComboValidator( v1, v2 );
+
+		    Assert.IsTrue( v.Validate( new int[] {} ) );
+		    Assert.IsTrue( v.Validate( true ) );
+		    Assert.IsTrue( v.Validate( false ) );
+		    Assert.IsFalse( v.Validate( 0 ) );
+    		
+		    v = v.ElementValidator();
+
+		    Assert.IsFalse( v.Validate( new int[] {} ) );
+		    Assert.IsFalse( v.Validate( true ) );
+		    Assert.IsFalse( v.Validate( false ) );
+		    Assert.IsTrue( v.Validate( 0 ) );
+	    }
+
+
+        [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void Test4()  
+	    {
+		    Validator v1 = Validator_boolean.Get( 0 );
+		    Validator v2 = Validator_int.Get( 1 );
+		    Validator v = new ComboValidator( v1, v2 );
+
+		    Assert.IsTrue( v.Validate( new int[] {} ) );
+		    Assert.IsTrue( v.Validate( true ) );
+		    Assert.IsTrue( v.Validate( false ) );
+		    Assert.IsFalse( v.Validate( 0 ) );
+    		
+		    v = v.ElementValidator();
+
+		    Assert.IsFalse( v.Validate( new int[] {} ) );
+		    Assert.IsFalse( v.Validate( true ) );
+		    Assert.IsFalse( v.Validate( false ) );
+		    Assert.IsTrue( v.Validate( 0 ) );
+    		
+		    v = v.ElementValidator();
+	    }
+    	
+	    [Test]
+        [ExpectedException(typeof(ArgumentException))]
+	    public void Test5()  
+	    {
+		    Validator v1 = Validator_boolean.Get( 1 );
+		    Validator v2 = Validator_int.Get( 1 );
+		    Validator v = new ComboValidator( v1, v2 );
+
+		    Assert.IsTrue( v.Validate( new Boolean[] {} ) );
+		    Assert.IsTrue( v.Validate( new int[] {} ) );
+    		
+		    v = v.ElementValidator();
+
+		    Assert.IsTrue( v.Validate( true ) );
+		    Assert.IsTrue( v.Validate( false ) );
+		    Assert.IsTrue( v.Validate( 0 ) );
+    		
+		    v = v.ElementValidator();
+	    }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestField.cs b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestField.cs
new file mode 100644
index 0000000..1af6cd8
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestField.cs
@@ -0,0 +1,66 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+
+    [TestFixture]
+    public class TestField
+    {
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestField" );
+        }
+
+        [Test]
+        public void FieldIntegerString()
+        {
+            TestMf(1, "one");
+            TestMf(2, "two");
+            TestMf(3, "three");
+        }
+
+        [Test]
+        public void FieldString()
+        {
+            TestMf("one");
+            TestMf("two");
+            TestMf("three");
+        }
+
+        private void TestMf(int id, string name)
+        {
+            Field mf = new Field(id, name);
+            Assert.AreEqual(id, mf.Id);
+            Assert.AreEqual(name, mf.Name);
+        }
+
+        private void TestMf(string name)
+        {
+            Field mf = new Field(name);
+            Assert.AreEqual(IdName.Hash(name), mf.Id);
+            Assert.AreEqual(name, mf.Name);
+        }
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestFieldMap.cs b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestFieldMap.cs
new file mode 100644
index 0000000..43c0220
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestFieldMap.cs
@@ -0,0 +1,34 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+    [TestFixture]
+    public class TestFieldMap
+    {
+        [Test]
+        [Ignore]
+        public void Nothing()
+        {
+            // TODO implement unit tests for FieldMap
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestIdName.cs b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestIdName.cs
new file mode 100644
index 0000000..725d33d
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestIdName.cs
@@ -0,0 +1,107 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+
+    [TestFixture]
+    public class TestIdName
+    {
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestIdName" );
+        }
+
+        [Test]
+        public void Id()
+        {
+            Assert.AreEqual(1, new IdName(1, "foo").Id);
+            Assert.AreEqual(1, new IdName(1, "bar").Id);
+            Assert.AreEqual(2, new IdName(2, "foo").Id);
+            Assert.AreEqual(2, new IdName(2, "bar").Id);
+        }
+
+        [Test]
+        public void Name()
+        {
+            Assert.AreEqual("foo", new IdName(1, "foo").Name);
+            Assert.AreEqual("bar", new IdName(1, "bar").Name);
+            Assert.AreEqual("foo", new IdName(2, "foo").Name);
+            Assert.AreEqual("bar", new IdName(2, "bar").Name);
+        }
+
+        [Test]
+        public void XToString() 
+        {
+            Assert.AreEqual( "foo(1)", new IdName( 1, "foo" ).ToString() );
+            Assert.AreEqual( "bar(1)", new IdName( 1, "bar" ).ToString() );
+            Assert.AreEqual( "foo(2)", new IdName( 2, "foo" ).ToString() );
+            Assert.AreEqual( "bar(2)", new IdName( 2, "bar" ).ToString() );
+        }
+
+        [Test]
+        public void EqualsObject()
+        {
+            Assert.IsTrue( new IdName( 1, "foo" ).Equals( new IdName( 1, "foo" ) ) );
+            Assert.IsTrue( new IdName( 1, "bar" ).Equals( new IdName( 1, "bar" ) ) );
+            Assert.IsTrue( new IdName( 2, "foo" ).Equals( new IdName( 2, "foo" ) ) );
+            Assert.IsTrue( new IdName( 2, "bar" ).Equals( new IdName( 2, "bar" ) ) );
+
+            Assert.IsFalse( new IdName( 1, "foo" ).Equals( new IdName( 2, "foo" ) ) ); // id changed
+            Assert.IsFalse( new IdName( 1, "foo" ).Equals( new IdName( 1, "bar" ) ) ); // name changed
+            Assert.IsFalse( new IdName( 1, "foo" ).Equals( new IdName( 2, "bar" ) ) ); // id and name changed
+
+            Assert.IsFalse( new IdName( 1, "foo" ).Equals( null ) );
+            Assert.IsFalse( new IdName( 1, "foo" ).Equals( 1 ) );
+            Assert.IsFalse( new IdName( 1, "foo" ).Equals( true ) );
+        }
+
+        [Test]
+        public void HashCodeObject() 
+        {
+            // you cannot really predict when HashCode will not be the same. the
+            // rule is that it must be the same when the objects would compare equal.
+            Assert.AreEqual( new IdName( 1, "foo" ).GetHashCode(), new IdName( 1, "foo" ).GetHashCode() );
+            Assert.AreEqual( new IdName( 2, "foo" ).GetHashCode(), new IdName( 2, "foo" ).GetHashCode() );
+            Assert.AreEqual( new IdName( 1, "bar" ).GetHashCode(), new IdName( 1, "bar" ).GetHashCode() );
+            Assert.AreEqual( new IdName( 2, "bar" ).GetHashCode(), new IdName( 2, "bar" ).GetHashCode() );
+        }
+
+        [Test]
+        public void Hash()
+        {
+            Assert.AreEqual(5381, IdName.Hash(""));
+            Assert.AreEqual(352988316, IdName.Hash("a"));
+            Assert.AreEqual(1511848646, IdName.Hash("ab"));
+            Assert.AreEqual(669497117, IdName.Hash("abc"));
+            Assert.AreEqual(-1994190713, IdName.Hash("abcd"));
+            Assert.AreEqual(-802680418, IdName.Hash("abcde"));
+            Assert.AreEqual(1266308680, IdName.Hash("abcdef"));
+            Assert.AreEqual(-379372513, IdName.Hash("abcdefg"));
+            Assert.AreEqual(-1416967159, IdName.Hash("abcdefgh"));
+            Assert.AreEqual(53556896, IdName.Hash("abcdefghi"));
+            Assert.AreEqual(-4427318, IdName.Hash("abcdefghij"));
+        }
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestIdNameMap.cs b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestIdNameMap.cs
new file mode 100644
index 0000000..8290ef1
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestIdNameMap.cs
@@ -0,0 +1,202 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+
+    public class MyIdNameMap<T> : IdNameMap<IdName>
+    {
+        public override IdName MakeNew(string name)
+        {
+            return new IdName( name );
+        }
+    }
+
+    [TestFixture]
+    public class TestIdNameMap
+    {
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestIdNameMap" );
+        }
+
+        [SetUp] // Before
+        public void Init()
+        {
+            map = new MyIdNameMap<IdName>();
+            a = map.Add(new IdName(1, "a"));
+            b = map.Add(new IdName(2, "b"));
+        }
+
+        private IdNameMap<IdName> map;
+
+        private IdName a;
+
+        private IdName b;
+
+        [Test]
+	    public void Check_a()
+	    {
+		    Assert.AreEqual( 2, map.Size() );
+		    Check( "a", 1, a );
+		    Assert.AreEqual( 2, map.Size() );
+	    }
+    	
+	    private void Check( String name, int id, IdName idName )
+	    {
+		    IdName x = map.Get( id );
+		    Assert.IsNotNull( x );
+		    Assert.AreSame( idName, x );
+		    Assert.AreEqual( id, x.Id );
+		    Assert.AreEqual( name, x.Name );
+    		
+		    x = map.Get( name );
+		    Assert.IsNotNull( x );
+		    Assert.AreSame( idName, x );
+		    Assert.AreEqual( id, x.Id );
+		    Assert.AreEqual( name, x.Name );
+	    }
+    	
+	    
+	    [Test]
+	    public void Check_b()
+	    {
+		    Assert.AreEqual( 2, map.Size() );
+		    Check( "b", 2, b );
+		    Assert.AreEqual( 2, map.Size() );
+	    }
+    	
+	    
+	    [Test]
+	    public void Get_3()
+	    {
+		    Assert.AreEqual( 2, map.Size() );
+		    IdName x = map.Get( 3 );
+		    Assert.IsNull( x );
+		    Assert.AreEqual( 2, map.Size() );
+	    }
+    	
+	    
+	    [Test]
+	    public void Get_3_locked()
+	    {
+		    Assert.AreEqual( 2, map.Size() );
+		    map.Lock();
+		    IdName x = map.Get( 3 );
+		    Assert.IsNull( x );
+		    Assert.AreEqual( 2, map.Size() );
+	    }
+    	
+	    
+	    [Test]
+	    public void Get_c()
+	    {
+		    Assert.AreEqual( 2, map.Size() );
+		    IdName c = map.Get( "c" );
+		    Check( "c", 352988318, c );
+		    Assert.AreEqual( 3, map.Size() );
+	    }
+    	
+	    
+	    [Test]
+	    public void Get_d_locked()
+	    {
+		    Assert.AreEqual( 2, map.Size() );
+		    map.Lock();
+		    IdName d = map.Get( "d" );
+		    Assert.IsNull( d );
+		    Assert.AreEqual( 2, map.Size() );
+	    }
+
+	    
+	    [Test]
+        [ ExpectedException ( typeof( Exception ) ) ]
+	    public void Add_3_c_locked()
+	    {
+		    Assert.AreEqual( 2, map.Size() );
+		    map.Lock();
+		    map.Add( new IdName( 3, "c" ) );
+		    Assert.AreEqual( 2, map.Size() );
+	    }
+    	
+	    
+	    [Test]
+        [ ExpectedException( typeof( ArgumentException ) ) ]
+	    public void Add_id_coll()
+	    {
+		    Assert.AreEqual( 2, map.Size() );
+		    map.Add( new IdName( 1, "c" ) );
+		    Assert.AreEqual( 2, map.Size() );
+	    }
+    	
+	    
+	    [Test]
+        [ ExpectedException( typeof( ArgumentException ) ) ]
+	    public void Add_name_coll()
+	    {
+		    Assert.AreEqual( 2, map.Size() );
+		    map.Add( new IdName( 3, "a" ) );
+		    Assert.AreEqual( 2, map.Size() );
+	    }
+    	
+	    
+	    [Test]
+        [ ExpectedException( typeof( ArgumentException ) ) ]
+	    public void Add_id_name_coll()
+	    {
+		    Assert.AreEqual( 2, map.Size() );
+		    map.Add( new IdName( 1, "a" ) );
+		    Assert.AreEqual( 2, map.Size() );
+	    }
+    	
+	    
+	    [Test]
+	    public void Values1()
+	    {
+		    List<IdName> actual = map.Values();
+		    Assert.AreEqual( 2, actual.Count );
+		    List<IdName> expected = new List<IdName>();
+		    expected.Add( new IdName( 1, "a" ) );
+		    expected.Add( new IdName( 2, "b" ) );
+		    Assert.AreEqual( expected, actual );
+    		
+		    map.Get( "c" );
+    		
+		    actual = map.Values();
+		    Assert.AreEqual( 3, actual.Count );
+		    expected = new List<IdName>();
+		    expected.Add( new IdName( 1, "a" ) );
+		    expected.Add( new IdName( 2, "b" ) );
+		    expected.Add( new IdName( "c" ) );
+		    Assert.AreEqual( expected, actual );
+	    }
+
+        [Test]
+        public void Values2()
+        {
+            Assert.AreNotSame(map.Values(),map.Values());
+        }
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestMessage.cs b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestMessage.cs
new file mode 100644
index 0000000..3807902
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestMessage.cs
@@ -0,0 +1,366 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+    [TestFixture]
+    public class TestMessage
+    {
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestMessage" );
+        }
+        private MyValueFactory vf = new MyValueFactory(); 
+        private XType mt1 = new XType(1, "mt"); 
+        private XType rmt = new XType(2, "rmt");
+        private Field mf1 = new Field(3, "x");
+        private Field mf2 = new Field(4, "y");
+
+        public TestMessage()
+        {
+            mt1.PutValidator( mf1, Validator_int.Get( 0 ) );
+            mt1.PutValidator( mf2, Validator_int.Get( 0 ) );
+            mt1.PutValidator( vf.mf_messageId, Validator_long.Get( 0 ) );
+
+            rmt.PutValidator( vf.mf_messageId, Validator_long.Get( 0 ) );
+            rmt.PutValidator( vf.mf_inReplyTo, Validator_long.Get( 0 ) );
+
+        }
+
+        [Test]
+        public void GetVf()
+        {
+            Message msg = new Message( mt1, vf );
+            Assert.AreSame( vf, msg.Vf );
+        }
+
+        //[Test]
+        //public void TestArrayIterator()
+        //{
+        //    ArrayIterator<int?> fooBar = new ArrayIterator<int?>(new int?[] { 1, 2, 3, 4, 5 });
+        //    Assert.IsTrue(fooBar.MoveNext());
+        //    Assert.AreEqual(1, fooBar.Current);
+        //    Assert.IsTrue(fooBar.MoveNext());
+        //    Assert.AreEqual(2, fooBar.Current);
+        //    Assert.IsTrue(fooBar.MoveNext());
+        //    Assert.AreEqual(3, fooBar.Current);
+        //    Assert.IsTrue(fooBar.MoveNext());
+        //    Assert.AreEqual(4, fooBar.Current);
+        //    Assert.IsTrue(fooBar.MoveNext());
+        //    Assert.AreEqual(5, fooBar.Current);
+        //    Assert.IsFalse(fooBar.MoveNext());
+        //}
+
+        //[Test]
+        //public void WriteMessage()
+        //{
+        //    Message msg = new Message( mt1 , vf );
+        //    WriteHelper(msg);
+
+        //    msg[mf1] = 123;
+        //    WriteHelper(msg);
+
+        //    msg[mf2] = 234 ;
+        //    WriteHelper(msg);
+        //}
+
+        //private void WriteHelper(Message msg)
+        //{
+        //    TaggedDataOutput tdo = new FakeTdo(msg);
+        //    msg.WriteMessage(tdo);
+        //    //tdo.Close();
+        //}
+
+        [Test]
+        public void Reply()
+        {
+            Message msg = new Message(mt1, vf);
+            msg.MessageId = 12345L;
+
+            Message rmsg = msg.Reply(rmt);
+            Assert.AreSame(rmt, rmsg.GetXType);
+            Assert.AreSame(vf, rmsg.Vf);
+            Assert.AreEqual(12345L, rmsg.InReplyTo);
+        }
+
+        [Test]
+        public void MessageId()
+        {
+            Message msg = new Message(mt1, vf);
+            Assert.IsNull(msg.MessageId);
+            msg.MessageId = 234L;
+            Assert.AreEqual(234L, msg.MessageId);
+            msg.MessageId = 345L;
+            Assert.AreEqual(345L, msg.MessageId);
+        }
+
+        [Test]
+        public void InReplyTo()
+        {
+            Message msg = new Message(rmt, vf);
+            Assert.IsNull(msg.InReplyTo);
+            msg.InReplyTo = 234L;
+            Assert.AreEqual(234L, msg.InReplyTo);
+            msg.InReplyTo = 345L;
+            Assert.AreEqual(345L, msg.InReplyTo);
+        }
+
+        //public class FakeTdo : TaggedDataOutput 
+        //{
+        //    public FakeTdo(Message msg)
+        //    {
+        //        this.xmsg = msg;
+        //    }
+
+        //    private Message xmsg; 
+
+        //    public void StartMessage(Message msg)
+        //    {
+        //        Assert.AreSame(xmsg, msg);
+        //        Assert.IsFalse(started);
+        //        Assert.IsFalse(ended);
+
+        //        started = true;
+        //    }
+
+        //    private bool started;
+
+        //    private bool ended;
+
+        //    public void WriteStructElement(Field key, Object value)
+        //    {
+        //        Assert.IsTrue(started);
+        //        Assert.IsFalse(ended);
+        //        items[key] = value;
+        //    }
+
+        //    private Dictionary<Field, Object> items = new Dictionary<Field, Object>();
+
+        //    public void EndMessage(Message msg)
+        //    {
+        //        Assert.AreSame(xmsg, msg);
+        //        Assert.IsTrue(started);
+        //        Assert.IsFalse(ended);
+
+        //        ended = true;
+        //    }
+
+        //    public void Close()
+        //    {
+        //        Assert.IsTrue(started);
+        //        Assert.IsTrue(ended);
+
+        //        Assert.AreEqual(xmsg.Count, items.Count);
+        //        Assert.AreEqual(xmsg, items); //entrySet() deleted
+        //    }
+
+        //    public void EndArray(ArrayValue array)
+        //    {
+        //        throw new NotSupportedException("not implemented");
+        //    }
+
+        //    public void EndStruct(StructValue struc)
+        //    {
+        //        throw new NotSupportedException("not implemented");
+        //    }
+
+        //    public void StartArray(ArrayValue array)
+        //    {
+        //        throw new NotSupportedException("not implemented");
+        //    }
+
+        //    public void StartStruct(StructValue struc)
+        //    {
+        //        throw new NotSupportedException("not implemented");
+        //    }
+
+        //    public void WriteArrayElement(Object value)
+        //    {
+        //        throw new NotSupportedException("not implemented");
+        //    }
+
+        //    #region TaggedDataOutput Members
+
+
+        //    public void SetBuffer( Etch.Transport.FlexBuffer msgBuf )
+        //    {
+        //        // ignore
+        //    }
+
+        //    #endregion
+        //}
+
+        public class MyValueFactory : ValueFactory
+	    {
+		    ///////////////
+		    // MESSAGEID //
+		    ///////////////
+    		
+		    public long? GetMessageId( Message msg )
+		    {
+			    return (long?) msg.Get( mf_messageId );
+		    }
+
+		    public void SetMessageId( Message msg, long? msgid )
+		    {
+			    msg[mf_messageId] = msgid;
+		    }
+
+            public Field Get_mf__messageId()
+            {
+                return mf_messageId;
+            }
+    		
+		    public readonly Field mf_messageId = new Field( "_messageId" );
+
+		    ///////////////
+		    // INREPLYTO //
+		    ///////////////
+    		
+		    public long? GetInReplyTo( Message msg )
+		    {
+			     return (long?) msg.Get( mf_inReplyTo );
+		    }
+
+		    public void SetInReplyTo( Message msg, long? msgid )
+		    {
+			    msg[mf_inReplyTo] = msgid ;
+		    }
+
+            public Field get_mf__inReplyTo()
+            {
+                return mf_inReplyTo;
+            }
+    		
+		    public readonly Field mf_inReplyTo = new Field( "_inReplyTo" );
+
+		    ////////////
+		    // UNUSED //
+		    ////////////
+    		
+
+		    public StructValue ExportCustomValue( Object value )
+		    {
+                throw new NotSupportedException("not implemented");
+		    }
+
+		 
+
+		    public Encoding GetStringEncoding()
+		    {
+                throw new NotSupportedException("not implemented");
+		    }
+
+		    public XType GetType( int id )
+		    {
+                throw new NotSupportedException("not implemented");
+		    }
+
+		    public XType GetType( String name )
+		    {
+                throw new NotSupportedException("not implemented");
+		    }
+
+		    public ICollection<XType> GetTypes()
+		    {
+                throw new NotSupportedException("not implemented");
+		    }
+
+		    public Object ImportCustomValue( StructValue sv )
+		    {
+                throw new NotSupportedException("not implemented");
+		    }
+
+            public XType GetCustomStructType( Type c )
+		    {
+                throw new NotSupportedException("not implemented");
+		    }
+
+            public XType Get_mt__Etch_AuthException()
+            {
+                throw new NotSupportedException("not implemented");
+            }
+
+            public XType Get_mt__Etch_RuntimeException()
+            {
+                throw new NotSupportedException("not implemented");
+            }
+
+            public XType get_mt__exception()
+            {
+                throw new NotSupportedException("not implemented");
+            }
+
+            #region ValueFactory Members
+
+            public XType GetType( int? id )
+            {
+                throw new Exception( "The method or operation is not implemented." );
+            }
+
+            public Field GetField( int? id )
+            {
+                throw new Exception( "The method or operation is not implemented." );
+            }
+
+            #endregion
+
+
+            public void AddType(XType type)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void LockDynamicTypes()
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void UnlockDynamicTypes()
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public Field Get_mf__inReplyTo()
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+
+            public Validator.Level GetLevel()
+            {
+                return Validator.Level.FULL;
+            }
+
+            public Validator.Level SetLevel(Validator.Level level)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestStructValue.cs b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestStructValue.cs
new file mode 100644
index 0000000..3cb8028
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestStructValue.cs
@@ -0,0 +1,368 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+    [TestFixture]
+    public class TestStructValue
+    {
+        private readonly ValueFactory vf = new DummyValueFactory();
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestStructValue" );
+        }
+
+        private XType mt1 = new XType("one");
+        private XType mt2 = new XType("two");
+        private Field mf1 = new Field( "f1" );
+        private Field mf2 = new Field( "f2" );
+        private Field mf3 = new Field( "f3" );
+        private Field mf4 = new Field( "f4" );
+        private Field mf5 = new Field( "f5" );
+        private Field mf6 = new Field( "f6" );
+
+        public TestStructValue()
+        {
+            mt1.PutValidator( mf1, Validator_boolean.Get( 0 ) );
+            mt1.PutValidator( mf2, Validator_boolean.Get( 1 ) );
+            mt1.PutValidator( mf3, Validator_int.Get( 0 ) );
+            mt1.PutValidator( mf4, Validator_int.Get( 1 ) );
+            mt1.PutValidator( mf5, Validator_string.Get( 0 ) );
+            mt1.PutValidator( mf6, Validator_string.Get( 1 ) );
+        }
+
+        [Test]
+        public void Test2str() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+            Assert.AreEqual( "one(785945377): {}", sv.ToString() );
+
+            sv = new StructValue(mt2, vf);
+            Assert.AreEqual( "two(827843303): {}", sv.ToString() );
+
+            sv = new StructValue(mt1, vf);
+            sv.Add( mf1, true );
+            Assert.AreEqual( "one(785945377): {f1(1512176592)=True}", sv.ToString() );
+
+            sv = new StructValue(mt1, vf);
+            sv.Add( mf3, 23 );
+            Assert.AreEqual( "one(785945377): {f3(1512176594)=23}", sv.ToString() );
+
+            sv = new StructValue(mt1, vf);
+            sv.Add( mf1, false );
+            sv.Add( mf3, 74 );
+            Assert.AreEqual( "one(785945377): {f1(1512176592)=False, f3(1512176594)=74}", sv.ToString() );
+	    }
+
+        [Test]
+        public void GetXType()
+        {
+            StructValue sv = new StructValue(mt1, vf);
+            Assert.AreSame(mt1, sv.GetXType);
+
+            sv = new StructValue(mt2, vf);
+            Assert.AreSame(mt2, sv.GetXType);
+        }
+
+        [Test]
+        public void IsType()
+        {
+            StructValue sv = new StructValue(mt1, vf);
+            Assert.IsTrue(sv.IsType(mt1));
+            Assert.IsFalse(sv.IsType(mt2));
+
+            sv = new StructValue(mt2, vf);
+            Assert.IsTrue(sv.IsType(mt2));
+            Assert.IsFalse(sv.IsType(mt1));
+        }
+
+        [Test]
+        public void CheckType_()
+        {
+            StructValue sv = new StructValue(mt1, vf);
+            sv.CheckType(mt1);
+            try { sv.CheckType(mt2); Assert.IsTrue(false); }
+            catch(ArgumentException ) { 
+                Assert.IsTrue(true);
+            }
+
+            sv = new StructValue(mt2, vf);
+            sv.CheckType(mt2);
+            try { sv.CheckType(mt1); Assert.IsTrue(false); }
+            catch(ArgumentException ) { Assert.IsTrue(true);
+            }
+        }
+
+        [Test]
+        public void Iterator()
+        {
+            StructValue sv = new StructValue(mt1, vf);
+            Assert.IsFalse( sv.GetEnumerator().MoveNext() );
+
+            sv.Add( mf1, true );
+
+            IEnumerator<KeyValuePair<Field, Object>> it = sv.GetEnumerator();
+            Assert.IsTrue( it.MoveNext() );
+            KeyValuePair<Field, Object> me = it.Current;
+            Assert.AreEqual( mf1, me.Key );
+            Assert.AreEqual( true, me.Value );
+            Assert.IsFalse( it.MoveNext() );
+
+            Dictionary<Field, Object> vals = new Dictionary<Field, object>();
+            vals.Add( mf1, true );
+            vals.Add( mf3, 2 );
+            vals.Add( mf5, "a" );
+
+            sv.Add( mf3, 2 );
+            sv.Add( mf5, "a" );
+
+            it = sv.GetEnumerator();
+            while ( it.MoveNext() )
+            {
+                me = it.Current;
+                Field key = me.Key;
+                Assert.IsTrue( vals.ContainsKey( key ) );
+                Assert.AreEqual( vals[key], me.Value );
+                vals.Remove( key );
+            }
+            Assert.IsTrue( vals.Count == 0 );
+        }
+
+        public void CheckType1()
+	    {
+            new StructValue(mt1, vf).CheckType(mt1);
+            new StructValue(mt2, vf).CheckType(mt2);
+	    }
+
+	     
+	    [Test][ExpectedException(typeof(ArgumentException))]
+	    public void CheckType2()
+	    {
+            new StructValue(mt1, vf).CheckType(mt2);
+	    }
+
+	     
+	    [Test][ExpectedException(typeof(ArgumentException))]
+	    public void CheckType()
+	    {
+            new StructValue(mt2, vf).CheckType(mt1);
+	    }
+    	
+	     
+	    [Test]
+	    public void Get() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+		    Assert.IsTrue( sv.Count == 0 );
+		    Assert.AreEqual( 0, sv.Count );
+            Assert.IsNull( sv.Get( mf1 ) );
+    		
+		    sv.Add( mf1, true );
+		    Assert.IsFalse( sv.Count == 0 );
+		    Assert.AreEqual( 1, sv.Count );
+		    Assert.AreEqual( true, sv.Get( mf1 ) );
+    		
+		    sv.Add( mf1, false );
+		    Assert.IsFalse( sv.Count == 0 );
+		    Assert.AreEqual( 1, sv.Count );
+		    Assert.AreEqual( false, sv.Get( mf1 ) );
+    		
+		    sv.Add( mf1, null );
+		    Assert.IsTrue( sv.Count == 0 );
+		    Assert.AreEqual( 0, sv.Count );
+		    Assert.IsNull( sv.Get( mf1 ) );
+	    }
+    	
+	     
+	    [Test]
+	    public void Remove() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+		    Assert.IsTrue( sv.Count == 0 );
+		    Assert.AreEqual( 0, sv.Count );
+		    Assert.IsNull( sv.Get( mf1 ) );
+    		
+		    sv.Remove( mf1 );
+		    Assert.IsTrue( sv.Count == 0 );
+		    Assert.AreEqual( 0, sv.Count );
+		    Assert.IsNull( sv.Get( mf1 ) );
+    		
+		    sv.Add( mf1, true );
+		    Assert.IsFalse( sv.Count == 0 );
+		    Assert.AreEqual( 1, sv.Count );
+		    Assert.AreEqual( true, sv.Get( mf1 ) );
+    		
+		    sv.Remove( mf1 );
+		    Assert.IsTrue( sv.Count == 0 );
+		    Assert.IsNull( sv.Get( mf1 ) );
+    		
+		    sv.Remove( mf1 );
+		    Assert.AreEqual( 0, sv.Count );
+		    Assert.IsNull( sv.Get( mf1 ) );
+	    }
+    	
+	     
+	    [Test]
+	    public void Put1() 
+	    {
+		    StructValue sv = new StructValue( mt1, vf );
+		    sv.Add( mf1, false );
+		    sv.Add( mf2, new Boolean[] { true, false } );
+		    sv.Add( mf3, 1 );
+		    sv.Add( mf4, new int[] { 1, 2 } );
+		    sv.Add( mf5, "a" );
+		    sv.Add( mf6, new String[] { "a", "b" } );
+		    Assert.AreEqual( 6, sv.Count );
+	    }
+    	
+	     
+	    [Test]
+	    public void Put2() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+		    sv.Add( mf1, null );
+		    sv.Add( mf2, null );
+		    sv.Add( mf3, null );
+		    sv.Add( mf4, null );
+		    sv.Add( mf5, null );
+		    sv.Add( mf6, null );
+		    Assert.AreEqual( 0, sv.Count );
+	    }
+    	
+	     
+	    [Test]
+	    public void Put3() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+		    sv.Add( mf1, false );
+		    sv.Add( mf2, new Boolean[] { true, false } );
+		    sv.Add( mf3, 1 );
+		    sv.Add( mf4, new int[] { 1, 2 } );
+		    sv.Add( mf5, "a" );
+		    sv.Add( mf6, new String[] { "a", "b" } );
+		    Assert.AreEqual( 6, sv.Count );
+    		
+		    // now "remove" them all
+    		
+		    sv.Add( mf1, null );
+		    sv.Add( mf2, null );
+		    sv.Add( mf3, null );
+		    sv.Add( mf4, null );
+		    sv.Add( mf5, null );
+		    sv.Add( mf6, null );
+		    Assert.AreEqual( 0, sv.Count );
+	    }
+    	
+	     
+	    [Test][ExpectedException(typeof(ArgumentException))]
+	    public void put5() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+		    sv.Add( mf1, (sbyte) 1 ); // wrong type
+	    }
+    	
+	     
+	    [Test][ExpectedException(typeof(ArgumentException))]
+	    public void put6() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+		    sv.Add( mf1, (short) 1 ); // wrong type
+	    }
+    	
+	     
+	    [Test][ExpectedException(typeof(ArgumentException))]
+	    public void put7() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+		    sv.Add( mf1, 1 ); // wrong type
+	    }
+    	
+	     
+	    [Test][ExpectedException(typeof(ArgumentException))]
+	    public void put8() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+		    sv.Add( mf1, (long) 1 ); // wrong type
+	    }
+    	
+	     
+	    [Test][ExpectedException(typeof(ArgumentException))]
+	    public void put9() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+		    sv.Add( mf1, (float) 1.2 ); // wrong type
+	    }
+    	
+	     
+	    [Test][ExpectedException(typeof(ArgumentException))]
+	    public void put10() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+		    sv.Add( mf1, 1.2 ); // wrong type
+	    }
+    	
+	     
+	    [Test][ExpectedException(typeof(ArgumentException))]
+	    public void put11() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+		    sv.Add( mf1, "a" ); // wrong type
+	    }
+    	
+	     
+	    [Test]
+	    public void put12() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+		    sv.Add( mf2, null );
+	    }
+    	
+	     
+	    [Test]
+	    public void put13() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+		    sv.Add( mf2, new Boolean[] {} );
+	    }
+    	
+	     
+	    [Test][ExpectedException(typeof(ArgumentException))]
+	    public void put14() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+		    sv.Add( mf2, true );
+	    }
+    	
+	     
+	    [Test][ExpectedException(typeof(ArgumentException))]
+	    public void put15() 
+	    {
+            StructValue sv = new StructValue(mt1, vf);
+		    sv.Add( mf2, new Boolean[][] {} );
+	    }
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestTypeMap.cs b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestTypeMap.cs
new file mode 100644
index 0000000..b804bd4
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestTypeMap.cs
@@ -0,0 +1,34 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+    [TestFixture]
+    public class TestTypeMap
+    {
+        [Test]
+        [Ignore]
+        public void Nothing()
+        {
+            // TODO implement unit tests for TypeMap
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestXType.cs b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestXType.cs
new file mode 100644
index 0000000..601b484
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Msg/TestXType.cs
@@ -0,0 +1,103 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Msg
+{
+
+    [TestFixture]
+    public class TestXType
+    {
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestXType" );
+        }
+
+        [Test]
+        public void TypeIntegerString()
+        {
+            TestMt(1, "one");
+            TestMt(2, "two");
+            TestMt(3, "three");
+        }
+
+        [Test]
+        public void TypeString()
+        {
+            TestMt("one");
+            TestMt("two");
+            TestMt("three");
+        }
+
+        [Test]
+        public void TestGetValidator() 
+	    {
+		    XType t = new XType( "t" );
+		    Field f = new Field( "f" );
+		    Field g = new Field( "g" );
+		    Validator v = Validator_int.Get( 0 );
+    		
+		    t.PutValidator( f, v );
+
+		    Assert.AreEqual( v, t.GetValidator( f ) );
+		    Assert.IsNull( t.GetValidator( g ) );
+	    }
+
+        [Test]
+	    public void TestPutValidatorNull() 
+	    {
+		    XType t = new XType( "t" );
+		    Field f = new Field( "f" );
+		    Validator v = Validator_int.Get( 0 );
+
+		    Assert.IsNull( t.GetValidator( f ) );
+    		
+		    t.PutValidator( f, null );
+		    Assert.IsNull( t.GetValidator( f ) );
+    		
+		    t.PutValidator( f, v );
+		    Assert.AreEqual( v, t.GetValidator( f ) );
+    		
+		    t.PutValidator( f, v );
+            Assert.AreEqual( typeof( ComboValidator ), ( t.GetValidator( f ) ).GetType() );
+    		
+		    t.ClearValidator( f );
+		    Assert.IsNull( t.GetValidator( f ) );
+	    }
+
+        private void TestMt(int id, string name)
+        {
+            XType mt = new XType(id, name);
+            Assert.AreEqual(id, mt.Id);
+            Assert.AreEqual(name, mt.Name);
+        }
+
+        private void TestMt(string name)
+        {
+            XType mt = new XType(name);
+            Assert.AreEqual(IdName.Hash(name), mt.Id);
+            Assert.AreEqual(name, mt.Name);
+        }
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestDefaultValueFactory.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestDefaultValueFactory.cs
new file mode 100644
index 0000000..b1d71aa
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestDefaultValueFactory.cs
@@ -0,0 +1,536 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    [TestFixture]
+    public class TestDefaultValueFactory : List<Object>
+    {
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.WriteLine("TestDefaultValueFactory");
+        }
+
+        private readonly MyValueFactory vf = new MyValueFactory();
+
+        [Test]
+	    public void testTypes()
+	    {
+            MyValueFactory vf = new MyValueFactory();
+
+		    List<XType> eTypes = MkTypeSet(
+                vf.GetType("_Etch_RuntimeException"),
+                vf.GetType("_Etch_List"),
+                vf.GetType("_Etch_Map"),
+                vf.GetType("_Etch_Datetime"),
+                vf.GetType("_Etch_AuthException"),
+                vf.GetType("_exception"),
+			    MyValueFactory._mt_x,
+			    MyValueFactory._mt_y
+		    );
+
+            //Dump("eTypes", eTypes);
+            //Dump("vf.GetTypes()", vf.GetTypes());
+
+		    Assert.IsTrue( CompareTypeLists( eTypes, vf.GetTypes() ) );
+
+		    foreach (XType t in eTypes)
+			    TestType( t );
+	    }
+
+        private void Dump(string title, ICollection<XType> c)
+        {
+            Console.Write(title+"[");
+            bool first = true;
+            foreach (XType type in c)
+            {
+                if (!first)
+                    Console.Write(", ");
+                else
+                    first = false;
+                Console.Write(type);
+            }
+            Console.WriteLine("]");
+        }
+    	
+        /// <summary>
+        /// Utility function to compare two lists of types
+        /// </summary>
+        /// <param name="list1"></param>
+        /// <param name="list2"></param>
+        /// <returns></returns>
+        private bool CompareTypeLists(List<XType> list1, ICollection<XType> list2)
+        {
+            if ((list1.Count == 0) && (list2.Count == 0))
+                return true;
+
+            // first compare length
+            if (list1.Count != list2.Count)
+            {
+                Console.WriteLine("lists count differs: {0} v. {1}", list1.Count, list2.Count);
+                return false;
+            }
+
+            // verify that each element in list1 is 
+            // present in list2 and vice versa
+
+            foreach (XType me in list1)
+            {
+                if (!list2.Contains(me))
+                {
+                    Console.WriteLine("!list2.Contains({0})", me);
+                    return false;
+                }
+            }
+
+            foreach (XType me in list2)
+            {
+                if (!list1.Contains(me))
+                {
+                    Console.WriteLine("!list1.Contains({0})", me);
+                    return false;
+                }
+            }
+
+            return true;
+        }
+        
+        /// <summary>
+        /// Utility function to compare two lists of fields
+        /// </summary>
+        /// <param name="list1"></param>
+        /// <param name="list2"></param>
+        /// <returns></returns>
+        private bool CompareFieldLists( List<Field> list1, ICollection<Field> list2 )
+        {
+            if ( ( list1.Count == 0 ) && ( list2.Count == 0 ) )
+                return true;
+
+            // first compare length
+            if ( list1.Count != list2.Count )
+                return false;
+
+            // verify that each element in list1 is 
+            // present in list2
+            foreach ( Field me in list1 )
+                if ( !list2.Contains( me ) )
+                    return false;
+
+            return true;
+        }
+
+	    private List<XType> MkTypeSet( params XType[] types )
+	    {
+		    List<XType> set = new List<XType>();
+
+		    foreach (XType t in types)
+			    set.Add( t );
+
+		    return set;
+	    }
+    	
+	    private void TestType( XType type )
+	    {
+		    Assert.AreSame( type, vf.GetType( type.Id ) );
+		    Assert.AreSame( type, vf.GetType( type.Name ) );
+	    }
+    	
+	    
+    	
+	    private List<Field> MkFieldSet( params Field[] fields )
+	    {
+		    List<Field> set = new List<Field>();
+
+		    foreach (Field f in fields )
+			    set.Add( f );
+
+		    return set;
+	    }
+    	
+	    
+	    
+	    [Test]
+	    public void Test_Etch_RuntimeException_fields()
+	    {
+		    TestTypeFields(
+                vf.GetType("_Etch_RuntimeException"),
+			    DefaultValueFactory._mf_msg
+		    );
+    		
+		    TestTypeField(
+                vf.GetType("_Etch_RuntimeException"),
+			    DefaultValueFactory._mf_msg,
+			    "abc"
+		    );			
+	    }
+    	
+	    
+	    [Test]
+        [ExpectedException (typeof(ArgumentException))]
+	    public void Test_Etch_RuntimeException_msg_badValue()
+	    {
+		    TestTypeField(
+                vf.GetType("_Etch_RuntimeException"),
+			    DefaultValueFactory._mf_msg,
+			    123
+		    );
+	    }
+    	
+	    
+	    [Test]
+        [ ExpectedException ( typeof( ArgumentException ) ) ]
+	    public void Test_Etch_RuntimeException_badField()
+	    {
+		    TestTypeField(
+                vf.GetType("_Etch_RuntimeException"),
+			    MyValueFactory._mf_a,
+			    "abc"
+		    );	
+	    }
+    	
+	    private void TestTypeField( XType type, Field field, Object value )
+	    {
+		    Message msg = new Message( type, vf );
+		    msg.Add( field, value );
+	    }
+    	
+	    private void TestTypeFields( XType type, params Field[] fields )
+	    {
+		    List<Field> aFields = type.GetFields();
+		    List<Field> eFields = MkFieldSet( fields );
+            Assert.IsTrue( CompareFieldLists( eFields, aFields ) );
+	    }
+    	
+	    
+	    [Test]
+	    public void Test_Etch_AuthException_fields()
+	    {
+		    TestTypeFields(
+                vf.GetType("_Etch_AuthException"),
+			    DefaultValueFactory._mf_msg
+		    );
+    		
+		    TestTypeField(
+                vf.GetType("_Etch_AuthException"),
+			    DefaultValueFactory._mf_msg,
+			    "abc"
+		    );
+	    }
+    	
+	    
+	    [Test]
+        [ ExpectedException ( typeof( ArgumentException ) ) ]
+	    public void Test_Etch_AuthException_msg_badValue()
+	    {
+		    TestTypeField(
+                vf.GetType("_Etch_AuthException"),
+			    DefaultValueFactory._mf_msg,
+			    123
+		    );
+	    }
+    	
+	    [Test]
+	    public void Test_exception_fields()
+	    {
+		    TestTypeFields(
+                vf.GetType("_exception"),
+			    DefaultValueFactory._mf_result,
+			    DefaultValueFactory._mf__messageId,
+			    DefaultValueFactory._mf__inReplyTo
+		    );
+    		
+		    TestTypeField(
+                vf.GetType("_exception"),
+			    DefaultValueFactory._mf_result,
+			    new Exception()
+		    );
+    		
+		    TestTypeField(
+                vf.GetType("_exception"),
+			    DefaultValueFactory._mf__messageId,
+			    123L
+		    );
+    		
+		    TestTypeField(
+                vf.GetType("_exception"),
+			    DefaultValueFactory._mf__inReplyTo,
+			    123L
+		    );
+	    }
+    	
+	    
+	    [Test]
+        [ ExpectedException ( typeof( ArgumentException ) ) ]
+	    public void Test_exception_result_badValue()
+	    {
+		    TestTypeField(
+                vf.GetType("_exception"),
+			    DefaultValueFactory._mf_result,
+			    123
+		    );
+	    }
+    	
+	    
+	    [Test]
+        [ ExpectedException ( typeof( ArgumentException ) ) ]
+	    public void Test_exception_messageId_badValue()
+	    {
+		    TestTypeField(
+                vf.GetType("_exception"),
+			    DefaultValueFactory._mf__messageId,
+			    true
+		    );
+	    }
+    	
+	    
+	    [Test]
+        [ ExpectedException ( typeof( ArgumentException ) ) ]
+	    public void Test_exception_inReplyTo_badValue()
+	    {
+		    TestTypeField(
+                vf.GetType("_exception"),
+			    DefaultValueFactory._mf__inReplyTo,
+			    "abc"
+		    );
+	    }
+
+	    
+	    [Test]
+	    public void GetType_locked()
+	    {
+		    Assert.IsNotNull( vf.GetType( "x" ) );
+		    Assert.IsNotNull( vf.GetType( "y" ) );
+            Assert.IsNotNull(vf.GetType("a"));
+            vf.LockDynamicTypes();
+		    Assert.IsNull( vf.GetType( "b" ) );
+	    }
+
+	    
+	    [Test]
+	    public void GetField_locked()
+	    {
+		    XType type = new XType("blah");
+
+            Assert.IsNotNull( type.GetField( "a" ) );
+		    Assert.IsNotNull( type.GetField( "b" ) );
+            type.Lock();
+            Assert.IsNotNull(type.GetField("a"));
+            Assert.IsNotNull(type.GetField("b"));
+		    Assert.IsNull( type.GetField( "x" ) );
+		    Assert.IsNull( type.GetField( "y" ) );
+	    }
+
+        [Test]
+        public void GetField_Id_MessageId()
+        {
+            Assert.AreEqual("_messageId", DefaultValueFactory._mf__messageId.Name);
+            Assert.AreEqual(1661383784, DefaultValueFactory._mf__messageId.Id);
+        }
+
+        [Test]
+        public void GetField_Id_InReplyTo()
+        {
+            Assert.AreEqual("_inReplyTo", DefaultValueFactory._mf__inReplyTo.Name);
+            Assert.AreEqual(-307705434,DefaultValueFactory._mf__inReplyTo.Id);
+        }
+
+        
+        /////////////////////
+        // STRING ENCODING //
+        /////////////////////
+
+        [Test]
+        public void GetStringEncoding()
+        {
+            Encoding enc = vf.GetStringEncoding();
+            String s = enc.GetString(enc.GetBytes("abc"));
+            Assert.AreEqual("abc", s);
+        }
+
+        ////////////////
+        // MESSAGE ID //
+        ////////////////
+
+        [Test]
+        public void MessageId()
+        {   
+            XType mt_foo = new XType( "foo" );
+            mt_foo.PutValidator( DefaultValueFactory._mf__messageId, Validator_long.Get( 0 ) );
+            
+            Message msg = new Message( mt_foo, vf );
+
+            Assert.IsNull(vf.GetMessageId(msg));
+
+            vf.SetMessageId(msg, 234L);
+
+            long msgid = (long) vf.GetMessageId(msg);
+            Assert.IsNotNull(msgid);
+            Assert.AreEqual(234L, msgid);
+
+            vf.SetMessageId(msg, null);
+
+            Assert.IsNull(vf.GetMessageId(msg));
+        }
+
+        /////////////////
+        // IN REPLY TO //
+        /////////////////
+
+        [Test]
+        public void InReplyTo()
+        {
+            XType mt_foo = new XType( "foo" );
+            mt_foo.PutValidator( DefaultValueFactory._mf__inReplyTo, Validator_long.Get( 0 ) );
+
+            Message msg = new Message( mt_foo, vf );
+
+            Assert.IsNull( vf.GetInReplyTo( msg ) );
+
+            vf.SetInReplyTo( msg, 234L );
+
+            long? msgid = vf.GetInReplyTo( msg );
+            Assert.IsNotNull( msgid );
+            Assert.AreEqual( 234L, msgid );
+
+            vf.SetInReplyTo( msg, null );
+
+            Assert.IsNull( vf.GetInReplyTo( msg ) );
+        }
+
+        //////////////////////
+        // VALUE CONVERSION //
+        //////////////////////
+
+        [Test]
+        public void ExportCustomValue_RuntimeException()
+        {
+            Exception value = new NullReferenceException();
+            StructValue sv = vf.ExportCustomValue(value);
+            sv.CheckType(vf.GetType("_Etch_RuntimeException"));
+            Assert.AreEqual(1, sv.Count);
+            Assert.AreEqual("System.NullReferenceException: Object reference not set to an instance of an object.",
+                sv.Get(DefaultValueFactory._mf_msg));
+        }
+
+        [Test]
+        public void ExportCustomValue_RuntimeException_msg()
+        {
+            Exception value = new NullReferenceException("foo != null");
+            StructValue sv = vf.ExportCustomValue(value);
+            sv.CheckType(vf.GetType("_Etch_RuntimeException"));
+            Assert.AreEqual(1, sv.Count);
+            Assert.AreEqual("System.NullReferenceException: foo != null",
+                sv.Get(DefaultValueFactory._mf_msg));
+        }
+
+        [Test]
+        public void ExportCustomValue_Object()
+        {
+            Object value = new Object();
+            Assert.IsNull( vf.ExportCustomValue( value ) );
+            // cannot export unsupported XType
+        }
+
+        [Test]
+        public void ImportCustomValue_Etch_RuntimeException()
+        {
+            StructValue sv = new StructValue(vf.GetType("_Etch_RuntimeException"), vf);
+            _Etch_RuntimeException e = (_Etch_RuntimeException) vf.ImportCustomValue(sv);
+            Assert.IsNotNull(e);
+            Assert.IsNull(e.msg);
+        }
+
+        [Test]
+        public void ImportCustomValue_Etch_RuntimeException_msg()
+        {
+            StructValue sv = new StructValue(vf.GetType("_Etch_RuntimeException"), vf);
+            sv[DefaultValueFactory._mf_msg] = "foo";
+            _Etch_RuntimeException e = (_Etch_RuntimeException) vf.ImportCustomValue(sv);
+            Assert.IsNotNull(e);
+            Assert.AreEqual("foo", e.msg);
+        }
+
+        [Test]
+        public void ImportCustomValue_Unknown()
+        {
+            StructValue sv = new StructValue( vf.GetType( "x" ), vf );
+            Assert.IsNull( vf.ImportCustomValue( sv ) );
+            // cannot using unsupported XType
+        }
+
+        /// <summary>
+        /// A fake implementation of DefaultValueFactory for testing
+        /// </summary>
+        public class MyValueFactory : DefaultValueFactory
+	    {
+		    private readonly static TypeMap types = new TypeMap();
+
+		   
+
+            private readonly static Class2TypeMap class2type = 
+                new Class2TypeMap();
+
+		    
+    		
+		    // define our types and fields here:
+    		
+		    /** type x */
+		    public readonly static XType _mt_x = types.Get( "x" );
+    		
+		    /** type y */
+		    public readonly static XType _mt_y = types.Get( "y" );
+    		
+		    /** field a */
+		    public readonly static Field _mf_a = new Field( "a" );
+    		
+		    /** field b */
+		    public readonly static Field _mf_b = new Field( "b" );
+
+            static MyValueFactory()
+            {
+                DefaultValueFactory.Init(types, class2type);
+                types.Lock();
+                class2type.Lock();
+
+
+            }
+            
+    		
+		    /**
+		     * Constructs the ValueFactoryFake.
+		     */
+		    public MyValueFactory(): base("none:",types,class2type)
+		    {
+			    // nothing to do.
+		    }
+
+           
+
+	    }
+        
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestFreePool.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestFreePool.cs
new file mode 100644
index 0000000..b0fab94
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestFreePool.cs
@@ -0,0 +1,301 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Threading;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    [TestFixture]
+    public class TestFreePool
+    {
+        private const int Q1 = 30; // 1 quanta of reliable clock tick
+        private const int Q2 = 60; // 2 quanta of reliable clock tick
+        private const int Q3 = 90; // 3 quanta of reliable clock tick
+
+        [Test]
+        public void close1()
+        {
+            FreePool p = new FreePool(2);
+            p.Close();
+        }
+
+        [Test]
+        [ExpectedException(typeof(Exception))]
+        public void close2()
+        {
+            // free pool thread count exceeded or pool closed
+            FreePool p = new FreePool(2);
+            p.Close();
+
+            MyPoolRunnable r = new MyPoolRunnable(0, false);
+            p.Run(r.run, r.exception);
+        }
+
+        [Test]
+        public void close3()
+        {
+            FreePool p = new FreePool(2);
+            p.Close();
+            p.Close();
+        }
+
+        [Test]
+        [ExpectedException(typeof(Exception))]
+        public void join1()
+        {
+            // free pool thread count exceeded or pool closed
+            FreePool p = new FreePool(2);
+            p.Join();
+
+            MyPoolRunnable r = new MyPoolRunnable(0, false);
+            p.Run(r.run, r.exception);
+        }
+
+        [Test]
+        public void join2()
+        {
+            FreePool p = new FreePool(2);
+
+            MyPoolRunnable r = new MyPoolRunnable(0, false);
+            Assert.IsFalse(r.done);
+            Assert.IsNull(r.ex);
+            p.Run(r.run, r.exception);
+            Thread.Sleep(Q2);
+            Assert.IsTrue(r.done);
+            Assert.IsNull(r.ex);
+            p.Join();
+        }
+
+        [Test]
+        public void join3()
+        {
+            FreePool p = new FreePool(2);
+
+            MyPoolRunnable r = new MyPoolRunnable(Q1, false);
+            Assert.IsFalse(r.done);
+            Assert.IsNull(r.ex);
+            p.Run(r.run, r.exception);
+            Assert.IsFalse(r.done);
+            Assert.IsNull(r.ex);
+            p.Join();
+            Assert.IsTrue(r.done);
+            Assert.IsNull(r.ex);
+        }
+
+        [Test]
+        public void run1()
+        {
+            FreePool p = new FreePool(2);
+
+            MyPoolRunnable r = new MyPoolRunnable(0, false);
+            Assert.IsFalse(r.done);
+            Assert.IsNull(r.ex);
+
+            p.Run(r.run, r.exception);
+
+            Thread.Sleep(Q1);
+            Assert.IsTrue(r.done);
+            Assert.IsNull(r.ex);
+        }
+
+        [Test]
+        public void run2()
+        {
+            FreePool p = new FreePool(2);
+            for (int i = 0; i < 100; i++)
+            {
+                MyPoolRunnable r = new MyPoolRunnable(0, false);
+                Assert.IsFalse(r.done);
+                Assert.IsNull(r.ex);
+
+                p.Run(r.run, r.exception);
+
+                Thread.Sleep(Q1);
+                Assert.IsTrue(r.done);
+                Assert.IsNull(r.ex);
+            }
+        }
+
+        [Test]
+        public void run3()
+        {
+            FreePool p = new FreePool(2);
+
+            MyPoolRunnable r = new MyPoolRunnable(0, true);
+            Assert.IsFalse(r.done);
+            Assert.IsNull(r.ex);
+
+            p.Run(r.run, r.exception);
+
+            Thread.Sleep(Q1);
+            Assert.IsFalse(r.done);
+            Assert.IsNotNull(r.ex);
+        }
+
+        [Test]
+        public void run4()
+        {
+            FreePool p = new FreePool(2);
+
+            MyPoolRunnable r = new MyPoolRunnable(Q2, false);
+            Assert.IsFalse(r.done);
+            Assert.IsNull(r.ex);
+
+            p.Run(r.run, r.exception);
+
+            Thread.Sleep(Q1);
+            Assert.IsFalse(r.done);
+            Assert.IsNull(r.ex);
+
+            Thread.Sleep(Q3);
+            Assert.IsTrue(r.done);
+            Assert.IsNull(r.ex);
+        }
+
+        [Test]
+        public void run5()
+        {
+            FreePool p = new FreePool(2);
+
+            MyPoolRunnable r1 = new MyPoolRunnable(Q2, false);
+            Assert.IsFalse(r1.done);
+            Assert.IsNull(r1.ex);
+
+            MyPoolRunnable r2 = new MyPoolRunnable(Q2, false);
+            Assert.IsFalse(r2.done);
+            Assert.IsNull(r2.ex);
+
+            p.Run(r1.run, r1.exception);
+            p.Run(r2.run, r2.exception);
+
+            Thread.Sleep(Q1);
+            Assert.IsFalse(r1.done);
+            Assert.IsNull(r1.ex);
+
+            Assert.IsFalse(r2.done);
+            Assert.IsNull(r2.ex);
+
+            Thread.Sleep(Q3);
+            Assert.IsTrue(r1.done);
+            Assert.IsNull(r1.ex);
+
+            Assert.IsTrue(r2.done);
+            Assert.IsNull(r2.ex);
+        }
+
+        [Test]
+        [ExpectedException(typeof(Exception))]
+        public void run6()
+        {
+            // free pool thread count exceeded
+            FreePool p = new FreePool(2);
+
+            MyPoolRunnable r1 = new MyPoolRunnable(Q2, false);
+            Assert.IsFalse(r1.done);
+            Assert.IsNull(r1.ex);
+
+            MyPoolRunnable r2 = new MyPoolRunnable(Q2, false);
+            Assert.IsFalse(r2.done);
+            Assert.IsNull(r2.ex);
+
+            MyPoolRunnable r3 = new MyPoolRunnable(Q2, false);
+            Assert.IsFalse(r3.done);
+            Assert.IsNull(r3.ex);
+
+            p.Run(r1.run, r1.exception);
+            p.Run(r2.run, r2.exception);
+            p.Run(r3.run, r3.exception);
+        }
+
+        [Test]
+        public void run7()
+        {
+            FreePool p = new FreePool(2);
+
+            MyPoolRunnable r1 = new MyPoolRunnable(Q2, false);
+            Assert.IsFalse(r1.done);
+            Assert.IsNull(r1.ex);
+
+            MyPoolRunnable r2 = new MyPoolRunnable(Q2, false);
+            Assert.IsFalse(r2.done);
+            Assert.IsNull(r2.ex);
+
+            MyPoolRunnable r3 = new MyPoolRunnable(Q2, false);
+            Assert.IsFalse(r3.done);
+            Assert.IsNull(r3.ex);
+
+            p.Run(r1.run, r1.exception);
+            p.Run(r2.run, r2.exception);
+            try { p.Run(r3.run, r3.exception); } catch (Exception) { }
+
+            Thread.Sleep(Q1);
+            Assert.IsFalse(r1.done);
+            Assert.IsNull(r1.ex);
+
+            Assert.IsFalse(r2.done);
+            Assert.IsNull(r2.ex);
+
+            Assert.IsFalse(r3.done);
+            Assert.IsNull(r3.ex);
+
+            Thread.Sleep(Q3);
+            Assert.IsTrue(r1.done);
+            Assert.IsNull(r1.ex);
+
+            Assert.IsTrue(r2.done);
+            Assert.IsNull(r2.ex);
+
+            Assert.IsFalse(r3.done);
+            Assert.IsNull(r3.ex);
+        }
+    }
+
+    class MyPoolRunnable
+    {
+        public MyPoolRunnable( int delay, bool excp )
+        {
+            this.delay = delay;
+            this.excp = excp;
+        }
+
+        private readonly int delay;
+
+        private readonly bool excp;
+
+        public bool done;
+
+        public Exception ex;
+
+        public void run()
+        {
+            if (delay > 0)
+                Thread.Sleep(delay);
+            if (excp)
+                throw new Exception();
+            done = true;
+        }
+
+        public void exception( Exception e )
+        {
+            ex = e;
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestRemoteBase.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestRemoteBase.cs
new file mode 100644
index 0000000..6c8fdce
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestRemoteBase.cs
@@ -0,0 +1,289 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Transport;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+
+//using Etch.Support;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+
+    [TestFixture]
+    public class TestRemoteBase : RemoteBase
+    {
+        
+        public TestRemoteBase() : this(new MyDeliveryService(),new MyDefaultValueFactory())
+        {
+            
+        }
+
+        public TestRemoteBase(MyDeliveryService svc, MyDefaultValueFactory vf) : base(svc,vf)
+        {
+            this.svc = svc;
+        }
+        
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestRemoteBase" );
+        }
+
+        [SetUp]
+        public void Init()
+        {
+            svc.what = null;
+            svc.xmsg = null;
+            svc.xresponseType = null;
+            svc.xresponseField = null;
+            svc.xtimeout = 0;
+        }
+
+        private readonly MyDeliveryService svc;
+     /*   private static MyDeliveryService svc = new MyDeliveryService(); //declared static
+        //private static DefaultValueFactory vf = new DefaultValueFactory();//declared static
+        private static MyDefaultValueFactory vf = new MyDefaultValueFactory(); 
+        private RemoteBase rb = new RemoteBase(svc, vf); */
+    	private XType mt = new XType( "foo" );
+    	private XType rmt = new XType( "bar" );
+    	private Field rmf = new Field( "baz" );
+	
+	    [Test]
+	    public void NewMessage()
+	    {
+		    Message msg = _NewMessage( mt );
+		    msg.CheckType( mt );
+		   
+		    Assert.IsNull( svc.what );
+		    Assert.IsNull( svc.xmsg );
+		    Assert.IsNull( svc.xresponseType );
+		    Assert.IsNull( svc.xresponseField );
+		    Assert.AreEqual( 0, svc.xtimeout );
+	    }
+    	
+	    [Test]
+	    public void Send() 
+	    {
+
+		    Message msg = _NewMessage( mt );
+    		
+		    _Send( msg );
+		    Assert.IsTrue( svc.what.Equals(What.SEND));
+		    Assert.AreSame( svc.xmsg, msg );
+		    Assert.IsNull( svc.xresponseType );
+		    Assert.IsNull( svc.xresponseField );
+		    Assert.AreEqual( 0, svc.xtimeout );
+	    }
+    	
+        [Test]
+	    public void Call() 
+	    {
+		    Message msg = _NewMessage( mt );
+
+            rmt.ResponseField = rmf;
+            rmt.Timeout = 98;
+
+            Object result = _EndCall( _BeginCall( msg ), rmt );
+
+		    Assert.IsTrue( svc.what.Equals(What.CALL));
+		    Assert.AreSame( svc.xmsg, msg );
+		    Assert.AreSame( svc.xresponseType, rmt );
+		    Assert.AreSame( svc.xresponseField, rmf );
+		    Assert.AreEqual( svc.xtimeout, 98 );
+		    Assert.AreEqual( result, 23 );
+	    }
+    	
+	    public enum What { SEND, CALL, SHUTDOWN, BEGINCALL };
+    	
+	    public class MyDeliveryService : DeliveryService, MailboxManager
+	    {
+
+            public Enum what;
+            
+            public void Init()
+            {
+                what = null;
+            }
+
+		    public Message xmsg;
+		    public XType xresponseType;
+		    public Field xresponseField;
+		    public int xtimeout;
+            public Mailbox xmb;
+    		
+		    public void Send( Message msg ) 
+		    {
+			    Assert.IsNull( what );
+			    what = What.SEND;
+			    this.xmsg = msg;
+		    }
+
+            public Mailbox BeginCall( Message msg )
+            {
+                Init();
+                Assert.IsNull( what );
+                what = What.BEGINCALL;
+                this.xmsg = msg;
+                this.xmb = new PlainMailbox(this, 0L);
+                return this.xmb;
+            }
+
+            public Object EndCall( Mailbox mb, XType responseType ) 
+		    {
+                Assert.AreEqual( What.BEGINCALL, what );
+                Assert.AreEqual( xmb, mb );
+			    what = What.CALL;
+                xmb = null;
+			    this.xresponseType = responseType;
+                this.xresponseField = responseType.ResponseField;
+			    this.xtimeout = responseType.Timeout;
+			    return 23;
+		    }
+
+            public void TransportNotify( Object eventObj )
+            {
+                // ignore
+            }
+
+            public Object TransportQuery( Object query )
+            {
+                // ignore
+                return null;
+            }
+
+            public void TransportControl( Object control, Object value )
+            {
+                // ignore
+            }
+
+            public void Redeliver(Who sender, Message msg)
+            {
+                // ignore
+            }
+
+            public void Unregister(Mailbox mb)
+            {
+                // ignore
+            }
+
+
+            #region TransportMessage Members
+
+            public void TransportMessage(Who recipient, Message msg)
+            {
+                Assert.IsNull(what);
+                what = What.SEND;
+                this.xmsg = msg;
+               
+            }
+
+            #endregion
+
+            #region Transport<SessionMessage> Members
+
+
+            public void SetSession(SessionMessage session)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public SessionMessage GetSession()
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+
+            #region SessionMessage Members
+
+            public bool SessionMessage(Who sender, Message msg)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+
+            #region Session Members
+
+            public object SessionQuery(object query)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SessionControl(object control, object value)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SessionNotify(object eventObj)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+
+
+
+            #region MailboxManager Members
+
+
+            public Mailbox TransportCall(Who recipient, Message msg)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+        }
+
+        /// <summary>
+        /// A fake implementation of DefaultValueFactory for testing
+        /// </summary>
+        /// 
+	    public class MyDefaultValueFactory : DefaultValueFactory
+	    {
+		    private readonly static TypeMap types = new TypeMap();
+
+		    
+
+            private readonly static Class2TypeMap class2type = 
+                new Class2TypeMap();
+
+		    static MyDefaultValueFactory()
+		    {
+                DefaultValueFactory.Init( types, class2type );
+		    }
+
+		    /**
+		     * Constructs the ValueFactoryFake.
+		     */
+            public MyDefaultValueFactory() : base("none:",types, class2type)
+		    {
+		    
+		    }
+
+		   
+
+           
+	    }
+  }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestStubBase.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestStubBase.cs
new file mode 100644
index 0000000..f2e5770
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestStubBase.cs
@@ -0,0 +1,174 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Transport;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    [TestFixture]
+    public class TestStubBase
+    {
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestStubBase" );
+        }
+
+        public enum What 
+        { 
+            /** wanted message delivered */ UNWANTED 
+        };
+
+        [Test]
+        public void Nothing()
+        { }
+
+        //[Test] 
+        [ExpectedException("System.InvalidOperationException")]
+        public void Unwanted3()
+        {
+            Object obj = new Object();
+
+            DeliveryService src = new MyMessageSource();
+            StubBase sb = new StubBase( src, obj, null, null );
+
+            Who sender = new MyWho(); 
+            Message msg = new Message(null, null);
+
+            sb.SessionMessage(sender, msg);
+           Assert.Fail("delivery of unwanted message should fail");
+        }
+
+        //[Test]
+        [ExpectedException("System.InvalidOperationException")]
+        public void Unwanted4()
+        {
+            Object obj = new Object();
+
+            DeliveryService src = new MyMessageSource();
+            StubBase sb = new StubBase( src, obj, null, null );
+
+            Who sender = new MyWho(); 
+            Message msg = new Message(null, null);
+
+            sb.SessionMessage(sender, msg);
+            Assert.Fail("delivery of unwanted message should fail");
+        }
+
+        public class MyMessageSource : DeliveryService
+        {
+
+           
+
+            #region TransportMessage Members
+
+            public void TransportMessage(Who recipient, Message msg)
+            {
+                Assert.Fail("not needed");
+            }
+
+            #endregion
+
+            #region Transport<SessionMessage> Members
+
+            public object TransportQuery(object query)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void TransportControl(object control, object value)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void TransportNotify(object eventObj)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SetSession(SessionMessage session)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+
+            #region DeliveryService Members
+
+            public Mailbox BeginCall(Message msg)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public object EndCall(Mailbox mb, XType responseType)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+
+            #region SessionMessage Members
+
+            public bool SessionMessage(Who sender, Message msg)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+
+            #region Session Members
+
+            public object SessionQuery(object query)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SessionControl(object control, object value)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SessionNotify(object eventObj)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+
+            #region Transport<SessionMessage> Members
+
+
+            public SessionMessage GetSession()
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+        }
+    }
+
+    public class MyWho : Who
+    {
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestTodoManager.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestTodoManager.cs
new file mode 100644
index 0000000..d624f5d
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestTodoManager.cs
@@ -0,0 +1,209 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Threading;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    [TestFixture]
+    public class TestTodoManager
+    {
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestTodoManager" );
+        }
+
+        [SetUp]
+        public void Setup()
+        {
+            MyTodo.ResetGlobalId();
+        }
+
+        [Test]
+        [ExpectedException(typeof(Exception))]
+        public void TestManagerNotStarted()
+        {
+            TodoManager mgr = new TodoManager( 50, 10, 1, 5, 5000, 1 );
+            mgr.Add( new MyTodo() );
+        }
+
+        [Test]
+        [ExpectedException( typeof( Exception ) )]
+        public void TestShutDown()
+        {
+            TodoManager mgr = TodoManager.GetTodoManager();
+            mgr.Add( new MyTodo() );
+
+            TodoManager.ShutDown();
+            
+            // adding after shutting down should cause exception
+            mgr.Add( new MyTodo() );
+        }
+
+        [Test]
+        public void TestWorkersAndEntries()
+        {
+            TodoManager mgr = new TodoManager( 50, 10, 1, 5, 5000, 1 );
+            mgr.Start();
+
+            Assert.AreEqual( 0, mgr.NumEntries() );
+            Assert.AreEqual( 0, mgr.NumWorkers() );
+            
+            mgr.Add( new MyTodo() );
+
+            Assert.AreEqual( 1, mgr.NumEntries() );
+            Assert.AreEqual( 1, mgr.NumWorkers() );
+            
+            // experiment with a total of 50 entries.
+            for ( int i = 0; i < 49; i++ )
+            {
+                mgr.Add( new MyTodo() );
+            }
+
+            Assert.AreEqual( 50, MyTodo.LastIdGenerated() );
+            
+            WaitTillComplete( 4000 );
+            //Assert.AreEqual( 5, mgr.NumWorkers() );
+
+            
+            // test if all todo's were executed. 
+            Assert.AreEqual( 0, mgr.NumEntries() );
+
+            TodoManager.ShutDown();
+            
+        }
+
+        //[Test]
+        public void TestSeparateThreads()
+        {
+            TodoManager mgr = TodoManager.GetTodoManager();
+            TodoManager.GetTodoManager().Add( new MyTodo() );
+
+            // Start another thread to add items to the todomanager. 
+            ( new Thread( new ThreadStart( AddUsingDifferentThread ) ) ).Start();
+
+            // simple "lock"
+            while ( simpleLock != true )
+                ;
+
+            WaitTillComplete( 4000 );
+
+            TodoManager.ShutDown();
+        }
+
+        // Thread that adds independently to the queue. 
+        public void AddUsingDifferentThread()
+        {
+            TodoManager.GetTodoManager().Add( new MyTodo() );
+            
+            simpleLock = true;
+        }
+        private bool simpleLock = false;
+
+        /// <summary>
+        /// Wait until all Todos are run. 
+        /// </summary>
+        /// <param name="maxWait">Max time in milliseconds 
+        /// to wait</param>
+        private void WaitTillComplete( long maxWait )
+        {
+            DateTime now = DateTime.Now;
+
+            long nowTime = 0;
+            long endTime = nowTime + maxWait;
+
+            TimeSpan span;
+            long spanTime = 0;
+
+            while ( true && ( nowTime < endTime ) )
+            {
+                if ( MyTodo.TodosRemaining() == 0 )
+                    return;
+
+                span = DateTime.Now - now;
+                now = DateTime.Now;
+                spanTime = (long) span.TotalMilliseconds;
+                nowTime += spanTime;
+            }
+
+            throw new Exception( "Time exceeded" );
+        }
+
+        /// <summary>
+        /// "Todo" tasks put inside the TodoManager queue. 
+        /// </summary>
+        public class MyTodo : Todo
+        {
+            /// <summary>
+            /// unique id for every "todo" created
+            /// </summary>
+            private static int globalId = 0;
+            private static int lastRun = 0;
+            private int uniqueId = 0;
+
+            public MyTodo()
+            {
+                globalId++;
+                uniqueId = globalId;
+                lastRun++;
+            }
+
+            public static int LastIdGenerated()
+            {
+                return globalId;
+            }
+
+            /// <summary>
+            /// Reset the global id.
+            /// </summary>
+            public static void ResetGlobalId()
+            {
+                globalId = 0;
+                lastRun = 0;
+            }
+
+            /// <summary>
+            /// How many todos remain to be run
+            /// </summary>
+            /// <returns>number of todos remaining</returns>
+            public static int TodosRemaining()
+            {
+                return lastRun;
+            }
+
+            public void Doit( TodoManager mgr )
+            {
+                lastRun--;
+            }
+
+            public void Exception( TodoManager mgr, Exception e )
+            {
+                Console.WriteLine( "exception thrown by todo " + uniqueId );
+                Console.WriteLine( e.Message );
+                Console.WriteLine( e );
+            }
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestTypeValidator.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestTypeValidator.cs
new file mode 100644
index 0000000..cae6857
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestTypeValidator.cs
@@ -0,0 +1,115 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    [TestFixture]
+    public class TestTypeValidator
+    {
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestTypeValidator" );
+        }
+
+        [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+        public void TestValidate()
+        {
+            new MyTypeValidator( typeof( int ), typeof( int ), -1, "bzzt" );
+        }
+
+        [Test]
+        public void TestTypeValidator1()
+        {
+            MyTypeValidator v = new MyTypeValidator( typeof( int ), null, 0, "abc" );
+            Assert.AreEqual( typeof( int ), v.GetExpectedClass() );
+            Assert.AreEqual( 0, v.GetNDims() );
+            Assert.AreEqual( "abc", v.ToString() );
+        }
+
+        [Test]
+        public void TestTypeValidator2()
+        {
+            MyTypeValidator v = new MyTypeValidator( typeof(Boolean), null, 0, "def" );
+            Assert.AreEqual( typeof( Boolean ), v.GetExpectedClass() );
+		    Assert.AreEqual( 0, v.GetNDims() );
+		    Assert.AreEqual( "def", v.ToString() );
+        }
+
+        [Test]
+	    public void TestTypeValidator3()
+	    {
+		    MyTypeValidator v = new MyTypeValidator( null, typeof(int), 1, "ghi" );
+		    Assert.AreEqual( typeof(int[]), v.GetExpectedClass() );
+		    Assert.AreEqual( 1, v.GetNDims() );
+		    Assert.AreEqual( "ghi", v.ToString() );
+	    }
+
+        [Test]
+	    public void TestTypeValidator4()
+	    {
+		    MyTypeValidator v = new MyTypeValidator( null, typeof(Boolean), 1, "jkl" );
+		    Assert.AreEqual( typeof(Boolean[]), v.GetExpectedClass() );
+		    Assert.AreEqual( 1, v.GetNDims() );
+		    Assert.AreEqual( "jkl", v.ToString() );
+	    }
+
+        [Test]
+	    public void TestToString()
+	    {
+		    MyTypeValidator v = new MyTypeValidator( typeof(int), typeof(int), 0, "abc" );
+		    Assert.AreEqual( "abc", v.ToString() );
+    		
+		    v = new MyTypeValidator( typeof(int), typeof(int), 0, "def" );
+		    Assert.AreEqual( "def", v.ToString() );
+    		
+		    v = new MyTypeValidator( typeof(int), typeof(int), 0, "ghi" );
+		    Assert.AreEqual( "ghi", v.ToString() );
+	    }
+
+        [Test]
+	    public void TestSilly()
+	    {
+		  
+		    new MyTypeValidator( typeof(int), typeof(int), 0, "ghi" ).ElementValidator();
+	    }
+
+        public class MyTypeValidator : TypeValidator
+        {
+            public MyTypeValidator( Type scalarClass, Type arrayClass, int nDims,
+                String descr ) : base ( scalarClass, arrayClass, nDims, descr)
+            { }
+
+           
+
+            public override Validator ElementValidator()
+            {
+                // ignore
+                return null;
+            }
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_StructValue.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_StructValue.cs
new file mode 100644
index 0000000..c919afd
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_StructValue.cs
@@ -0,0 +1,232 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    [TestFixture]
+    public class TestValidator_StructValue
+    {
+        private readonly ValueFactory vf = new DummyValueFactory();
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write("TestValidator_StructValue");
+        }
+
+        private XType abc = new XType( "abc" );
+	
+	/** @  */
+	[Test]
+	public void constructor1()  
+	{
+		testconstructor( 0, "StructValue[abc(669497117),0]", typeof(StructValue));
+		testconstructor( 1, "StructValue[abc(669497117),1]", typeof(StructValue[]) );
+		testconstructor( 2, "StructValue[abc(669497117),2]", typeof(StructValue[][]) );
+		testconstructor( 3, "StructValue[abc(669497117),3]", typeof(StructValue[][][]) );
+		testconstructor( 4, "StructValue[abc(669497117),4]", typeof(StructValue[][][][]) );
+		testconstructor( 5, "StructValue[abc(669497117),5]", typeof(StructValue[][][][][]) );
+		testconstructor( 6, "StructValue[abc(669497117),6]", typeof(StructValue[][][][][][]) );
+		testconstructor( 7, "StructValue[abc(669497117),7]", typeof(StructValue[][][][][][][]) );
+		testconstructor( 8, "StructValue[abc(669497117),8]", typeof(StructValue[][][][][][][][]) );
+		testconstructor( 9, "StructValue[abc(669497117),9]", typeof(StructValue[][][][][][][][][]) );
+		Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testconstructor( int n, String descr, Type expectedClass )
+	{
+		Validator_StructValue v = Validator_StructValue.Get( abc, n );
+		Assert.AreEqual( n, v.GetNDims() );
+		Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		Assert.AreEqual( descr, v.ToString() );
+		Assert.AreEqual( abc, v.GetXType() );
+	}
+	
+	
+	[Test]  
+    [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	public void constructor2()  
+	{
+		Validator_StructValue.Get( abc, -1 );
+	}
+	
+	/** @  */
+	[Test]  
+    [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	public void constructor3()  
+	{
+		Validator_StructValue.Get( abc, Validator.MAX_NDIMS+1 );
+	}
+	
+	/** @  */
+	[Test]
+	public void elementvalidator1()  
+	{
+		testelementvalidator( 1, "StructValue[abc(669497117),0]", typeof(StructValue) );
+		testelementvalidator( 2, "StructValue[abc(669497117),1]", typeof(StructValue[]) );
+		testelementvalidator( 3, "StructValue[abc(669497117),2]", typeof(StructValue[][]) );
+		testelementvalidator( 4, "StructValue[abc(669497117),3]", typeof(StructValue[][][]) );
+		testelementvalidator( 5, "StructValue[abc(669497117),4]", typeof(StructValue[][][][]) );
+		testelementvalidator( 6, "StructValue[abc(669497117),5]", typeof(StructValue[][][][][]) );
+		testelementvalidator( 7, "StructValue[abc(669497117),6]", typeof(StructValue[][][][][][]) );
+		testelementvalidator( 8, "StructValue[abc(669497117),7]", typeof(StructValue[][][][][][][]) );
+		testelementvalidator( 9, "StructValue[abc(669497117),8]", typeof(StructValue[][][][][][][][]) );
+		Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testelementvalidator( int n, String descr, Type expectedClass )
+	{
+		Validator_StructValue v = (Validator_StructValue) Validator_StructValue.Get( abc, n ).ElementValidator();
+		Assert.AreEqual( n-1, v.GetNDims() );
+		Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		Assert.AreEqual( descr, v.ToString() );
+		Assert.AreEqual( abc, v.GetXType() );
+	}
+
+	
+	[Test]  
+    [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	public void elementvalidator2()  
+	{
+		Validator_StructValue.Get( abc, 0 ).ElementValidator();
+	}
+	
+	
+	[Test]
+	public void good_scalar()  
+	{
+        testgoodvalue(0, new StructValue(abc, vf));
+	}
+	
+	/** @  */
+	[Test]
+	public void good_array()  
+	{
+		testgoodvalue( 1,  new StructValue[] {} );
+		testgoodvalue( 2,  new StructValue[][] {} );
+		testgoodvalue( 3,  new StructValue[][][] {} );
+		testgoodvalue( 4,  new StructValue[][][][] {} );
+		testgoodvalue( 5,  new StructValue[][][][][] {} );
+		testgoodvalue( 6,  new StructValue[][][][][][] {} );
+		testgoodvalue( 7,  new StructValue[][][][][][][] {} );
+		testgoodvalue( 8,  new StructValue[][][][][][][][] {} );
+		testgoodvalue( 9,  new StructValue[][][][][][][][][] {} );
+		Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testgoodvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_StructValue.Get( abc, n );
+		Assert.IsTrue( v.Validate( value ) );
+		Assert.IsTrue( validateValueOk( v, value ) );
+	}
+	
+	/** @  */
+	[Test]
+	public void bad_scalar()  
+	{
+		testbadvalue( 0, null );
+		testbadvalue( 0, false );
+		testbadvalue( 0, true );
+		testbadvalue( 0, (byte) 1 );
+		testbadvalue( 0, (short) 2222 );
+		testbadvalue( 0, 33333333 );
+		testbadvalue( 0, 4444444444444444L );
+		testbadvalue( 0, 5.5f );
+		testbadvalue( 0, 6.6 );
+		testbadvalue( 0, "" );
+		testbadvalue( 0, "abc" );
+		testbadvalue( 0, new Object() );
+		testbadvalue( 0, new StructValue( new XType( "def" ), vf ) );
+		testbadvalue( 0, new DateTime() );
+
+		testbadvalue( 1, null );
+		testbadvalue( 1, false );
+		testbadvalue( 1, true );
+		testbadvalue( 1, (byte) 1 );
+		testbadvalue( 1, (short) 2222 );
+		testbadvalue( 1, 333333 );
+	    testbadvalue(1, 4444444444444444L);
+		testbadvalue( 1, 5.5f );
+		testbadvalue( 1, 6.6 );
+		testbadvalue( 1, "" );
+		testbadvalue( 1, "abc" );
+		testbadvalue( 1, new Object() );
+	//	testbadvalue( 1, new StructValue( abc ) );
+	    testbadvalue(1, new DateTime());
+	}
+	
+	/** @  */
+	[Test]
+	public void bad_array()  
+	{
+		testbadvalue( 0, new StructValue[] {} );
+		testbadvalue( 1, new StructValue[][] {} );
+		testbadvalue( 2, new StructValue[][][] {} );
+		testbadvalue( 3, new StructValue[][][][] {} );
+		testbadvalue( 4, new StructValue[][][][][] {} );
+		testbadvalue( 5, new StructValue[][][][][][] {} );
+		testbadvalue( 6, new StructValue[][][][][][][] {} );
+		testbadvalue( 7, new StructValue[][][][][][][][] {} );
+		testbadvalue( 8, new StructValue[][][][][][][][][] {} );
+		testbadvalue( 9, new StructValue[][][][][][][][][][] {} );
+		Assert.AreEqual( 9, Validator.MAX_NDIMS );
+
+		testbadvalue( 2, new StructValue[] {} );
+		testbadvalue( 3, new StructValue[][] {} );
+		testbadvalue( 4, new StructValue[][][] {} );
+		testbadvalue( 5, new StructValue[][][][] {} );
+		testbadvalue( 6, new StructValue[][][][][] {} );
+		testbadvalue( 7, new StructValue[][][][][][] {} );
+		testbadvalue( 8, new StructValue[][][][][][][] {} );
+		testbadvalue( 9, new StructValue[][][][][][][][] {} );
+		Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	}
+
+	private void testbadvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_StructValue.Get( abc, n );
+		Assert.IsFalse( v.Validate( value ) );
+		Assert.IsFalse( validateValueOk( v, value ) );
+	}
+
+	private bool validateValueOk( Validator v, Object value )
+	{
+		try
+		{
+			Object x = v.ValidateValue( value );
+			Assert.AreEqual( value, x );
+			return true;
+		}
+		catch ( Exception  )
+		{
+          
+			return false;
+		}
+	}
+
+
+
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_boolean.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_boolean.cs
new file mode 100644
index 0000000..c69f6b1
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_boolean.cs
@@ -0,0 +1,225 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    [TestFixture]
+    public class TestValidator_Boolean
+    {
+        private readonly ValueFactory vf = new DummyValueFactory();
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestValidator_Boolean" );
+        }
+
+        [Test]
+	    public void Constructor1()  
+	    {
+		    TestConstructor(0,"boolean[0]",typeof(Boolean));
+            TestConstructor(1, "boolean[1]", typeof(Boolean[]));
+            TestConstructor(2, "boolean[2]", typeof(Boolean[][]));
+            TestConstructor(3, "boolean[3]", typeof(Boolean[][][]));
+            TestConstructor(4, "boolean[4]", typeof(Boolean[][][][]));
+            TestConstructor(5, "boolean[5]", typeof(Boolean[][][][][]));
+            TestConstructor(6, "boolean[6]", typeof(Boolean[][][][][][]));
+            TestConstructor(7, "boolean[7]", typeof(Boolean[][][][][][][]));
+            TestConstructor(8, "boolean[8]", typeof(Boolean[][][][][][][][]));
+            TestConstructor(9, "boolean[9]", typeof(Boolean[][][][][][][][][]));
+            Assert.AreEqual(9,Validator.MAX_NDIMS);
+	    }
+
+        private void TestConstructor(int n, string descr, Type expectedClass)
+        {
+            Validator_boolean v = Validator_boolean.Get(n);
+            Assert.AreEqual(n, v.GetNDims());
+            Assert.AreSame(expectedClass,v.GetExpectedClass());
+            Assert.AreEqual(descr, v.ToString());            
+        }
+ 
+	    [Test]
+        [ExpectedException(typeof(ArgumentOutOfRangeException))]
+	    public void Constructor2()
+	    {		
+		    Validator_boolean.Get( -1 );
+	    }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentOutOfRangeException))]
+        public void Constructor3()
+        {
+            Validator_boolean.Get(Validator.MAX_NDIMS + 1);
+        }
+
+        [Test]
+        public void ElementValidator1() 
+	    {
+		    TestElementValidator( 1, "boolean[0]", typeof(Boolean)  );
+		    TestElementValidator( 2, "boolean[1]", typeof(Boolean[])  );
+		    TestElementValidator( 3, "boolean[2]", typeof(Boolean[][])  );
+		    TestElementValidator( 4, "boolean[3]", typeof(Boolean[][][])  );
+		    TestElementValidator( 5, "boolean[4]", typeof(Boolean[][][][])  );
+		    TestElementValidator( 6, "boolean[5]", typeof(Boolean[][][][][])  );
+		    TestElementValidator( 7, "boolean[6]", typeof(Boolean[][][][][][])  );
+		    TestElementValidator( 8, "boolean[7]", typeof(Boolean[][][][][][][])  );
+		    TestElementValidator( 9, "boolean[8]", typeof(Boolean[][][][][][][][])  );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+
+        private void TestElementValidator( int n, String descr, Type expectedClass )
+	    {
+		    Validator_boolean v = (Validator_boolean) Validator_boolean.Get( n ).ElementValidator();
+		    Assert.AreEqual( n-1, v.GetNDims() );
+		    Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		    Assert.AreEqual( descr, v.ToString() );
+	    }
+
+
+        [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void ElementValidator2  ()
+	    {		
+		    Validator_boolean.Get( 0 ).ElementValidator();
+        }
+
+       
+	    [Test]
+	    public void Good_Scalar() 
+	    {
+		    TestGoodValue( 0,  false );
+		    TestGoodValue( 0, true );
+	    }
+	
+	
+	    [Test]
+	    public void Good_Array() 
+	    {
+		    TestGoodValue( 1, new Boolean[] {} );
+		    TestGoodValue( 2,  new Boolean[][] {} );
+		    TestGoodValue( 3,  new Boolean[][][] {} );
+		    TestGoodValue( 4,  new Boolean[][][][] {} );
+		    TestGoodValue( 5,  new Boolean[][][][][] {} );
+		    TestGoodValue( 6,  new Boolean[][][][][][] {} );
+		    TestGoodValue( 7,  new Boolean[][][][][][][] {} );
+		    TestGoodValue( 8,  new Boolean[][][][][][][][] {} );
+		    TestGoodValue( 9,  new Boolean[][][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+	
+	    private void TestGoodValue( int n,  Object value )
+	    {
+		    TypeValidator v = Validator_boolean.Get( n );
+		   
+		    Assert.IsTrue( v.Validate( value ) );
+		    Assert.IsTrue( ValidateValueOk( v, value ) );
+	    }
+	
+	
+	    [Test]
+	    public void bad_scalar() 
+	    {
+		    TestBadValue( 0, null );
+		    TestBadValue( 0, (byte) 1 );
+		    TestBadValue( 0, (short) 2222 );
+		    TestBadValue( 0, 33333333 );
+		    TestBadValue( 0, 4444444444444444L );
+		    TestBadValue( 0, 5.5f );
+		    TestBadValue( 0, 6.6 );
+		    TestBadValue( 0, "" );
+		    TestBadValue( 0, "abc" );
+		    TestBadValue( 0, new Object() );
+            TestBadValue(0, new StructValue(new XType("abc"), vf));
+		    TestBadValue( 0, new DateTime() );
+
+		    TestBadValue( 1, null );
+		    TestBadValue( 1, false );
+		    TestBadValue( 1, true );
+		    TestBadValue( 1, (byte) 1 );
+		    TestBadValue( 1, (short) 2222 );
+		    TestBadValue( 1, 33333333 );
+		    TestBadValue( 1, 4444444444444444L );
+		    TestBadValue( 1, 5.5f );
+		    TestBadValue( 1, 6.6 );
+		    TestBadValue( 1, "" );
+		    TestBadValue( 1, "abc" );
+		    TestBadValue( 1, new Object() );
+            TestBadValue(1, new StructValue(new XType("abc"), vf));
+		    TestBadValue( 1, new DateTime() );
+	    }
+	
+	
+	    [Test]
+	    public void bad_array() 
+	    {
+		    TestBadValue( 0, new Boolean[] {} );
+		    TestBadValue( 1, new Boolean[][] {} );
+		    TestBadValue( 2, new Boolean[][][] {} );
+		    TestBadValue( 3, new Boolean[][][][] {} );
+		    TestBadValue( 4, new Boolean[][][][][] {} );
+		    TestBadValue( 5, new Boolean[][][][][][] {} );
+		    TestBadValue( 6, new Boolean[][][][][][][] {} );
+		    TestBadValue( 7, new Boolean[][][][][][][][] {} );
+		    TestBadValue( 8, new Boolean[][][][][][][][][] {} );
+		    TestBadValue( 9, new Boolean[][][][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+
+		    TestBadValue( 2, new Boolean[] {} );
+		    TestBadValue( 3, new Boolean[][] {} );
+		    TestBadValue( 4, new Boolean[][][] {} );
+		    TestBadValue( 5, new Boolean[][][][] {} );
+		    TestBadValue( 6, new Boolean[][][][][] {} );
+		    TestBadValue( 7, new Boolean[][][][][][] {} );
+		    TestBadValue( 8, new Boolean[][][][][][][] {} );
+		    TestBadValue( 9, new Boolean[][][][][][][][] {} );
+            Assert.AreEqual(9, Validator.MAX_NDIMS);
+	    }
+
+	    private void TestBadValue( int n, Object value )
+	    {
+		    TypeValidator v = Validator_boolean.Get( n );
+		    Assert.IsFalse( v.Validate( value ) );
+		    Assert.IsFalse( ValidateValueOk( v, value ) );
+	    }
+
+	    private bool ValidateValueOk( Validator v, Object value )
+	    {
+		    try
+		    {
+			    Object x = v.ValidateValue( value );
+			    Assert.AreEqual( value, x );
+			    return true;
+		    }
+		    catch ( Exception )
+		    {
+               
+                return false;
+		    }
+	    }
+
+
+
+
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_byte.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_byte.cs
new file mode 100644
index 0000000..c00597f
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_byte.cs
@@ -0,0 +1,275 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    [TestFixture]
+    public class TestValidator_byte
+    {
+        private readonly ValueFactory vf = new DummyValueFactory();
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestValidator_byte" );
+        }
+
+        [Test]
+        public void Contructor1()
+        {
+      
+            testconstructor( 0, "byte[0]", typeof(sbyte) );
+		    testconstructor( 1, "byte[1]", typeof( sbyte[]) );
+		    testconstructor( 2, "byte[2]", typeof( sbyte[][] ) );
+		    testconstructor( 3, "byte[3]", typeof( sbyte[][][] ) );
+		    testconstructor( 4, "byte[4]", typeof( sbyte[][][][] ) );
+		    testconstructor( 5, "byte[5]", typeof( sbyte[][][][][] ) );
+		    testconstructor( 6, "byte[6]", typeof( sbyte[][][][][][] ) );
+		    testconstructor( 7, "byte[7]", typeof( sbyte[][][][][][][] ) );
+		    testconstructor( 8, "byte[8]", typeof( sbyte[][][][][][][][] ) );
+            testconstructor(9, "byte[9]", typeof(sbyte[][][][][][][][][]));
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+            
+        }
+
+        private void testconstructor( int n, String descr, Type expectedClass )
+	    {
+		    TypeValidator v = Validator_byte.Get( n );
+		    Assert.AreEqual( n, v.GetNDims() );
+		    Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		    Assert.AreEqual( descr, v.ToString() );
+	    }
+
+       
+	    [Test] 
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void constructor2() 
+	    {
+		    Validator_byte.Get( -1 );
+	    }
+	
+	
+	    [Test] 
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void constructor3() 
+	    {
+		    Validator_byte.Get( Validator.MAX_NDIMS+1 );
+	    }
+	
+	
+	    [Test]
+	    public void elementvalidator1() 
+	    {
+		    testelementvalidator( 1, "byte[0]", typeof(sbyte) );
+		    testelementvalidator( 2, "byte[1]", typeof( sbyte[]) );
+		    testelementvalidator( 3, "byte[2]", typeof( sbyte[][] ) );
+		    testelementvalidator( 4, "byte[3]", typeof( sbyte[][][] ) );
+		    testelementvalidator( 5, "byte[4]", typeof( sbyte[][][][] ) );
+		    testelementvalidator( 6, "byte[5]", typeof( sbyte[][][][][] ) );
+		    testelementvalidator( 7, "byte[6]", typeof( sbyte[][][][][][] ) );
+		    testelementvalidator( 8, "byte[7]", typeof( sbyte[][][][][][][] ) );
+		    testelementvalidator( 9, "byte[8]", typeof( sbyte[][][][][][][][] ) );
+           
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+	
+	    private void testelementvalidator( int n, String descr, Type expectedClass )
+	    {
+		    TypeValidator v = (TypeValidator) Validator_byte.Get( n ).ElementValidator();
+		    Assert.AreEqual( n-1, v.GetNDims() );
+		    Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		    Assert.AreEqual( descr, v.ToString() );
+	    }
+
+	
+	    [Test] 
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void elementvalidator2() 
+	    {
+		    Validator_byte.Get( 0 ).ElementValidator();
+	    }
+	
+	
+	    [Test]
+	    public void good_scalar() 
+	    {
+		    // BYTES
+    		
+		    testgoodvalue( 0,  (sbyte) 0 );
+    		
+		    testgoodvalue( 0,  (sbyte) 1 );
+		    testgoodvalue( 0,  (sbyte) 64 );
+		    testgoodvalue( 0,  SByte.MaxValue );
+    		
+		    testgoodvalue( 0,  (sbyte) -1 );
+		    testgoodvalue( 0,  (sbyte) -64 );
+		    testgoodvalue( 0,  SByte.MinValue );
+
+		    // SHORTS
+    		
+		    testgoodvalue( 0,  (short) 0 );
+    		
+		    testgoodvalue( 0,  (short) 1 );
+		    testgoodvalue( 0,  (short) 64 );
+		    testgoodvalue( 0,  (short) SByte.MaxValue );
+    		
+		    testgoodvalue( 0,  (short) -1 );
+		    testgoodvalue( 0,  (short) -64 );
+		    testgoodvalue( 0,  (short) SByte.MinValue );
+
+		    // INTS
+    		
+		    testgoodvalue( 0,  0 );
+    		
+		    testgoodvalue( 0,  1 );
+		    testgoodvalue( 0,  64 );
+		    testgoodvalue( 0,  (int) SByte.MaxValue );
+    		
+		    testgoodvalue( 0,  -1 );
+		    testgoodvalue( 0,  -64 );
+		    testgoodvalue( 0,  (int) SByte.MinValue );
+
+		    // LONGS
+    		
+		    testgoodvalue( 0,  (long) 0 );
+    		
+		    testgoodvalue( 0,  (long) 1 );
+		    testgoodvalue( 0,  (long) 64 );
+		    testgoodvalue( 0,  (long) SByte.MaxValue );
+    		
+		    testgoodvalue( 0,  (long) -1 );
+		    testgoodvalue( 0,  (long) -64 );
+		    testgoodvalue( 0,  (long) SByte.MinValue );
+	    }
+	
+	
+	    [Test]
+	    public void good_array() 
+	    {
+		    testgoodvalue( 1,new sbyte[] {} );
+		    testgoodvalue( 2,  new sbyte[][] {} );
+		    testgoodvalue( 3,  new sbyte[][][] {} );
+		    testgoodvalue( 4,  new sbyte[][][][] {} );
+		    testgoodvalue( 5,  new sbyte[][][][][] {} );
+		    testgoodvalue( 6,  new sbyte[][][][][][] {} );
+		    testgoodvalue( 7,  new sbyte[][][][][][][] {} );
+		    testgoodvalue( 8,  new sbyte[][][][][][][][] {} );
+		    testgoodvalue( 9,  new sbyte[][][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+	
+	    private void testgoodvalue( int n,Object value )
+	    {
+		    TypeValidator v = Validator_byte.Get( n );
+		    Assert.IsTrue( v.Validate( value ) );
+		    Assert.IsTrue( ValidateValueOk( v, value ) );
+	    }
+	
+	    
+	    [Test]
+	    public void bad_scalar() 
+	    {
+		    testbadvalue( 0, null );
+		    testbadvalue( 0, false );
+		    testbadvalue( 0, true );
+    //		testbadvalue( 0, (byte) 1 ); good!
+		    testbadvalue( 0, (short) 2222 );
+		    testbadvalue( 0, 33333333 );
+		    testbadvalue( 0, 4444444444444444L );
+		    testbadvalue( 0, 5.5f );
+		    testbadvalue( 0, 6.6 );
+		    testbadvalue( 0, "" );
+		    testbadvalue( 0, "abc" );
+		    testbadvalue( 0, new Object() );
+            testbadvalue(0, new StructValue(new XType("abc"), vf));
+		    testbadvalue( 0, new DateTime() );
+
+		    testbadvalue( 1, null );
+		    testbadvalue( 1, false );
+		    testbadvalue( 1, true );
+		    testbadvalue( 1, (byte) 1 );
+		    testbadvalue( 1, (short) 2222 );
+		    testbadvalue( 1, 333333 );
+		    testbadvalue( 1, 4444444444444444L );
+		    testbadvalue( 1, 5.5f );
+		    testbadvalue( 1, 6.6 );
+		    testbadvalue( 1, "" );
+		    testbadvalue( 1, "abc" );
+		    testbadvalue( 1, new Object() );
+            testbadvalue(1, new StructValue(new XType("abc"), vf));
+		    testbadvalue( 1, new DateTime() );
+	    }
+	
+	
+	    [Test]
+	    public void bad_array() 
+	    {
+		    testbadvalue( 0, new sbyte[] {} );
+		    testbadvalue( 1, new sbyte[][] {} );
+		    testbadvalue( 2, new sbyte[][][] {} );
+		    testbadvalue( 3, new sbyte[][][][] {} );
+		    testbadvalue( 4, new sbyte[][][][][] {} );
+		    testbadvalue( 5, new sbyte[][][][][][] {} );
+		    testbadvalue( 6, new sbyte[][][][][][][] {} );
+		    testbadvalue( 7, new sbyte[][][][][][][][] {} );
+		    testbadvalue( 8, new sbyte[][][][][][][][][] {} );
+		    testbadvalue( 9, new sbyte[][][][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+
+		    testbadvalue( 2, new sbyte[] {} );
+		    testbadvalue( 3, new sbyte[][] {} );
+		    testbadvalue( 4, new sbyte[][][] {} );
+		    testbadvalue( 5, new sbyte[][][][] {} );
+		    testbadvalue( 6, new sbyte[][][][][] {} );
+		    testbadvalue( 7, new sbyte[][][][][][] {} );
+		    testbadvalue( 8, new sbyte[][][][][][][] {} );
+		    testbadvalue( 9, new sbyte[][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+
+	    private void testbadvalue( int n, Object value )
+	    {
+	        TypeValidator v = Validator_byte.Get(n);
+		    Assert.IsFalse( v.Validate( value ) );
+            Assert.IsFalse(ValidateValueOk(v, value));
+	    }
+
+	    private bool ValidateValueOk( Validator v, Object value )
+	    {
+		    try
+		    {
+			    Object x = v.ValidateValue( value );
+			    Assert.AreEqual( value, x );
+			    return true;
+		    }
+		    catch ( Exception)
+		    {
+               
+                return false;
+		    }
+	    }
+
+      
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_double.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_double.cs
new file mode 100644
index 0000000..6e8130c
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_double.cs
@@ -0,0 +1,229 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    [TestFixture]
+    public class TestValidator_double
+    {
+        private readonly ValueFactory vf = new DummyValueFactory();
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestValidator_double" );
+        }
+
+        [Test]
+	    public void constructor1() 
+	    {
+		    testconstructor( 0, "double[0]", typeof(double) );
+		    testconstructor( 1, "double[1]", typeof(double[]) );
+		    testconstructor( 2, "double[2]", typeof(double[][]) );
+		    testconstructor( 3, "double[3]", typeof(double[][][]) );
+		    testconstructor( 4, "double[4]", typeof(double[][][][]) );
+		    testconstructor( 5, "double[5]", typeof(double[][][][][]) );
+		    testconstructor( 6, "double[6]", typeof(double[][][][][][]) );
+		    testconstructor( 7, "double[7]", typeof(double[][][][][][][]) );
+		    testconstructor( 8, "double[8]", typeof(double[][][][][][][][]) );
+		    testconstructor( 9, "double[9]", typeof(double[][][][][][][][][]) );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+	
+	    private void testconstructor( int n, String descr, Type expectedClass )
+	    {
+		    TypeValidator v = Validator_double.Get( n );
+		    Assert.AreEqual( n, v.GetNDims() );
+		    Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		    Assert.AreEqual( descr, v.ToString() );
+	    }
+	
+	
+	    [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void constructor2() 
+	    {
+		    Validator_double.Get( -1 );
+	    }
+	
+	    [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void constructor3() 
+	    {
+		    Validator_double.Get( Validator.MAX_NDIMS+1 );
+	    }
+	
+	
+	    [Test]
+	    public void ElementValidator1() 
+	    {
+		    testelementvalidator( 1, "double[0]", typeof(double) );
+		    testelementvalidator( 2, "double[1]", typeof(double[]) );
+		    testelementvalidator( 3, "double[2]", typeof(double[][]) );
+		    testelementvalidator( 4, "double[3]", typeof(double[][][]) );
+		    testelementvalidator( 5, "double[4]", typeof(double[][][][]) );
+		    testelementvalidator( 6, "double[5]", typeof(double[][][][][]) );
+		    testelementvalidator( 7, "double[6]", typeof(double[][][][][][]) );
+		    testelementvalidator( 8, "double[7]", typeof(double[][][][][][][]) );
+		    testelementvalidator( 9, "double[8]", typeof(double[][][][][][][][]) );
+
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+	
+	    private void testelementvalidator( int n, String descr, Type expectedClass )
+	    {
+		    TypeValidator v = (TypeValidator) Validator_double.Get( n ).ElementValidator();
+		    Assert.AreEqual( n-1, v.GetNDims() );
+		    Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		    Assert.AreEqual( descr, v.ToString() );
+	    }
+
+	
+	    [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void elementvalidator2() 
+	    {
+		    Validator_double.Get( 0 ).ElementValidator();
+	    }
+	
+	
+	    [Test]
+	    public void good_scalar() 
+	    {
+		    testgoodvalue( 0,  0.0 );
+		    testgoodvalue( 0,  1.1 );
+		    testgoodvalue( 0,  -1.1 );
+	    }
+	
+	
+	    [Test]
+	    public void good_array() 
+	    {
+		    testgoodvalue( 1,  new double[] {} );
+		    testgoodvalue( 2,  new double[][] {} );
+		    testgoodvalue( 3,  new double[][][] {} );
+		    testgoodvalue( 4,  new double[][][][] {} );
+		    testgoodvalue( 5,  new double[][][][][] {} );
+		    testgoodvalue( 6,  new double[][][][][][] {} );
+		    testgoodvalue( 7,  new double[][][][][][][] {} );
+		    testgoodvalue( 8,  new double[][][][][][][][] {} );
+		    testgoodvalue( 9,  new double[][][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+	
+	    private void testgoodvalue( int n, Object value )
+	    {
+		    TypeValidator v = Validator_double.Get( n );
+		   
+		    Assert.IsTrue( v.Validate( value ) );
+		    Assert.IsTrue( ValidateValueOk( v, value ) );
+	    }
+	
+	
+	    [Test]
+	    public void bad_scalar() 
+	    {
+		    testbadvalue( 0, null );
+		    testbadvalue( 0, false );
+		    testbadvalue( 0, true );
+		    testbadvalue( 0, (byte) 1 );
+		    testbadvalue( 0, (short) 2222 );
+		    testbadvalue( 0, 33333333 );
+		    testbadvalue( 0, 4444444444444444L );
+		    testbadvalue( 0, 5.5f );
+    //		testbadvalue( 0, 6.6 ); good!
+		    testbadvalue( 0, "" );
+		    testbadvalue( 0, "abc" );
+		    testbadvalue( 0, new Object() );
+            testbadvalue(0, new StructValue(new XType("abc"), vf));
+		    testbadvalue( 0, new DateTime() );
+
+		    testbadvalue( 1, null );
+		    testbadvalue( 1, false );
+		    testbadvalue( 1, true );
+		    testbadvalue( 1, (byte) 1 );
+		    testbadvalue( 1, (short) 2222 );
+		    testbadvalue( 1, 333333 );
+		    testbadvalue( 1, 4444444444444444L );
+		    testbadvalue( 1, 5.5f );
+		    testbadvalue( 1, 6.6 );
+		    testbadvalue( 1, "" );
+		    testbadvalue( 1, "abc" );
+		    testbadvalue( 1, new Object() );
+            testbadvalue(1, new StructValue(new XType("abc"), vf));
+		    testbadvalue( 1, new DateTime() );
+	    }
+	
+	
+	    [Test]
+	    public void bad_array() 
+	    {
+		    testbadvalue( 0, new double[] {} );
+		    testbadvalue( 1, new double[][] {} );
+		    testbadvalue( 2, new double[][][] {} );
+		    testbadvalue( 3, new double[][][][] {} );
+		    testbadvalue( 4, new double[][][][][] {} );
+		    testbadvalue( 5, new double[][][][][][] {} );
+		    testbadvalue( 6, new double[][][][][][][] {} );
+		    testbadvalue( 7, new double[][][][][][][][] {} );
+		    testbadvalue( 8, new double[][][][][][][][][] {} );
+		    testbadvalue( 9, new double[][][][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+
+		    testbadvalue( 2, new double[] {} );
+		    testbadvalue( 3, new double[][] {} );
+		    testbadvalue( 4, new double[][][] {} );
+		    testbadvalue( 5, new double[][][][] {} );
+		    testbadvalue( 6, new double[][][][][] {} );
+		    testbadvalue( 7, new double[][][][][][] {} );
+		    testbadvalue( 8, new double[][][][][][][] {} );
+		    testbadvalue( 9, new double[][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+
+	    private void testbadvalue( int n, Object value )
+	    {
+		    TypeValidator v = Validator_double.Get( n );
+		    Assert.IsFalse( v.Validate( value ) );
+            Assert.IsFalse(ValidateValueOk(v, value));
+	    }
+
+	    private bool ValidateValueOk( Validator v, Object value )
+	    {
+		    try
+		    {
+			    Object x = v.ValidateValue( value );
+			    Assert.AreEqual( value, x );
+			    return true;
+		    }
+		    catch ( Exception)
+		    {
+               
+			    return false;
+		    }
+	    }
+
+        
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_float.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_float.cs
new file mode 100644
index 0000000..89b78a0
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_float.cs
@@ -0,0 +1,230 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+        [TestFixture]
+        public class TestValidator_float
+        {
+            private readonly ValueFactory vf = new DummyValueFactory();
+
+            [TestFixtureSetUp]
+            public void First()
+            {
+                Console.WriteLine();
+                Console.Write( "TestValidator_float" );
+            }
+
+        [Test]
+	    public void constructor1() 
+	    {
+		    testconstructor( 0, "float[0]", typeof(float) );
+		    testconstructor( 1, "float[1]", typeof(float[]) );
+		    testconstructor( 2, "float[2]", typeof(float[][]));
+		    testconstructor( 3, "float[3]", typeof(float[][][]) );
+		    testconstructor( 4, "float[4]", typeof(float[][][][]) );
+		    testconstructor( 5, "float[5]", typeof(float[][][][][]) );
+		    testconstructor( 6, "float[6]", typeof(float[][][][][][]) );
+		    testconstructor( 7, "float[7]", typeof(float[][][][][][][]) );
+		    testconstructor( 8, "float[8]", typeof(float[][][][][][][][]));
+		    testconstructor( 9, "float[9]", typeof(float[][][][][][][][][]) );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+    	
+	    private void testconstructor( int n, String descr, Type expectedClass )
+	    {
+		    TypeValidator v = Validator_float.Get( n );
+		    Assert.AreEqual( n, v.GetNDims() );
+		    Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		    Assert.AreEqual( descr, v.ToString() );
+	    }
+    	
+    	
+	    [Test]  
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void constructor2() 
+	    {
+		    Validator_float.Get( -1 );
+	    }
+    	
+	    /** @ */
+	    [Test]  
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void constructor3() 
+	    {
+		    Validator_float.Get( Validator.MAX_NDIMS+1 );
+	    }
+    	
+	    /** @ */
+	    [Test]
+	    public void elementvalidator1() 
+	    {
+            testelementvalidator( 1, "float[0]", typeof(float) );
+		    testelementvalidator( 2, "float[1]", typeof(float[]) );
+		    testelementvalidator( 3, "float[2]", typeof(float[][]));
+		    testelementvalidator( 4, "float[3]", typeof(float[][][]) );
+		    testelementvalidator( 5, "float[4]", typeof(float[][][][]) );
+		    testelementvalidator( 6, "float[5]", typeof(float[][][][][]) );
+		    testelementvalidator( 7, "float[6]", typeof(float[][][][][][]) );
+		    testelementvalidator( 8, "float[7]", typeof(float[][][][][][][]) );
+		    testelementvalidator( 9, "float[8]", typeof(float[][][][][][][][]));
+            Assert.AreEqual( 9, Validator.MAX_NDIMS );
+    		
+    		
+	    }
+    	
+	    private void testelementvalidator( int n, String descr, Type expectedClass )
+	    {
+		    TypeValidator v = (TypeValidator) Validator_float.Get( n ).ElementValidator();
+		    Assert.AreEqual( n-1, v.GetNDims() );
+		    Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		    Assert.AreEqual( descr, v.ToString() );
+	    }
+
+    	
+	    [Test]  
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void elementvalidator2() 
+	    {
+		    Validator_float.Get( 0 ).ElementValidator();
+	    }
+    	
+	    /** @ */
+	    [Test]
+	    public void good_scalar() 
+	    {
+		    testgoodvalue( 0,0.0f );
+		    testgoodvalue( 0,1.1f );
+		    testgoodvalue( 0, -1.1f );
+	    }
+    	
+	    /** @ */
+	    [Test]
+	    public void good_array() 
+	    {
+		    testgoodvalue( 1,  new float[] {} );
+		    testgoodvalue( 2,  new float[][] {} );
+		    testgoodvalue( 3,  new float[][][] {} );
+		    testgoodvalue( 4,  new float[][][][] {} );
+		    testgoodvalue( 5,  new float[][][][][] {} );
+		    testgoodvalue( 6,  new float[][][][][][] {} );
+		    testgoodvalue( 7,  new float[][][][][][][] {} );
+		    testgoodvalue( 8,  new float[][][][][][][][] {} );
+		    testgoodvalue( 9,  new float[][][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+    	
+	    private void testgoodvalue( int n,  Object value )
+	    {
+		    TypeValidator v = Validator_float.Get( n );
+		    Assert.IsTrue( v.Validate( value ) );
+		    Assert.IsTrue( validateValueOk( v, value ) );
+	    }
+    	
+	    /** @ */
+	    [Test]
+	    public void bad_scalar() 
+	    {
+		    testbadvalue( 0, null );
+		    testbadvalue( 0, false );
+		    testbadvalue( 0, true );
+		    testbadvalue( 0, (byte) 1 );
+		    testbadvalue( 0, (short) 2222 );
+		    testbadvalue( 0, 33333333 );
+		    testbadvalue( 0, 4444444444444444L );
+    //		testbadvalue( 0, 5.5f ); good!
+		    testbadvalue( 0, 6.6 );
+		    testbadvalue( 0, "" );
+		    testbadvalue( 0, "abc" );
+		    testbadvalue( 0, new Object() );
+            testbadvalue(0, new StructValue(new XType("abc"), vf));
+		    testbadvalue( 0, new DateTime() );
+
+		    testbadvalue( 1, null );
+		    testbadvalue( 1, false );
+		    testbadvalue( 1, true );
+		    testbadvalue( 1, (byte) 1 );
+		    testbadvalue( 1, (short) 2222 );
+		    testbadvalue( 1, 333333 );
+		    testbadvalue( 1, 4444444444444444L );
+		    testbadvalue( 1, 5.5f );
+		    testbadvalue( 1, 6.6 );
+		    testbadvalue( 1, "" );
+		    testbadvalue( 1, "abc" );
+		    testbadvalue( 1, new Object() );
+            testbadvalue(1, new StructValue(new XType("abc"), vf));
+		    testbadvalue( 1, new DateTime() );
+	    }
+    	
+	    /** @ */
+	    [Test]
+	    public void bad_array() 
+	    {
+		    testbadvalue( 0, new float[] {} );
+		    testbadvalue( 1, new float[][] {} );
+		    testbadvalue( 2, new float[][][] {} );
+		    testbadvalue( 3, new float[][][][] {} );
+		    testbadvalue( 4, new float[][][][][] {} );
+		    testbadvalue( 5, new float[][][][][][] {} );
+		    testbadvalue( 6, new float[][][][][][][] {} );
+		    testbadvalue( 7, new float[][][][][][][][] {} );
+		    testbadvalue( 8, new float[][][][][][][][][] {} );
+		    testbadvalue( 9, new float[][][][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+
+		    testbadvalue( 2, new float[] {} );
+		    testbadvalue( 3, new float[][] {} );
+		    testbadvalue( 4, new float[][][] {} );
+		    testbadvalue( 5, new float[][][][] {} );
+		    testbadvalue( 6, new float[][][][][] {} );
+		    testbadvalue( 7, new float[][][][][][] {} );
+		    testbadvalue( 8, new float[][][][][][][] {} );
+		    testbadvalue( 9, new float[][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+
+	    private void testbadvalue( int n, Object value )
+	    {
+		    TypeValidator v = Validator_float.Get( n );
+		    Assert.IsFalse( v.Validate( value ) );
+		    Assert.IsFalse( validateValueOk( v, value ) );
+	    }
+
+	    private bool validateValueOk( Validator v, Object value )
+	    {
+		    try
+		    {
+			    Object x = v.ValidateValue( value );
+			    Assert.AreEqual( value, x );
+			    return true;
+		    }
+		    catch ( Exception)
+		    {
+			   
+                return false;
+		    }
+	    }
+
+       
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_int.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_int.cs
new file mode 100644
index 0000000..9d99489
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_int.cs
@@ -0,0 +1,288 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+        [TestFixture]
+        public class TestValidator_int
+        {
+            private readonly ValueFactory vf = new DummyValueFactory();
+
+            [TestFixtureSetUp]
+            public void First()
+            {
+                Console.WriteLine();
+                Console.Write( "TestValidator_int" );
+            }
+
+        [Test]
+	    public void constructor1()  
+	    {
+		    testconstructor( 0, "int[0]", typeof(int) );
+		    testconstructor( 1, "int[1]", typeof(int[]) );
+		    testconstructor( 2, "int[2]", typeof(int[][]) );
+		    testconstructor( 3, "int[3]", typeof(int[][][]) );
+		    testconstructor( 4, "int[4]", typeof(int[][][][]) );
+		    testconstructor( 5, "int[5]", typeof(int[][][][][]) );
+		    testconstructor( 6, "int[6]", typeof(int[][][][][][]) );
+		    testconstructor( 7, "int[7]", typeof(int[][][][][][][]) );
+		    testconstructor( 8, "int[8]", typeof(int[][][][][][][][]) );
+		    testconstructor( 9, "int[9]", typeof(int[][][][][][][][][]) );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+    	
+	    private void testconstructor( int n, String descr, Type expectedClass )
+	    {
+		    TypeValidator v = Validator_int.Get( n );
+		    Assert.AreEqual( n, v.GetNDims() );
+		    Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		    Assert.AreEqual( descr, v.ToString() );
+	    }
+    	
+    	
+	    [Test]  
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void constructor2()  
+	    {
+		    Validator_int.Get( -1 );
+	    }
+    	
+    	
+	    [Test]  
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void constructor3()  
+	    {
+		    Validator_int.Get( Validator.MAX_NDIMS+1 );
+	    }
+    	
+    	
+	    [Test]
+	    public void elementvalidator1()  
+	    {
+		    testelementvalidator( 1, "int[0]", typeof(int) );
+		    testelementvalidator( 2, "int[1]", typeof(int[]) );
+		    testelementvalidator( 3, "int[2]", typeof(int[][]) );
+		    testelementvalidator( 4, "int[3]", typeof(int[][][]) );
+		    testelementvalidator( 5, "int[4]", typeof(int[][][][]) );
+		    testelementvalidator( 6, "int[5]", typeof(int[][][][][]) );
+		    testelementvalidator( 7, "int[6]", typeof(int[][][][][][]) );
+		    testelementvalidator( 8, "int[7]", typeof(int[][][][][][][]) );
+		    testelementvalidator( 9, "int[8]", typeof(int[][][][][][][][]) );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+      
+	    }
+    	
+	    private void testelementvalidator( int n, String descr, Type expectedClass )
+	    {
+		    TypeValidator v = (TypeValidator) Validator_int.Get( n ).ElementValidator();
+		    Assert.AreEqual( n-1, v.GetNDims() );
+		    Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		    Assert.AreEqual( descr, v.ToString() );
+	    }
+
+    	
+	    [Test]  
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void elementvalidator2()  
+	    {
+		    Validator_int.Get( 0 ).ElementValidator();
+	    }
+    	
+    	
+	    [Test]
+	    public void good_scalar()  
+	    {
+    		
+		    testgoodvalue( 0,  (sbyte) 0 );
+    		
+		    testgoodvalue( 0,  (sbyte) 1 );
+		    testgoodvalue( 0,  (sbyte) 64 );
+		    testgoodvalue( 0,  (sbyte)SByte.MaxValue );
+    		
+		    testgoodvalue( 0,  (sbyte) -1 );
+		    testgoodvalue( 0,  (sbyte) -64 );
+		    testgoodvalue( 0,  (sbyte)SByte.MinValue);
+
+		    // SHORTS
+    		
+		    testgoodvalue( 0,  (short) 0 );
+    		
+		    testgoodvalue( 0,  (short) 1 );
+		    testgoodvalue( 0,  (short) 64 );
+		    testgoodvalue( 0,  (short) SByte.MaxValue );
+		    testgoodvalue( 0, (short) 2222 );
+		    testgoodvalue( 0, Int16.MaxValue );
+    		
+		    testgoodvalue( 0,  (short) -1 );
+		    testgoodvalue( 0,  (short) -64 );
+		    testgoodvalue( 0,  (short) SByte.MinValue );
+		    testgoodvalue( 0,  (short) -2222 );
+		    testgoodvalue( 0, Int16.MinValue );
+
+		    // INTS
+    		
+		    testgoodvalue( 0,  0 );
+    		
+		    testgoodvalue( 0,  1 );
+		    testgoodvalue( 0,  64 );
+		    testgoodvalue( 0,  (int) SByte.MaxValue );
+		    testgoodvalue( 0,  2222 );
+		    testgoodvalue( 0,  (int) Int16.MaxValue );
+		    testgoodvalue( 0,  33333333 );
+		    testgoodvalue( 0,  Int32.MaxValue );
+    		
+		    testgoodvalue( 0,  -1 );
+		    testgoodvalue( 0,  -64 );
+		    testgoodvalue( 0,  (int) SByte.MinValue );
+		    testgoodvalue( 0,  -2222 );
+		    testgoodvalue( 0,  (int) Int16.MinValue );
+		    testgoodvalue( 0,  -33333333 );
+		    testgoodvalue( 0,  Int32.MinValue );
+
+		    // LONGS
+    		
+		    testgoodvalue( 0,  (long) 0 );
+    		
+		    testgoodvalue( 0,  (long) 1 );
+		    testgoodvalue( 0,  (long) 64 );
+		    testgoodvalue( 0,  (long) SByte.MaxValue );
+		    testgoodvalue( 0,  (long) 2222 );
+		    testgoodvalue( 0,  (long) Int16.MaxValue );
+		    testgoodvalue( 0,  (long) 33333333 );
+		    testgoodvalue( 0,  (long) Int32.MaxValue );
+    		
+		    testgoodvalue( 0,  (long) -1 );
+		    testgoodvalue( 0,  (long) -64 );
+		    testgoodvalue( 0,  (long) Byte.MinValue );
+		    testgoodvalue( 0,  (long) -2222 );
+		    testgoodvalue( 0,  (long) Int16.MinValue );
+		    testgoodvalue( 0,  (long) -33333333 );
+		    testgoodvalue( 0,  (long) Int32.MinValue );
+	    }
+    	
+    	
+	    [Test]
+	    public void good_array()  
+	    {
+		    testgoodvalue( 1,  new int[] {} );
+		    testgoodvalue( 2,  new int[][] {} );
+		    testgoodvalue( 3,  new int[][][] {} );
+		    testgoodvalue( 4,  new int[][][][] {} );
+		    testgoodvalue( 5,  new int[][][][][] {} );
+		    testgoodvalue( 6,  new int[][][][][][] {} );
+		    testgoodvalue( 7,  new int[][][][][][][] {} );
+		    testgoodvalue( 8,  new int[][][][][][][][] {} );
+		    testgoodvalue( 9,  new int[][][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+    	
+	    private void testgoodvalue( int n, Object value )
+	    {
+		    TypeValidator v = Validator_int.Get( n );
+		    Assert.IsTrue( v.Validate( value ) );
+		    Assert.IsTrue( validateValueOk( v, value ) );
+	    }
+    	
+	    /** @  */
+	    [Test]
+	    public void bad_scalar()  
+	    {
+		    testbadvalue( 0, null );
+		    testbadvalue( 0, false );
+		    testbadvalue( 0, true );
+		    testbadvalue( 0, 4444444444444444L );
+		    testbadvalue( 0, 5.5f );
+		    testbadvalue( 0, 6.6 );
+		    testbadvalue( 0, "" );
+		    testbadvalue( 0, "abc" );
+		    testbadvalue( 0, new Object() );
+            testbadvalue(0, new StructValue(new XType("abc"), vf));
+		    testbadvalue( 0, new DateTime() );
+
+		    testbadvalue( 1, null );
+		    testbadvalue( 1, false );
+		    testbadvalue( 1, true );
+		    testbadvalue( 1, (byte) 1 );
+		    testbadvalue( 1, (short) 2222 );
+		    testbadvalue( 1, 333333 );
+		    testbadvalue( 1, 4444444444444444L );
+		    testbadvalue( 1, 5.5f );
+		    testbadvalue( 1, 6.6 );
+		    testbadvalue( 1, "" );
+		    testbadvalue( 1, "abc" );
+		    testbadvalue( 1, new Object() );
+            testbadvalue(1, new StructValue(new XType("abc"), vf));
+		    testbadvalue( 1, new DateTime() );
+	    }
+    	
+	    /** @  */
+	    [Test]
+	    public void bad_array()  
+	    {
+		    testbadvalue( 0, new int[] {} );
+		    testbadvalue( 1, new int[][] {} );
+		    testbadvalue( 2, new int[][][] {} );
+		    testbadvalue( 3, new int[][][][] {} );
+		    testbadvalue( 4, new int[][][][][] {} );
+		    testbadvalue( 5, new int[][][][][][] {} );
+		    testbadvalue( 6, new int[][][][][][][] {} );
+		    testbadvalue( 7, new int[][][][][][][][] {} );
+		    testbadvalue( 8, new int[][][][][][][][][] {} );
+		    testbadvalue( 9, new int[][][][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+
+		    testbadvalue( 2, new int[] {} );
+		    testbadvalue( 3, new int[][] {} );
+		    testbadvalue( 4, new int[][][] {} );
+		    testbadvalue( 5, new int[][][][] {} );
+		    testbadvalue( 6, new int[][][][][] {} );
+		    testbadvalue( 7, new int[][][][][][] {} );
+		    testbadvalue( 8, new int[][][][][][][] {} );
+		    testbadvalue( 9, new int[][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+
+	    private void testbadvalue( int n, Object value )
+	    {
+		    TypeValidator v = Validator_int.Get( n );
+		    Assert.IsFalse( v.Validate( value ) );
+		    Assert.IsFalse( validateValueOk( v, value ) );
+	    }
+
+	    private bool validateValueOk( Validator v, Object value )
+	    {
+		    try
+		    {
+			    Object x = v.ValidateValue( value );
+			    Assert.AreEqual( value, x );
+			    return true;
+		    }
+		    catch ( Exception)
+		    {
+               
+			    return false;
+		    }
+	    }
+
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_long.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_long.cs
new file mode 100644
index 0000000..6caa511
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_long.cs
@@ -0,0 +1,296 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+        [TestFixture]
+        public class TestValidator_long
+        {
+            private readonly ValueFactory vf = new DummyValueFactory();
+
+            [TestFixtureSetUp]
+            public void First()
+            {
+                Console.WriteLine();
+                Console.Write( "TestValidator_long" );
+            }
+
+        [Test]
+	    public void constructor1()  
+	    {
+		    testconstructor( 0, "long[0]", typeof(long) );
+		    testconstructor( 1, "long[1]", typeof(long[]) );
+		    testconstructor( 2, "long[2]", typeof(long[][]));
+		    testconstructor( 3, "long[3]", typeof(long[][][]) );
+		    testconstructor( 4, "long[4]", typeof(long[][][][]) );
+		    testconstructor( 5, "long[5]", typeof(long[][][][][]) );
+		    testconstructor( 6, "long[6]", typeof(long[][][][][][]) );
+		    testconstructor( 7, "long[7]", typeof(long[][][][][][][]) );
+		    testconstructor( 8, "long[8]", typeof(long[][][][][][][][]) );
+		    testconstructor( 9, "long[9]", typeof(long[][][][][][][][][]) );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+    	
+	    private void testconstructor( int n, String descr, Type expectedClass )
+	    {
+		    TypeValidator v = Validator_long.Get( n );
+		    Assert.AreEqual( n, v.GetNDims() );
+		    Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		    Assert.AreEqual( descr, v.ToString() );
+	    }
+    	
+    	
+	    [Test]  
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void constructor2()  
+	    {
+		    Validator_long.Get( -1 );
+	    }
+    	
+    	
+	    [Test]  
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void constructor3()  
+	    {
+		    Validator_long.Get( Validator.MAX_NDIMS+1 );
+	    }
+    	
+	    /** @  */
+	    [Test]
+	    public void elementvalidator1()  
+	    {
+		    testelementvalidator( 1, "long[0]", typeof(long) );
+		    testelementvalidator( 2, "long[1]", typeof(long[]) );
+		    testelementvalidator( 3, "long[2]", typeof(long[][]));
+		    testelementvalidator( 4, "long[3]", typeof(long[][][]) );
+		    testelementvalidator( 5, "long[4]", typeof(long[][][][]) );
+		    testelementvalidator( 6, "long[5]", typeof(long[][][][][]) );
+		    testelementvalidator( 7, "long[6]", typeof(long[][][][][][]) );
+		    testelementvalidator( 8, "long[7]", typeof(long[][][][][][][]) );
+		    testelementvalidator( 9, "long[8]", typeof(long[][][][][][][][]) );
+	        Assert.AreEqual( 9, Validator.MAX_NDIMS );
+          
+	    }
+    	
+	    private void testelementvalidator( int n, String descr, Type expectedClass )
+	    {
+		    TypeValidator v = (TypeValidator) Validator_long.Get( n ).ElementValidator();
+		    Assert.AreEqual( n-1, v.GetNDims() );
+		    Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		    Assert.AreEqual( descr, v.ToString() );
+	    }
+
+    	
+	    [Test]  
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void elementvalidator2()  
+	    {
+		    Validator_long.Get( 0 ).ElementValidator();
+	    }
+    	
+	    /** @  */
+	    [Test]
+	    public void good_scalar()  
+	    {
+		    // BYTES
+    		
+		    testgoodvalue( 0,  (sbyte) 0 );
+    		
+		    testgoodvalue( 0,  (sbyte) 1 );
+		    testgoodvalue( 0,  (sbyte) 64 );
+		    testgoodvalue( 0,  SByte.MaxValue );
+    		
+		    testgoodvalue( 0,  (sbyte) -1 );
+		    testgoodvalue( 0,  (sbyte) -64 );
+		    testgoodvalue( 0,  SByte.MinValue );
+
+		    // SHORTS
+    		
+		    testgoodvalue( 0,  (short) 0 );
+    		
+		    testgoodvalue( 0,  (short) 1 );
+		    testgoodvalue( 0,  (short) 64 );
+		    testgoodvalue( 0,  (short) SByte.MaxValue );
+		    testgoodvalue( 0,  (short) 2222 );
+		    testgoodvalue( 0,  Int16.MaxValue );
+    		
+		    testgoodvalue( 0,  (short) -1 );
+		    testgoodvalue( 0,  (short) -64 );
+		    testgoodvalue( 0,  (short) SByte.MinValue );
+		    testgoodvalue( 0,  (short) -2222 );
+		    testgoodvalue( 0,  Int16.MinValue );
+
+		    // INTS
+    		
+		    testgoodvalue( 0,  0 );
+    		
+		    testgoodvalue( 0,  1 );
+		    testgoodvalue( 0,  64 );
+		    testgoodvalue( 0,  (int) SByte.MaxValue );
+		    testgoodvalue( 0,  2222 );
+		    testgoodvalue( 0,  (int) Int16.MaxValue );
+		    testgoodvalue( 0,  33333333 );
+		    testgoodvalue( 0,  Int32.MaxValue );
+    		
+		    testgoodvalue( 0,  -1 );
+		    testgoodvalue( 0,  -64 );
+		    testgoodvalue( 0,  (int) SByte.MinValue );
+		    testgoodvalue( 0,  -2222 );
+		    testgoodvalue( 0,  (int) Int16.MinValue );
+		    testgoodvalue( 0,  -33333333 );
+		    testgoodvalue( 0,  Int32.MinValue );
+
+		    // LONGS
+    		
+		    testgoodvalue( 0,  (long) 0 );
+    		
+		    testgoodvalue( 0,  (long) 1 );
+		    testgoodvalue( 0,  (long) 64 );
+		    testgoodvalue( 0,  (long) SByte.MaxValue );
+		    testgoodvalue( 0,  (long) 2222 );
+		    testgoodvalue( 0,  (long) Int16.MaxValue );
+		    testgoodvalue( 0,  (long) 33333333 );
+		    testgoodvalue( 0,  (long) Int32.MaxValue );
+		    testgoodvalue( 0,  4444444444444444L );
+		    testgoodvalue( 0,  Int64.MaxValue );
+    		
+		    testgoodvalue( 0,  (long) -1 );
+		    testgoodvalue( 0,  (long) -64 );
+		    testgoodvalue( 0,  (long) SByte.MinValue );
+		    testgoodvalue( 0,  (long) -2222 );
+		    testgoodvalue( 0,  (long) Int16.MinValue );
+		    testgoodvalue( 0,  (long) -33333333 );
+		    testgoodvalue( 0,  (long) Int32.MinValue );
+		    testgoodvalue( 0,  -4444444444444444L );
+		    testgoodvalue( 0,  Int64.MinValue );
+	    }
+    	
+	    /** @  */
+	    [Test]
+	    public void good_array()  
+	    {
+		    testgoodvalue( 1,  new long[] {} );
+		    testgoodvalue( 2,  new long[][] {} );
+		    testgoodvalue( 3,  new long[][][] {} );
+		    testgoodvalue( 4,  new long[][][][] {} );
+		    testgoodvalue( 5,  new long[][][][][] {} );
+		    testgoodvalue( 6,  new long[][][][][][] {} );
+		    testgoodvalue( 7,  new long[][][][][][][] {} );
+		    testgoodvalue( 8,  new long[][][][][][][][] {} );
+		    testgoodvalue( 9,  new long[][][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+    	
+	    private void testgoodvalue( int n, Object value )
+	    {
+		    TypeValidator v = Validator_long.Get( n );
+		    Assert.IsTrue( v.Validate( value ) );
+		    Assert.IsTrue( validateValueOk( v, value ) );
+	    }
+    	
+	    /** @  */
+	    [Test]
+	    public void bad_scalar()  
+	    {
+		    testbadvalue( 0, null );
+		    testbadvalue( 0, false );
+		    testbadvalue( 0, true );
+    //		testbadvalue( 0, (byte) 1 ); good!
+    //		testbadvalue( 0, (short) 2222 ); good!
+    //		testbadvalue( 0, 33333333 ); good!
+    //		testbadvalue( 0, 4444444444444444L ); good!
+		    testbadvalue( 0, 5.5f );
+		    testbadvalue( 0, 6.6 );
+		    testbadvalue( 0, "" );
+		    testbadvalue( 0, "abc" );
+		    testbadvalue( 0, new Object() );
+            testbadvalue(0, new StructValue(new XType("abc"), vf));
+		    testbadvalue( 0, new DateTime() );
+
+		    testbadvalue( 1, null );
+		    testbadvalue( 1, false );
+		    testbadvalue( 1, true );
+		    testbadvalue( 1, (byte) 1 );
+		    testbadvalue( 1, (short) 2222 );
+		    testbadvalue( 1, 333333 );
+		    testbadvalue( 1, 4444444444444444L );
+		    testbadvalue( 1, 5.5f );
+		    testbadvalue( 1, 6.6 );
+		    testbadvalue( 1, "" );
+		    testbadvalue( 1, "abc" );
+		    testbadvalue( 1, new Object() );
+            testbadvalue(1, new StructValue(new XType("abc"), vf));
+		    testbadvalue( 1, new DateTime() );
+	    }
+    	
+	    /** @  */
+	    [Test]
+	    public void bad_array()  
+	    {
+		    testbadvalue( 0, new long[] {} );
+		    testbadvalue( 1, new long[][] {} );
+		    testbadvalue( 2, new long[][][] {} );
+		    testbadvalue( 3, new long[][][][] {} );
+		    testbadvalue( 4, new long[][][][][] {} );
+		    testbadvalue( 5, new long[][][][][][] {} );
+		    testbadvalue( 6, new long[][][][][][][] {} );
+		    testbadvalue( 7, new long[][][][][][][][] {} );
+		    testbadvalue( 8, new long[][][][][][][][][] {} );
+		    testbadvalue( 9, new long[][][][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+
+		    testbadvalue( 2, new long[] {} );
+		    testbadvalue( 3, new long[][] {} );
+		    testbadvalue( 4, new long[][][] {} );
+		    testbadvalue( 5, new long[][][][] {} );
+		    testbadvalue( 6, new long[][][][][] {} );
+		    testbadvalue( 7, new long[][][][][][] {} );
+		    testbadvalue( 8, new long[][][][][][][] {} );
+		    testbadvalue( 9, new long[][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+
+	    private void testbadvalue( int n, Object value )
+	    {
+		    TypeValidator v = Validator_long.Get( n );
+		    Assert.IsFalse( v.Validate( value ) );
+		    Assert.IsFalse( validateValueOk( v, value ) );
+	    }
+
+	    private bool validateValueOk( Validator v, Object value )
+	    {
+		    try
+		    {
+			    Object x = v.ValidateValue( value );
+			    Assert.AreEqual( value, x );
+			    return true;
+		    }
+		    catch ( Exception  )
+		    {
+              
+			    return false;
+		    }
+	    }
+
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_object.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_object.cs
new file mode 100644
index 0000000..84a0cce
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_object.cs
@@ -0,0 +1,332 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+        [TestFixture]
+        public class TestValidator_object
+        {
+            private readonly ValueFactory vf = new DummyValueFactory();
+
+            [TestFixtureSetUp]
+            public void First()
+            {
+                Console.WriteLine();
+                Console.Write( "TestValidator_object" );
+            }
+
+           
+	    [Test]
+	    public void constructor1()  
+	    {
+		    testconstructor( 0, "object[0]", typeof(Object) );
+		    testconstructor( 1, "object[1]", typeof(Object[]) );
+		    testconstructor( 2, "object[2]", typeof(Object[][]) );
+		    testconstructor( 3, "object[3]", typeof(Object[][][]) );
+		    testconstructor( 4, "object[4]", typeof(Object[][][][]));
+		    testconstructor( 5, "object[5]", typeof(Object[][][][][]) );
+		    testconstructor( 6, "object[6]", typeof(Object[][][][][][]) );
+		    testconstructor( 7, "object[7]", typeof(Object[][][][][][][]) );
+		    testconstructor( 8, "object[8]", typeof(Object[][][][][][][][]) );
+		    testconstructor( 9, "object[9]", typeof(Object[][][][][][][][][]) );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+    	
+	    private void testconstructor( int n, String descr, Type expectedClass )
+	    {
+		    TypeValidator v = Validator_object.Get( n );
+		    Assert.AreEqual( n, v.GetNDims() );
+		    Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		    Assert.AreEqual( descr, v.ToString() );
+	    }
+    	
+    	
+	    [Test]  
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void constructor2()  
+	    {
+		    Validator_object.Get( -1 );
+	    }
+    	
+    	
+	    [Test]  
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void constructor3()  
+	    {
+		    Validator_object.Get( Validator.MAX_NDIMS+1 );
+	    }
+    	
+    	
+	    [Test]
+	    public void elementvalidator1()  
+	    {
+		    testelementvalidator( 0, 0, "object[0]", typeof(Object) );
+		    testelementvalidator( 1, 0, "object[0]", typeof(Object) );
+		    testelementvalidator( 2, 1, "object[1]", typeof(Object[]) );
+		    testelementvalidator( 3, 2, "object[2]", typeof(Object[][]) );
+		    testelementvalidator( 4, 3, "object[3]", typeof(Object[][][]) );
+		    testelementvalidator( 5, 4, "object[4]", typeof(Object[][][][]) );
+		    testelementvalidator( 6, 5, "object[5]", typeof(Object[][][][][]) );
+		    testelementvalidator( 7, 6, "object[6]", typeof(Object[][][][][][]) );
+		    testelementvalidator( 8, 7, "object[7]", typeof(Object[][][][][][][]) );
+		    testelementvalidator( 9, 8, "object[8]", typeof(Object[][][][][][][][]) );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+    	
+	    private void testelementvalidator( int n, int k, String descr, Type expectedClass )
+	    {
+		    TypeValidator v = (TypeValidator) Validator_object.Get( n ).ElementValidator();
+		    Assert.AreEqual( k, v.GetNDims() );
+		    Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		    Assert.AreEqual( descr, v.ToString() );
+	    }
+    	
+	    /** @  */
+	    [Test]
+	    public void good_scalar()  
+	    {
+		    testgoodvalue( 0,  false );
+		    testgoodvalue( 0,  true );
+		    testgoodvalue( 0,  (sbyte) 1 );
+		    testgoodvalue( 0,  (short) 2222 );
+		    testgoodvalue( 0,  33333333 );
+		    testgoodvalue( 0,  4444444444444444L );
+		    testgoodvalue( 0,  5.5f );
+		    testgoodvalue( 0,  6.6 );
+		    testgoodvalue( 0,  "" );
+		    testgoodvalue( 0,  "abc" );
+		    testgoodvalue( 0,  new Object() );
+            testgoodvalue(0, new StructValue(new XType("abc"), vf));
+		    testgoodvalue( 0,  new DateTime() );
+	    }
+    	
+	    /** @  */
+	    [Test]
+	    public void good_array()  
+	    {
+		    // primitive array types are compatible with object.
+    		
+		    testgoodvalue( 0,  new bool[] {} );
+		    testgoodvalue( 0,  new sbyte[] {} );
+		    testgoodvalue( 0,  new short[] {} );
+		    testgoodvalue( 0,  new int[] {} );
+		    testgoodvalue( 0,  new long[] {} );
+		    testgoodvalue( 0,  new float[] {} );
+		    testgoodvalue( 0,  new double[] {} );
+    		
+		    // ref array types are compatible with object.
+
+		    testgoodvalue( 0,  new Boolean[] {} );
+		    testgoodvalue( 0,  new SByte[] {} );
+		    testgoodvalue( 0,  new Int16[] {} );
+		    testgoodvalue( 0,  new Int32[] {} );
+		    testgoodvalue( 0,  new Int64[] {} );
+		    testgoodvalue( 0,  new Single[] {} );
+		    testgoodvalue( 0,  new Double[] {} );
+		    testgoodvalue( 0,  new String[] {} );
+		    testgoodvalue( 0,  new Object[] {} );
+		    testgoodvalue( 0,  new StructValue[] {} );
+		    testgoodvalue( 0,  new DateTime[] {} );
+    		
+		    // ref array types are compatible with object array (same size).
+	       
+		/*    testgoodvalue( 1,  new Boolean[] {} );
+		    testgoodvalue( 1,  new SByte[] {} );
+		    testgoodvalue( 1,  new Int16[] {} ); 
+		    testgoodvalue( 1,  new Int32[] {} );
+		    testgoodvalue( 1,  new Int64[] {} );
+		    testgoodvalue( 1,  new Single[] {} );
+		    testgoodvalue( 1,  new Double[] {} ); */
+		    testgoodvalue( 1,  new String[] {} ); 
+		    testgoodvalue( 1,  new Object[] {} );
+		    testgoodvalue( 1,  new StructValue[] {} );
+//		    testgoodvalue( 1,  new DateTime[] {} );
+    		
+		    // ref array types are compatible with object array (larger size).
+    		
+/*		    testgoodvalue( 1,  new Boolean[][] {} );
+		    testgoodvalue( 1,  new SByte[][] {} );
+		    testgoodvalue( 1,  new Int16[][] {} );
+		    testgoodvalue( 1,  new Int32[][] {} );
+		    testgoodvalue( 1,  new Int64[][] {} );
+		    testgoodvalue( 1,  new Single[][] {} );
+		    testgoodvalue( 1,  new Double[][] {} ); */
+		    testgoodvalue( 1,  new String[][] {} );
+		    testgoodvalue( 1,  new Object[][] {} );
+		    testgoodvalue( 1,  new StructValue[][] {} );
+//		    testgoodvalue( 1,  new DateTime[][] {} );
+	    }
+    	
+	    private void testgoodvalue( int n, Object value )
+	    {
+		    TypeValidator v = Validator_object.Get( n );
+		    Assert.IsTrue( v.Validate( value ) );
+		    Assert.IsTrue( validateValueOk( v, value ) );
+	    }
+    	
+	    /** @  */
+	    [Test]
+	    public void assignable1()  
+	    {
+		    Object x;
+    		
+		    x = new Object();
+		    Assert.IsTrue( x1( typeof(Object), typeof(Object) ) );
+
+		    x = new Object[] {};
+		    Assert.IsTrue( x1( typeof(Object), typeof(Object[]) ) );
+    		
+		    x = new Object[][] {};
+		    Assert.IsTrue( x1( typeof(Object), typeof(Object[][]) ) );
+
+		    x = new Int32();
+		    Assert.IsTrue( x1( typeof(Object), typeof(Int32) ) );
+    		
+		    x = new Int32[] {};
+		    Assert.IsTrue( x1( typeof(Object), typeof(Int32[]) ) );
+
+		    x = new int[] {};
+		    Assert.IsTrue( x1(typeof(Object), typeof(int) ) );
+    		
+		    Assert.IsNotNull( x );
+	    }
+    	
+	    /** @  */
+	    [Test]
+	    public void assignable2()  
+	    {
+		    Object[] y;
+    		
+    //		y = new Object();
+		    Assert.IsFalse( x1( typeof(Object[]), typeof(Object) ) );
+
+		    y = new Object[] {};
+		    Assert.IsTrue( x1(  typeof(Object[]),  typeof(Object[]) ) );
+    		
+		    y = new Object[][] {};
+		    Assert.IsTrue( x1(  typeof(Object[]), typeof(Object[][]) ) );
+
+    //		y = new Integer( 0 );
+		    Assert.IsFalse( x1(  typeof(Object[]), typeof(Int32) ) );
+    		
+    		
+
+    //		y = new int[] {};
+		    Assert.IsFalse( x1(  typeof(Object[]), typeof(int[]) ) );
+	    }
+    	
+    	
+    	
+	    private bool x1( Type a, Type b )
+	    {
+		    return a.IsAssignableFrom( b );
+	    }
+
+    	
+	    [Test]
+	    public void bad_scalar()  
+	    {
+		    testbadvalue( 0, null );
+    //		testbadvalue( 0, false );
+    //		testbadvalue( 0, true );
+    //		testbadvalue( 0, (byte) 1 );
+    //		testbadvalue( 0, (short) 2222 );
+    //		testbadvalue( 0, 33333333 );
+    //		testbadvalue( 0, 4444444444444444L );
+    //		testbadvalue( 0, 5.5f );
+    //		testbadvalue( 0, 6.6 );
+    //		testbadvalue( 0, "" );
+    //		testbadvalue( 0, "abc" );
+    //		testbadvalue( 0, new Object() );
+    //		testbadvalue( 0, new StructValue( new Type( "abc" ) ) );
+    //		testbadvalue( 0, new Date() );
+
+		    testbadvalue( 1, null );
+		    testbadvalue( 1, false );
+		    testbadvalue( 1, true );
+		    testbadvalue( 1, (byte) 1 );
+		    testbadvalue( 1, (short) 2222 );
+		    testbadvalue( 1, 333333 );
+		    testbadvalue( 1, 4444444444444444L );
+		    testbadvalue( 1, 5.5f );
+		    testbadvalue( 1, 6.6 );
+		    testbadvalue( 1, "" );
+		    testbadvalue( 1, "abc" );
+		    testbadvalue( 1, new Object() );
+            testbadvalue(1, new StructValue(new XType("abc"), vf));
+		    testbadvalue( 1, new DateTime() );
+	    }
+    	
+	    /** @  */
+	    [Test]
+	    public void bad_array()  
+	    {
+		    // primitive arrays cannot map into object arrays...
+    		
+		    testbadvalue( 1, new bool[] {} );
+		    testbadvalue( 1, new sbyte[] {} );
+		    testbadvalue( 1, new short[] {} );
+		    testbadvalue( 1, new int[] {} );
+		    testbadvalue( 1, new long[] {} );
+		    testbadvalue( 1, new float[] {} );
+		    testbadvalue( 1, new double[] {} );
+
+		    // too short...
+    		
+		    testbadvalue( 2, new Object[] {} );
+		    testbadvalue( 3, new Object[][] {} );
+		    testbadvalue( 4, new Object[][][] {} );
+		    testbadvalue( 5, new Object[][][][] {} );
+		    testbadvalue( 6, new Object[][][][][] {} );
+		    testbadvalue( 7, new Object[][][][][][] {} );
+		    testbadvalue( 8, new Object[][][][][][][] {} );
+		    testbadvalue( 9, new Object[][][][][][][][] {} );
+		    Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	    }
+
+	    private void testbadvalue( int n, Object value )
+	    {
+		    TypeValidator v = Validator_object.Get( n );
+		    Assert.IsFalse( v.Validate( value ) );
+		    Assert.IsFalse( validateValueOk( v, value ) );
+	    }
+
+	    private bool validateValueOk( Validator v, Object value )
+	    {
+		    try
+		    {
+			    Object x = v.ValidateValue( value );
+			    Assert.AreEqual( value, x );
+			    return true;
+		    }
+		    catch ( Exception)
+		    {
+               
+			    return false;
+		    }
+	    }
+
+       
+
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_short.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_short.cs
new file mode 100644
index 0000000..8560ae9
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_short.cs
@@ -0,0 +1,283 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    [TestFixture]
+    public class TestValidator_short
+    {
+        private readonly ValueFactory vf = new DummyValueFactory();
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestValidator_short" );
+        }
+
+    [Test]
+	public void constructor1()  
+	{
+		testconstructor( 0, "short[0]", typeof(short) );
+		testconstructor( 1, "short[1]", typeof(short[]) );
+		testconstructor( 2, "short[2]", typeof(short[][]) );
+		testconstructor( 3, "short[3]", typeof(short[][][]) );
+		testconstructor( 4, "short[4]", typeof(short[][][][]) );
+		testconstructor( 5, "short[5]", typeof(short[][][][][]) );
+		testconstructor( 6, "short[6]", typeof(short[][][][][][]) );
+		testconstructor( 7, "short[7]", typeof(short[][][][][][][]) );
+		testconstructor( 8, "short[8]", typeof(short[][][][][][][][]) );
+		testconstructor( 9, "short[9]", typeof(short[][][][][][][][][]) );
+		Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testconstructor( int n, String descr, Type expectedClass )
+	{
+		TypeValidator v = Validator_short.Get( n );
+		Assert.AreEqual( n, v.GetNDims() );
+		Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		Assert.AreEqual( descr, v.ToString() );
+	}
+	
+	/** @  */
+	[Test]  
+    [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	public void constructor2()  
+	{
+		Validator_short.Get( -1 );
+	}
+	
+	/** @  */
+	[Test]  
+    [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	public void constructor3()  
+	{
+		Validator_short.Get( Validator.MAX_NDIMS+1 );
+	}
+	
+	
+	[Test]
+	public void elementvalidator1()  
+	{
+		testelementvalidator( 1, "short[0]", typeof(short) );
+		testelementvalidator( 2, "short[1]", typeof(short[]) );
+		testelementvalidator( 3, "short[2]", typeof(short[][]) );
+		testelementvalidator( 4, "short[3]", typeof(short[][][]) );
+		testelementvalidator( 5, "short[4]", typeof(short[][][][]) );
+		testelementvalidator( 6, "short[5]", typeof(short[][][][][]) );
+		testelementvalidator( 7, "short[6]", typeof(short[][][][][][]) );
+		testelementvalidator( 8, "short[7]", typeof(short[][][][][][][]));
+		testelementvalidator( 9, "short[8]", typeof(short[][][][][][][][]) );
+		Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testelementvalidator( int n, String descr, Type expectedClass )
+	{
+		TypeValidator v = (TypeValidator) Validator_short.Get( n ).ElementValidator();
+		Assert.AreEqual( n-1, v.GetNDims() );
+		Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		Assert.AreEqual( descr, v.ToString() );
+	}
+
+	/** @  */
+	[Test]  [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	public void elementvalidator2()  
+	{
+		Validator_short.Get( 0 ).ElementValidator();
+	}
+	
+	/** @  */
+	[Test]
+	public void good_scalar()  
+	{
+		// BYTES
+		
+		testgoodvalue( 0,  (sbyte) 0 );
+		
+		testgoodvalue( 0,  (sbyte) 1 );
+		testgoodvalue( 0,  (sbyte) 64 );
+		testgoodvalue( 0,  SByte.MaxValue );
+		
+		testgoodvalue( 0,  (sbyte) -1 );
+		testgoodvalue( 0,  (sbyte) -64 );
+		testgoodvalue( 0,  SByte.MinValue );
+
+		// SHORTS
+		
+		testgoodvalue( 0,  (short) 0 );
+		
+		testgoodvalue( 0,  (short) 1 );
+		testgoodvalue( 0,  (short) 64 );
+		testgoodvalue( 0,  (short) SByte.MaxValue );
+		testgoodvalue( 0,  (short) 2222 );
+		testgoodvalue( 0,  Int16.MaxValue );
+		
+		testgoodvalue( 0,  (short) -1 );
+		testgoodvalue( 0,  (short) -64 );
+		testgoodvalue( 0,  (short) SByte.MinValue );
+		testgoodvalue( 0,  (short) -2222 );
+		testgoodvalue( 0,  Int16.MinValue );
+
+		// INTS
+		
+		testgoodvalue( 0,  0 );
+		
+		testgoodvalue( 0,  1 );
+		testgoodvalue( 0,  64 );
+		testgoodvalue( 0,  (int) SByte.MaxValue );
+		testgoodvalue( 0,  2222 );
+		testgoodvalue( 0,  (int) Int16.MaxValue );
+		
+		testgoodvalue( 0,  -1 );
+		testgoodvalue( 0,  -64 );
+		testgoodvalue( 0,  (int) SByte.MinValue );
+		testgoodvalue( 0,  -2222 );
+		testgoodvalue( 0,  (int) Int16.MinValue );
+
+		// LONGS
+		
+		testgoodvalue( 0,  (long) 0 );
+		
+		testgoodvalue( 0,  (long) 1 );
+		testgoodvalue( 0,  (long) 64 );
+		testgoodvalue( 0,  (long) SByte.MaxValue );
+		testgoodvalue( 0,  (long) 2222 );
+		testgoodvalue( 0,  (long) Int16.MaxValue );
+		
+		testgoodvalue( 0,  (long) -1 );
+		testgoodvalue( 0,  (long) -64 );
+		testgoodvalue( 0,  (long) SByte.MinValue );
+		testgoodvalue( 0,  (long) -2222 );
+		testgoodvalue( 0,  (long) Int16.MinValue );
+	}
+	
+	/** @  */
+	[Test]
+	public void good_array()  
+	{
+		testgoodvalue( 1,  new short[] {} );
+		testgoodvalue( 2,  new short[][] {} );
+		testgoodvalue( 3,  new short[][][] {} );
+		testgoodvalue( 4,  new short[][][][] {} );
+		testgoodvalue( 5,  new short[][][][][] {} );
+		testgoodvalue( 6,  new short[][][][][][] {} );
+		testgoodvalue( 7,  new short[][][][][][][] {} );
+		testgoodvalue( 8,  new short[][][][][][][][] {} );
+		testgoodvalue( 9,  new short[][][][][][][][][] {} );
+		Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testgoodvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_short.Get( n );
+		Assert.IsTrue( v.Validate( value ) );
+		Assert.IsTrue( validateValueOk( v, value ) );
+	}
+	
+	/** @  */
+	[Test]
+	public void bad_scalar()  
+	{
+		testbadvalue( 0, null );
+		testbadvalue( 0, false );
+		testbadvalue( 0, true );
+//		testbadvalue( 0, (byte) 1 ); good!
+//		testbadvalue( 0, (short) 2222 ); good!
+		testbadvalue( 0, 33333333 );
+		testbadvalue( 0, 4444444444444444L );
+		testbadvalue( 0, 5.5f );
+		testbadvalue( 0, 6.6 );
+		testbadvalue( 0, "" );
+		testbadvalue( 0, "abc" );
+		testbadvalue( 0, new Object() );
+        testbadvalue(0, new StructValue(new XType("abc"), vf));
+		testbadvalue( 0, new DateTime() );
+
+		testbadvalue( 1, null );
+		testbadvalue( 1, false );
+		testbadvalue( 1, true );
+		testbadvalue( 1, (byte) 1 );
+		testbadvalue( 1, (short) 2222 );
+		testbadvalue( 1, 333333 );
+		testbadvalue( 1, 4444444444444444L );
+		testbadvalue( 1, 5.5f );
+		testbadvalue( 1, 6.6 );
+		testbadvalue( 1, "" );
+		testbadvalue( 1, "abc" );
+		testbadvalue( 1, new Object() );
+        testbadvalue(1, new StructValue(new XType("abc"), vf));
+		testbadvalue( 1, new DateTime() );
+	}
+	
+	/** @  */
+	[Test]
+	public void bad_array()  
+	{
+		testbadvalue( 0, new short[] {} );
+		testbadvalue( 1, new short[][] {} );
+		testbadvalue( 2, new short[][][] {} );
+		testbadvalue( 3, new short[][][][] {} );
+		testbadvalue( 4, new short[][][][][] {} );
+		testbadvalue( 5, new short[][][][][][] {} );
+		testbadvalue( 6, new short[][][][][][][] {} );
+		testbadvalue( 7, new short[][][][][][][][] {} );
+		testbadvalue( 8, new short[][][][][][][][][] {} );
+		testbadvalue( 9, new short[][][][][][][][][][] {} );
+		Assert.AreEqual( 9, Validator.MAX_NDIMS );
+
+		testbadvalue( 2, new short[] {} );
+		testbadvalue( 3, new short[][] {} );
+		testbadvalue( 4, new short[][][] {} );
+		testbadvalue( 5, new short[][][][] {} );
+		testbadvalue( 6, new short[][][][][] {} );
+		testbadvalue( 7, new short[][][][][][] {} );
+		testbadvalue( 8, new short[][][][][][][] {} );
+		testbadvalue( 9, new short[][][][][][][][] {} );
+		Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	}
+
+	private void testbadvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_short.Get( n );
+		Assert.IsFalse( v.Validate( value ) );
+		Assert.IsFalse( validateValueOk( v, value ) );
+	}
+
+	private bool validateValueOk( Validator v, Object value )
+	{
+		try
+		{
+			Object x = v.ValidateValue( value );
+			Assert.AreEqual( value, x );
+			return true;
+		}
+		catch ( Exception )
+		{
+            
+			return false;
+		}
+	}
+
+     
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_string.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_string.cs
new file mode 100644
index 0000000..9c7cbcf
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_string.cs
@@ -0,0 +1,227 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    [TestFixture]
+    public class TestValidator_string
+    {
+        private readonly ValueFactory vf = new DummyValueFactory();
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestValidator_string" );
+        }
+
+        [Test]
+	public void constructor1()  
+	{
+		testconstructor( 0, "string[0]", typeof(string) );
+		testconstructor( 1, "string[1]", typeof(string[]));
+		testconstructor( 2, "string[2]", typeof(string[][]) );
+		testconstructor( 3, "string[3]", typeof(string[][][]) );
+		testconstructor( 4, "string[4]", typeof(string[][][][]));
+		testconstructor( 5, "string[5]", typeof(string[][][][][]) );
+		testconstructor( 6, "string[6]", typeof(string[][][][][][]) );
+		testconstructor( 7, "string[7]", typeof(string[][][][][][][]) );
+		testconstructor( 8, "string[8]", typeof(string[][][][][][][][]) );
+		testconstructor( 9, "string[9]", typeof(string[][][][][][][][][]) );
+		Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testconstructor( int n, string descr, Type expectedClass )
+	{
+		TypeValidator v = Validator_string.Get( n );
+		Assert.AreEqual( n, v.GetNDims() );
+		Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		Assert.AreEqual( descr, v.ToString() );
+	}
+	
+	/** @  */
+	[Test]  
+    [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	public void constructor2()  
+	{
+		Validator_string.Get( -1 );
+	}
+	
+	/** @  */
+	[Test]  
+    [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	public void constructor3()  
+	{
+		Validator_string.Get( Validator.MAX_NDIMS+1 );
+	}
+	
+	/** @  */
+	[Test]
+	public void elementvalidator1()  
+	{
+		testelementvalidator( 1, "string[0]", typeof(string) );
+		testelementvalidator( 2, "string[1]", typeof(string[]) );
+		testelementvalidator( 3, "string[2]", typeof(string[][]) );
+		testelementvalidator( 4, "string[3]", typeof(string[][][]) );
+		testelementvalidator( 5, "string[4]", typeof(string[][][][]) );
+		testelementvalidator( 6, "string[5]", typeof(string[][][][][]) );
+		testelementvalidator( 7, "string[6]", typeof(string[][][][][][]) );
+		testelementvalidator( 8, "string[7]", typeof(string[][][][][][][]) );
+        testelementvalidator(9,  "string[8]", typeof(string[][][][][][][][]));
+		Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testelementvalidator( int n, string descr, Type expectedClass )
+	{
+		TypeValidator v = (TypeValidator) Validator_string.Get( n ).ElementValidator();
+		Assert.AreEqual( n-1, v.GetNDims() );
+		Assert.AreSame( expectedClass, v.GetExpectedClass() );
+		Assert.AreEqual( descr, v.ToString() );
+	}
+
+	/** @  */
+	[Test]  
+    [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	public void elementvalidator2()  
+	{
+		Validator_string.Get( 0 ).ElementValidator();
+	}
+	
+	/** @  */
+	[Test]
+	public void good_scalar()  
+	{
+		testgoodvalue( 0, "" );
+		testgoodvalue( 0,  "abc" );
+	}
+	
+	/** @  */
+	[Test]
+	public void good_array()  
+	{
+		testgoodvalue( 1,  new string[] {} );
+		testgoodvalue( 2,  new string[][] {} );
+		testgoodvalue( 3,  new string[][][] {} );
+		testgoodvalue( 4,  new string[][][][] {} );
+		testgoodvalue( 5,  new string[][][][][] {} );
+		testgoodvalue( 6,  new string[][][][][][] {} );
+		testgoodvalue( 7,  new string[][][][][][][] {} );
+		testgoodvalue( 8,  new string[][][][][][][][] {} );
+		testgoodvalue( 9,  new string[][][][][][][][][] {} );
+		Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testgoodvalue( int n,  Object value )
+	{
+		TypeValidator v = Validator_string.Get( n );
+		Assert.IsTrue( v.Validate( value ) );
+		Assert.IsTrue( validateValueOk( v, value ) );
+	}
+	
+	/** @  */
+	[Test]
+	public void bad_scalar()  
+	{
+		testbadvalue( 0, null );
+		testbadvalue( 0, false );
+		testbadvalue( 0, true );
+		testbadvalue( 0, (byte) 1 );
+		testbadvalue( 0, (short) 2222 );
+		testbadvalue( 0, 33333333 );
+		testbadvalue( 0, 4444444444444444L );
+		testbadvalue( 0, 5.5f );
+		testbadvalue( 0, 6.6 );
+//		testbadvalue( 0, "" ); // good!
+//		testbadvalue( 0, "abc" ); // good!
+		testbadvalue( 0, new Object() );
+		testbadvalue( 0, new StructValue( new XType( "abc" ), vf ) );
+		testbadvalue( 0, new DateTime() );
+
+		testbadvalue( 1, null );
+		testbadvalue( 1, false );
+		testbadvalue( 1, true );
+		testbadvalue( 1, (byte) 1 );
+		testbadvalue( 1, (short) 2222 );
+		testbadvalue( 1, 333333 );
+		testbadvalue( 1, 4444444444444444L );
+		testbadvalue( 1, 5.5f );
+		testbadvalue( 1, 6.6 );
+		testbadvalue( 1, "" );
+		testbadvalue( 1, "abc" );
+		testbadvalue( 1, new Object() );
+        testbadvalue(1, new StructValue(new XType("abc"), vf));
+		testbadvalue( 1, new DateTime() );
+	}
+	
+	/** @  */
+	[Test]
+	public void bad_array()  
+	{
+		testbadvalue( 0, new string[] {} );
+		testbadvalue( 1, new string[][] {} );
+		testbadvalue( 2, new string[][][] {} );
+		testbadvalue( 3, new string[][][][] {} );
+		testbadvalue( 4, new string[][][][][] {} );
+		testbadvalue( 5, new string[][][][][][] {} );
+		testbadvalue( 6, new string[][][][][][][] {} );
+		testbadvalue( 7, new string[][][][][][][][] {} );
+		testbadvalue( 8, new string[][][][][][][][][] {} );
+		testbadvalue( 9, new string[][][][][][][][][][] {} );
+		Assert.AreEqual( 9, Validator.MAX_NDIMS );
+
+		testbadvalue( 2, new string[] {} );
+		testbadvalue( 3, new string[][] {} );
+		testbadvalue( 4, new string[][][] {} );
+		testbadvalue( 5, new string[][][][] {} );
+		testbadvalue( 6, new string[][][][][] {} );
+		testbadvalue( 7, new string[][][][][][] {} );
+		testbadvalue( 8, new string[][][][][][][] {} );
+		testbadvalue( 9, new string[][][][][][][][] {} );
+		Assert.AreEqual( 9, Validator.MAX_NDIMS );
+	}
+
+	private void testbadvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_string.Get( n );
+		Assert.IsFalse( v.Validate( value ) );
+		Assert.IsFalse( validateValueOk( v, value ) );
+	}
+
+	private bool validateValueOk( Validator v, Object value )
+	{
+		try
+		{
+			Object x = v.ValidateValue( value );
+			Assert.AreEqual( value, x );
+			return true;
+		}
+		catch ( Exception  )
+		{
+           
+			return false;
+		}
+	}
+
+      
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_void.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_void.cs
new file mode 100644
index 0000000..a458033
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidator_void.cs
@@ -0,0 +1,79 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    [TestFixture]
+    public class TestValidator_void
+    {
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestValidator_void" );
+        }
+
+        [Test]
+        public void Test()
+        {
+            Test( 0, "void[0]", null, ( sbyte ) 1 );
+            Test( 0, "void[0]",  null, ( float ) 1 );
+            Test( 0, "void[0]",  null, ( int ) 1 );
+            Test( 0, "void[0]",  null, ( short ) 1 );
+            Test( 0, "void[0]",  null, ( double ) 1 );
+            Test( 0, "void[0]",  null, ( long ) 1 );
+            Test( 0, "void[0]",  null, "abc" );
+        }
+
+        private void Test( int n, String s,Object good, Object bad )
+        {
+            Validator_void v = Validator_void.Get( n );
+            Assert.IsTrue( v.Validate( good ) );
+            Assert.IsFalse( v.Validate( bad ) );
+          
+        }
+
+
+        [Test]
+        [ExpectedException( typeof( ArgumentException ) )]
+        public void TestGetNeg1()
+        {
+            Validator_void.Get( -1 );
+        }
+
+
+        [Test]
+        public void TestGetNeg2()
+        {
+            Assert.IsNull( Validator_void.Get( 0 ).ElementValidator() );
+        }
+
+
+        [Test]
+        [ExpectedException( typeof( ArgumentException ) )]
+        public void TestGetMaxPlusOne()
+        {
+            Validator_void.Get( Validator.MAX_NDIMS + 1 );
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidators.cs b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidators.cs
new file mode 100644
index 0000000..860948d
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Support/TestValidators.cs
@@ -0,0 +1,284 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Support
+{
+    [TestFixture]
+    public class TestValidators
+    {
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestValidator" );
+        }
+
+        [Test]
+	    public void Test_boolean()
+	    {
+		    Test( Validator_boolean.Get( 2 ), 2,
+			    new Boolean[][] { new Boolean[] { false, false }, new Boolean[] { false, false } } );
+    		
+		    Test( Validator_boolean.Get( 2 ), 2,
+			    new Boolean[][] { new Boolean[] { true, true }, new Boolean[] { true, true } } );
+	    }
+
+	    
+	    [Test]
+	    public void Test_SByte()
+	    {
+		    Test( Validator_byte.Get( 2 ), 2,
+			 
+			    new SByte[][] { new SByte[] { 0, 0 }, new SByte[] { 0, 0 } } );
+
+		    Test( Validator_byte.Get( 2 ), 2,
+              
+			    new SByte[][] { new SByte[] { 1, 1 }, new SByte[] { 1, 1 } } );
+
+		    Test( Validator_byte.Get( 2 ), 2,
+              
+			    new SByte[][] { new SByte[] { -1, -1 }, new SByte[] { -1, -1 } } );
+    		
+		    Test( Validator_byte.Get( 2 ), 2,
+               
+			    new SByte[][] { new SByte[] { SByte.MaxValue, SByte.MinValue }, new SByte[] { SByte.MaxValue, SByte.MinValue } } );
+    		
+		    Test( Validator_byte.Get( 2 ), 2,
+              
+			    new SByte[][] { new SByte[] { SByte.MinValue, SByte.MinValue }, new SByte[] { SByte.MinValue, SByte.MinValue } } );
+	    }
+
+	    
+	    [Test]
+	    public void Test_short()
+	    {
+		    Test( Validator_short.Get( 2 ), 2,
+			    
+			    new short[][] { new short[] { 0, 0 }, new short[] { 0, 0 } } );
+    		
+		    Test( Validator_short.Get( 2 ), 2,
+			  
+			    new short[][] { new short[] { 1, 1 }, new short[] { 1, 1 } } );
+    		
+		    Test( Validator_short.Get( 2 ), 2,
+			   
+			    new short[][] { new short[] { -1, -1 }, new short[] { -1, -1 } } );
+    		
+		    Test( Validator_short.Get( 2 ), 2,
+			  
+			    new short[][] { new short[] { SByte.MaxValue, SByte.MaxValue }, new short[] { SByte.MaxValue, SByte.MaxValue } } );
+    		
+		    Test( Validator_short.Get( 2 ), 2,
+			  
+			    new short[][] { new short[] { SByte.MinValue, SByte.MinValue }, new short[] { SByte.MinValue, SByte.MinValue } } );
+    		
+		    Test( Validator_short.Get( 2 ), 2,
+			   
+                new short[][] { new short[] { short.MaxValue, short.MaxValue }, new short[] { short.MaxValue, short.MaxValue } } );
+    		
+		    Test( Validator_short.Get( 2 ), 2,
+			    
+                new short[][] { new short[] { short.MinValue, short.MinValue }, new short[] { short.MinValue, short.MinValue } } );
+	    }
+
+	    
+	    [Test]
+	    public void Test_int()
+	    {
+		    Test( Validator_int.Get( 2 ), 2,
+			    
+			    new int[][] { new int[] { 0, 0 }, new int[] { 0, 0 } } );
+    		
+		    Test( Validator_int.Get( 2 ), 2,
+			   
+			    new int[][] { new int[] { 1, 1 }, new int[] { 1, 1 } } );
+    		
+		    Test( Validator_int.Get( 2 ), 2,
+			   
+			    new int[][] { new int[] { -1, -1 }, new int[] { -1, -1 } } );
+    		
+		    Test( Validator_int.Get( 2 ), 2,
+			    
+			    new int[][] { new int[] { SByte.MaxValue, SByte.MaxValue }, new int[] { SByte.MaxValue, SByte.MaxValue } } );
+    		
+		    Test( Validator_int.Get( 2 ), 2,
+			    
+			    new int[][] { new int[] { SByte.MinValue, SByte.MinValue }, new int[] { SByte.MinValue, SByte.MinValue } } );
+    		
+		    Test( Validator_int.Get( 2 ), 2,
+			    
+			    new int[][] { new int[] { short.MaxValue, short.MaxValue }, new int[] { short.MaxValue, short.MaxValue } } );
+    		
+		    Test( Validator_int.Get( 2 ), 2,
+			   
+			    new int[][] { new int[] { short.MinValue, short.MinValue }, new int[] { short.MinValue, short.MinValue } } );
+    		
+		    Test( Validator_int.Get( 2 ), 2,
+			  
+			    new int[][] { new int[] { int.MaxValue, int.MaxValue }, new int[] { int.MaxValue, int.MaxValue} } );
+    		
+		    Test( Validator_int.Get( 2 ), 2,
+			   
+			    new int[][] { new int[] { int.MinValue, int.MinValue }, new int[] { int.MinValue, int.MinValue } } );
+	    }
+
+	    
+	    [Test]
+	    public void Test_long()
+	    {
+		    Test( Validator_long.Get( 2 ), 2,
+			   
+			    new long[][] { new long[] { 0, 0 }, new long[] { 0, 0 } } );
+    		
+		    Test( Validator_long.Get( 2 ), 2,
+			   
+			    new long[][] { new long[] { 1, 1 }, new long[] { 1, 1 } } );
+    		
+		    Test( Validator_long.Get( 2 ), 2,
+			   
+			    new long[][] { new long[] { -1, -1 }, new long[] { -1, -1 } } );
+    		
+		    Test( Validator_long.Get( 2 ), 2,
+			   
+			    new long[][] { new long[] { SByte.MaxValue, SByte.MaxValue }, new long[] { SByte.MaxValue, SByte.MaxValue } } );
+    		
+		    Test( Validator_long.Get( 2 ), 2,
+			    
+			    new long[][] { new long[] { SByte.MinValue, SByte.MinValue }, new long[] { SByte.MinValue, SByte.MinValue } } );
+    		
+		    Test( Validator_long.Get( 2 ), 2,
+			  
+			    new long[][] { new long[] { short.MaxValue, short.MaxValue }, new long[] { short.MaxValue, short.MaxValue } } );
+    		
+		    Test( Validator_long.Get( 2 ), 2,
+			  
+			    new long[][] { new long[] { short.MinValue, short.MinValue }, new long[] { short.MinValue, short.MinValue } } );
+    		
+		    Test( Validator_long.Get( 2 ), 2,
+			
+			    new long[][] { new long[] { int.MaxValue, int.MaxValue }, new long[] { int.MaxValue, int.MaxValue } } );
+    		
+		    Test( Validator_long.Get( 2 ), 2,
+			  
+			    new long[][] { new long[] { int.MinValue, int.MinValue }, new long[] { int.MinValue, int.MinValue } } );
+    		
+		    Test( Validator_long.Get( 2 ), 2,
+			 
+			    new long[][] { new long[] { long.MaxValue, long.MaxValue }, new long[] { long.MaxValue, long.MaxValue } } );
+    		
+		    Test( Validator_long.Get( 2 ), 2,
+		
+			    new long[][] { new long[] { long.MinValue, long.MinValue }, new long[] { long.MinValue, long.MinValue } } );
+	    }
+
+	    
+	    [Test]
+	    public void Test_float()
+	    {
+		    Test( Validator_float.Get( 2 ), 2,
+			   
+			    new float[][] { new float[] { 0, 0 }, new float[] { 0, 0 } } );
+    		
+		    Test( Validator_float.Get( 2 ), 2,
+			   
+			    new float[][] { new float[] { 1, 1 }, new float[] { 1, 1 } } );
+    		
+		    Test( Validator_float.Get( 2 ), 2,
+			  
+			    new float[][] { new float[] { -1, -1 }, new float[] { -1, -1 } } );
+    		
+		    Test( Validator_float.Get( 2 ), 2,
+			 
+			    new float[][] { new float[] { float.MaxValue, float.MaxValue }, new float[] { float.MaxValue, float.MaxValue } } );
+    		
+		    Test( Validator_float.Get( 2 ), 2,
+			 
+			    new float[][] { new float[] { float.MinValue, float.MinValue }, new float[] { float.MinValue, float.MinValue } } );
+	    }
+
+	    
+	    [Test]
+	    public void Test_double()
+	    {
+		    Test( Validator_double.Get( 2 ), 2,
+			   
+			    new double[][] { new double[] { 0, 0 }, new double[] { 0, 0 } } );
+    		
+		    Test( Validator_double.Get( 2 ), 2,
+			   
+			    new double[][] { new double[] { 1, 1 }, new double[] { 1, 1 } } );
+    		
+		    Test( Validator_double.Get( 2 ), 2,
+			   
+			    new double[][] { new double[] { -1, -1 }, new double[] { -1, -1 } } );
+    		
+		    Test( Validator_double.Get( 2 ), 2,
+			   
+			    new double[][] { new double[] { Double.MaxValue, Double.MaxValue }, new double[] { Double.MaxValue, Double.MaxValue } } );
+    		
+		    Test( Validator_double.Get( 2 ), 2,
+			   
+			    new double[][] { new double[] { Double.MinValue, Double.MinValue }, new double[] { Double.MinValue, Double.MinValue } } );
+	    }
+
+	    
+	    [Test]
+	    public void Test_string()
+	    {
+		    Test( Validator_string.Get( 2 ), 2,
+			  
+			    new String[][] { new String[] { "", "" }, new String[] { "", "" } } );
+    		
+		    Test( Validator_string.Get( 2 ), 2,
+			  
+			    new String[][] { new String[] { "abc", "abc" }, new String[] { "abc", "abc" } } );
+	    }
+
+	    
+	    [Test]
+	    public void Test_custom()
+	    {
+            Test( Validator_custom.Get( typeof( DateTime ), 2 ,false), 2,
+               
+                new DateTime[][] { new DateTime[] { new DateTime(), new DateTime() }, new DateTime[] { new DateTime(), new DateTime() } } );
+	    }
+    	
+	    private void Test( Validator v, int n, Object o )
+	    {
+    //		System.out.printf( "Testing with %s\n", v );
+    //		Assert.assertEquals( n, v.GetDim() );
+    		
+		    Assert.IsTrue( v.Validate( o ) );
+		  
+    		
+		    if (n > 0)
+		    {
+
+
+                int k = ( ( Array ) o ).Length;
+                for ( int i = 0; i < k; i++ )
+                    Test( v.ElementValidator(), n-1, ( ( Array ) o ).GetValue( i ) );
+		    }
+	    }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Transport/Filter/TestKeepAlive.cs b/binding-csharp/runtime/src/test/csharp/Etch/Transport/Filter/TestKeepAlive.cs
new file mode 100644
index 0000000..bf23690
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Transport/Filter/TestKeepAlive.cs
@@ -0,0 +1,357 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Threading;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Filter
+{
+    [TestFixture]
+    public class TestKeepAlive
+    {
+        private MyTransport transport;
+        private MySession session;
+        private MyValueFactory vf;
+        private Resources resources;
+
+        [SetUp]
+        public void Initialize()
+        {
+            transport = new MyTransport();
+            session = new MySession();
+            vf = new MyValueFactory("tcp:");
+            resources = new Resources();
+            resources.Add(TransportConsts.VALUE_FACTORY, vf);
+        }
+
+        private KeepAlive newKeepAlive(string uri)
+        {
+            return new KeepAlive(transport, new URL(uri), resources);
+        }
+
+        [Test]
+        public void Constructor1()
+        {
+            transport.is_server = true;
+            string uri = "tcp://localhost:4008?filter=KeepAlive";
+            KeepAlive filter = newKeepAlive(uri);
+
+            filter.SetSession(session);
+
+            Assert.AreSame(transport.GetSession(), filter);
+            Assert.AreSame(filter.GetSession(), session);
+            Assert.AreEqual(filter.GetServer(), true);
+            Assert.AreEqual(filter.GetCount(), 4);
+            Assert.AreEqual(filter.GetDelay(), 15);
+        }
+
+        [Test]
+        public void constructor2()
+        {
+            transport.is_server = true;
+            String uri = "tcp://localhost:4008?filter=KeepAlive&KeepAlive.delay=20&KeepAlive.count=5";
+            KeepAlive filter = newKeepAlive(uri);
+            filter.SetSession(session);
+
+            Assert.AreSame(transport.GetSession(), filter);
+            Assert.AreSame(filter.GetSession(), session);
+            Assert.AreEqual(filter.GetServer(), true);
+            Assert.AreEqual(filter.GetCount(), 5);
+            Assert.AreEqual(filter.GetDelay(), 20);
+        }
+
+        [Test]
+        public void constructor3()
+        {
+            transport.is_server = false;
+            String uri = "tcp://localhost:4008?filter=KeepAlive";
+            KeepAlive filter = newKeepAlive(uri);
+            filter.SetSession(session);
+
+            Assert.AreSame(transport.GetSession(), filter);
+            Assert.AreSame(filter.GetSession(), session);
+            Assert.AreEqual(filter.GetServer(), false);
+            Assert.AreEqual(filter.GetCount(), 4);
+            Assert.AreEqual(filter.GetDelay(), 15);
+        }
+
+        [Test]
+        public void clientup()
+        {
+            transport.is_server = false;
+            string uri = "tcp://localhost:4008?filter=KeepAlive&KeepAlive.delay=3";
+            KeepAlive filter = newKeepAlive(uri);
+            filter.SetSession(session);
+            filter.SessionNotify(SessionConsts.UP);
+            Console.WriteLine("Sleeping for 5 seconds");
+            Thread.Sleep(5000);
+            Console.WriteLine("Out of sleep");
+            Assert.AreEqual(What.TRANSPORT_MESSAGE, transport.what);
+            Message msg = transport.msg;
+            Assert.AreEqual("_Etch_KeepAliveReq", msg.GetXType.Name);
+            Assert.AreEqual(4, msg.Get(new Field("count")));
+            Assert.AreEqual(3, msg.Get(new Field("delay")));
+        }
+
+        [Test]
+        public void clientup1()
+        {
+            transport.is_server = false;
+            string uri = "tcp://localhost:4008?filter=KeepAlive&KeepAlive.delay=2";
+            KeepAlive filter = newKeepAlive(uri);
+            filter.SetSession(session);
+            filter.SessionNotify(SessionConsts.UP);
+            Console.WriteLine("Sleeping for 4 seconds");
+            Thread.Sleep(4000);
+            Console.WriteLine("Out of sleep");
+            Assert.AreEqual(What.TRANSPORT_MESSAGE, transport.what);
+            Message msg = transport.msg;
+            Assert.AreEqual("_Etch_KeepAliveReq", msg.GetXType.Name);
+            Assert.AreEqual(4, msg.Get(new Field("count")));
+            Assert.AreEqual(2, msg.Get(new Field("delay")));
+        }
+
+        [Test]
+        public void clientdown()
+        {
+            transport.is_server = false;
+            string uri = "tcp://localhost:4008?filter=KeepAlive";
+            KeepAlive filter = newKeepAlive(uri);
+            filter.SetSession(session);
+            filter.SessionNotify(SessionConsts.DOWN);
+            Assert.IsFalse(session.up);
+        }
+
+        [Test]
+        public void serverUp()
+        {
+            transport.is_server = true;
+            string uri = "tcp://localhost:4008?filter=KeepAlive";
+            KeepAlive filter = newKeepAlive(uri);
+            filter.SetSession(session);
+            filter.SessionNotify(SessionConsts.UP);
+            Message req = ConstructMessage();
+
+            filter.SessionMessage(null, req);
+
+            Assert.AreEqual(req.Reply().ToString(), transport.msg.ToString());
+        }
+
+        [Test]
+        public void serverdown()
+        {
+            transport.is_server = true;
+            string uri = "tcp://localhost:4008?filter=KeepAlive";
+            KeepAlive filter = newKeepAlive(uri);
+            filter.SetSession(session);
+            filter.SessionNotify(SessionConsts.DOWN);
+            Assert.IsFalse(session.up);
+        }
+
+        private Message ConstructMessage()
+        {
+            int delay = 15;
+            int count = 4;
+
+            MyValueFactory vf1 = new MyValueFactory("tcp:");
+
+            Field mf_delay = new Field("delay");
+            Field mf_count = new Field("count");
+
+            XType mt_request = new XType("_Etch_KeepAliveReq");
+            mt_request.PutValidator(mf_delay, Validator_int.Get(0));
+            mt_request.PutValidator(mf_count, Validator_int.Get(0));
+            vf1.AddType(mt_request);
+
+            XType mt_response = new XType("_Etch_KeepAliveResp");
+            vf1.AddType(mt_response);
+
+            mt_request.SetResult(mt_response);
+
+            Message msg = new Message(mt_request, vf1);
+            msg.Add(mf_delay, delay);
+            msg.Add(mf_count, count);
+
+            return msg;
+        }
+
+        public enum What
+        {
+            TRANSPORT_MESSAGE,
+            SESSION_MESSAGE
+        }
+
+        static Object cook(Object o)
+        {
+            if (o is Exception)
+            {
+                Exception e = (Exception)o;
+                e.GetBaseException();
+                throw e;
+            }
+            return o;
+        }
+
+        public class MyTransport : TransportMessage
+        {
+
+            public What what;
+
+            public Who recipient;
+
+            public Message msg;
+
+            public Object is_server;
+
+            private SessionMessage session;
+
+
+            #region TransportMessage Members
+
+            public void TransportMessage(Who recipient, Org.Apache.Etch.Bindings.Csharp.Msg.Message msg)
+            {
+                this.what = What.TRANSPORT_MESSAGE;
+                this.recipient = recipient;
+                this.msg = msg;
+            }
+
+            #endregion
+
+            #region Transport<SessionMessage> Members
+
+            public object TransportQuery(object query)
+            {
+                if ((string)query == TransportConsts.IS_SERVER)
+                    return cook(is_server);
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void TransportControl(object control, object value)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void TransportNotify(object eventObj)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SetSession(SessionMessage session)
+            {
+                this.session = session;
+            }
+
+            public SessionMessage GetSession()
+            {
+                return session;
+            }
+
+            #endregion
+        }
+
+        public class MySession : SessionMessage
+        {
+
+
+            public What what;
+
+            public Who sender;
+
+            public Message msg;
+
+            public bool handled;
+
+            public Object user;
+
+            public Object password;
+
+            public Boolean up;
+
+
+
+            #region SessionMessage Members
+
+            public bool SessionMessage(Who sender, Org.Apache.Etch.Bindings.Csharp.Msg.Message msg)
+            {
+                this.what = What.SESSION_MESSAGE;
+                this.sender = sender;
+                this.msg = msg;
+                return handled;
+            }
+
+            #endregion
+
+            #region Session Members
+
+            public object SessionQuery(object query)
+            {
+                return query;
+            }
+
+            public void SessionControl(object control, object value)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SessionNotify(object eventObj)
+            {
+                if (eventObj.Equals(SessionConsts.UP))
+                {
+                    up = true;
+                    return;
+                }
+
+                if (eventObj.Equals(SessionConsts.DOWN))
+                {
+                    up = false;
+                    return;
+                }
+
+
+
+                
+            }
+
+            #endregion
+        }
+
+        public class MyValueFactory : DefaultValueFactory
+        {
+
+            public MyValueFactory(String uri)
+                : base(uri, types, class2type)
+            {
+            }
+
+            private readonly static TypeMap types = new TypeMap();
+
+            private readonly static Class2TypeMap class2type = new Class2TypeMap();
+
+            static MyValueFactory()
+            {
+                DefaultValueFactory.Init(types, class2type);
+            }
+
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Transport/Filter/TestLogger.cs b/binding-csharp/runtime/src/test/csharp/Etch/Transport/Filter/TestLogger.cs
new file mode 100644
index 0000000..da31490
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Transport/Filter/TestLogger.cs
@@ -0,0 +1,290 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Filter
+{
+    [TestFixture]
+    public class TestLogger
+    {
+        private MyTransport transport;
+        private MySession session;
+        private MyValueFactory vf;
+        private Resources resources;
+
+        [SetUp]
+        public void Initialize()
+        {
+            transport = new MyTransport();
+            session = new MySession();
+            vf = new MyValueFactory("tcp:");
+            resources = new Resources();
+            resources.Add(TransportConsts.VALUE_FACTORY, vf);
+        }
+
+        private Logger newLogger(string uri) 
+	    {
+		    return new Logger(transport,new URL(uri),null);
+	    }
+
+        [Test]
+	    public void constructor1() {
+		    String uri = "tcp://localhost:4008?filter=Logger";
+		    Logger.testFlag = true;
+		    Logger logger = newLogger(uri);
+		    Assert.AreEqual(logger.GetFileName(),"Log.txt");
+            Assert.AreNotSame(logger.GetFileName(),logger.GetTestRenamedFileName());
+	    }
+
+        [Test]
+        public void constructor2()
+        {
+            String uri = "tcp://localhost:4008?filter=Logger&Logger.filePath=Test.txt";
+            Logger.testFlag = true;
+            Logger logger = newLogger(uri);
+            Assert.AreEqual(logger.GetFileName(), "Test.txt");
+            Assert.AreNotSame(logger.GetFileName(), logger.GetTestRenamedFileName());
+        }
+
+        [Test]
+	    public void logger() {
+		    String uri = "tcp://localhost:4008?filter=Logger";
+		    Logger.testFlag = true;
+		    Logger logger = newLogger(uri);
+		    logger.SetSession( session );
+		    Assert.AreSame(transport.GetSession(),logger);
+		    Assert.AreSame(logger.GetSession(),session);
+	    }
+
+        [Test]
+        public void logger1()
+        {
+            String uri = "tcp://localhost:4008?filter=Logger";
+            Logger.testFlag = true;
+            Logger logger = newLogger(uri);
+            logger.SetSession(session);
+            Assert.AreSame(transport.GetSession(), logger);
+            Assert.AreSame(logger.GetSession(), session);
+            Message m = constructMessage();
+            logger.TransportMessage(null,m);
+            Assert.AreEqual(m.ToString(),transport.msg.ToString());
+        }
+
+        [Test]
+        public void logger2()
+        {
+            String uri = "tcp://localhost:4008?filter=Logger";
+            Logger.testFlag = true;
+            Logger logger = newLogger(uri);
+            logger.SetSession(session);
+            Assert.AreSame(transport.GetSession(), logger);
+            Assert.AreSame(logger.GetSession(), session);
+            Message m = constructMessage();
+            logger.SessionMessage(null, m);
+            Assert.AreEqual(m.ToString(), session.msg.ToString());
+        }
+
+        private Message constructMessage()
+	    {	
+		    XType mt_request = new XType( "_Etch_Logger_Test" );
+		
+		
+		    XType mt_response = new XType( "_Etch_Logger_Test_Resp" );
+			
+		    mt_request.SetResult( mt_response );
+		
+		    vf.AddType( mt_request);
+		
+		    Message msg = new Message( mt_request, vf );
+	
+		    return msg;
+	}
+
+
+        public enum What
+        {
+            TRANSPORT_MESSAGE,
+            SESSION_MESSAGE
+        }
+
+        static Object cook(Object o)
+        {
+            if (o is Exception)
+            {
+                Exception e = (Exception)o;
+                e.GetBaseException();
+                throw e;
+            }
+            return o;
+        }
+
+        public class MyTransport : TransportMessage
+        {
+
+            public What what;
+
+            public Who recipient;
+
+            public Message msg;
+
+            public Object is_server;
+
+            private SessionMessage session;
+
+
+            #region TransportMessage Members
+
+            public void TransportMessage(Who recipient, Org.Apache.Etch.Bindings.Csharp.Msg.Message msg)
+            {
+                this.what = What.TRANSPORT_MESSAGE;
+                this.recipient = recipient;
+                this.msg = msg;
+            }
+
+            #endregion
+
+            #region Transport<SessionMessage> Members
+
+            public object TransportQuery(object query)
+            {
+                if ((string)query == TransportConsts.IS_SERVER)
+                    return cook(is_server);
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void TransportControl(object control, object value)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void TransportNotify(object eventObj)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SetSession(SessionMessage session)
+            {
+                this.session = session;
+            }
+
+            public SessionMessage GetSession()
+            {
+                return session;
+            }
+
+            #endregion
+        }
+
+        public class MySession : SessionMessage
+        {
+
+
+            public What what;
+
+            public Who sender;
+
+            public Message msg;
+
+            public bool handled;
+
+            public Object user;
+
+            public Object password;
+
+            public Boolean up;
+
+
+
+            #region SessionMessage Members
+
+            public bool SessionMessage(Who sender, Org.Apache.Etch.Bindings.Csharp.Msg.Message msg)
+            {
+                this.what = What.SESSION_MESSAGE;
+                this.sender = sender;
+                this.msg = msg;
+                return handled;
+            }
+
+            #endregion
+
+            #region Session Members
+
+            public object SessionQuery(object query)
+            {
+                return query;
+            }
+
+            public void SessionControl(object control, object value)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SessionNotify(object eventObj)
+            {
+                if (eventObj.Equals(SessionConsts.UP))
+                {
+                    up = true;
+                    return;
+                }
+
+                if (eventObj.Equals(SessionConsts.DOWN))
+                {
+                    up = false;
+                    return;
+                }
+
+
+
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+        }
+
+        public class MyValueFactory : DefaultValueFactory
+        {
+
+            public MyValueFactory(String uri)
+                : base(uri, types, class2type)
+            {
+            }
+
+            private readonly static TypeMap types = new TypeMap();
+
+            private readonly static Class2TypeMap class2type = new Class2TypeMap();
+
+            static MyValueFactory()
+            {
+                DefaultValueFactory.Init(types, class2type);
+            }
+
+        }
+
+
+
+
+
+
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Transport/Filter/TestPwAuth.cs b/binding-csharp/runtime/src/test/csharp/Etch/Transport/Filter/TestPwAuth.cs
new file mode 100644
index 0000000..dbdb0df
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Transport/Filter/TestPwAuth.cs
@@ -0,0 +1,432 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Filter
+{
+    [TestFixture]
+    public class TestPwAuth
+    {
+        private MyTransport transport;
+        private  MySession session;
+        private MyValueFactory vf;
+        private  Resources resources;
+
+        [SetUp]
+        public void Initialize()
+        {
+            transport = new MyTransport();
+            session = new MySession();
+            vf = new MyValueFactory("tcp:");
+            resources = new Resources();
+            resources.Add(TransportConsts.VALUE_FACTORY, vf);
+        }
+
+        private PwAuth newPwAuth( String uri ) 
+	    {
+		    return new PwAuth( transport, new URL( uri ), resources );
+	    }
+
+        [Test]
+        public void Constructor1()
+        {
+            transport.is_server = true;
+            PwAuth pwAuth = newPwAuth("tcp://fred:1234@host:9999");
+            pwAuth.SetSession(session);
+            Assert.AreSame(pwAuth,transport.GetSession());
+            Assert.AreSame(session, pwAuth.GetSession());
+            Assert.AreEqual(true,pwAuth.GetServer());
+            Assert.IsNull(pwAuth.TransportQuery(PwAuth.USER));
+            Assert.IsNull(pwAuth.TransportQuery(PwAuth.PASSWORD));
+        }
+
+        [Test]
+        public void Constructor2()
+        {
+            transport.is_server = false;
+            PwAuth pwAuth = newPwAuth("tcp://fred:1234@host:9999");
+            pwAuth.SetSession(session);
+            Assert.AreSame(pwAuth, transport.GetSession());
+            Assert.AreSame(session, pwAuth.GetSession());
+            Assert.AreEqual(false, pwAuth.GetServer());
+            Assert.AreEqual("fred",pwAuth.TransportQuery(PwAuth.USER));
+            Assert.AreEqual("1234", pwAuth.TransportQuery(PwAuth.PASSWORD));
+        }
+
+        [Test]
+        public void Constructor3()
+        {
+            transport.is_server = false;
+            PwAuth pwAuth = newPwAuth("tcp://mary:2345@host:9999");
+            pwAuth.SetSession(session);
+            Assert.AreSame(pwAuth, transport.GetSession());
+            Assert.AreSame(session, pwAuth.GetSession());
+            Assert.AreEqual(false, pwAuth.GetServer());
+            Assert.AreEqual("mary", pwAuth.TransportQuery(PwAuth.USER));
+            Assert.AreEqual("2345", pwAuth.TransportQuery(PwAuth.PASSWORD));
+        }
+
+        [Test]
+        public void Constructor4()
+        {
+            transport.is_server = false;
+            PwAuth pwAuth = newPwAuth("tcp://alice@host:9999");
+            pwAuth.SetSession(session);
+            Assert.AreSame(pwAuth, transport.GetSession());
+            Assert.AreSame(session, pwAuth.GetSession());
+            Assert.AreEqual(false, pwAuth.GetServer());
+            Assert.AreEqual("alice", pwAuth.TransportQuery(PwAuth.USER));
+            Assert.IsNull(pwAuth.TransportQuery(PwAuth.PASSWORD));
+        }
+
+        [Test]
+        public void Constructor5()
+        {
+            transport.is_server = false;
+            PwAuth pwAuth = newPwAuth("tcp://host:9999");
+            pwAuth.SetSession(session);
+            Assert.AreSame(pwAuth, transport.GetSession());
+            Assert.AreSame(session, pwAuth.GetSession());
+            Assert.AreEqual(false, pwAuth.GetServer());
+            Assert.IsNull(pwAuth.TransportQuery(PwAuth.USER));
+            Assert.IsNull(pwAuth.TransportQuery(PwAuth.PASSWORD));
+        }
+
+        [Test]
+        [ExpectedException(typeof(Exception))]
+        public void Constructor6()
+        {
+            transport.is_server = new Exception("is_server failed");
+            PwAuth pwAuth = newPwAuth("tcp://fred:1234@host:9999");
+            
+        }
+
+        [Test]
+        public void Clientup1()
+        {
+            transport.is_server = false;
+            PwAuth pwAuth = newPwAuth("tcp://fred:1234@host:9999");
+            pwAuth.SetSession(session);
+            pwAuth.SessionNotify(SessionConsts.UP);
+            Assert.IsTrue(session.up);
+            Assert.AreEqual(What.TRANSPORT_MESSAGE, transport.what);
+            Message msg1 = transport.msg;
+            Assert.AreEqual("_Etch_PwAuthReq", msg1.GetXType.Name);
+            Assert.AreEqual("fred",msg1.Get(new Field("user")));
+            Assert.AreEqual("1234", msg1.Get(new Field("password")));
+        }
+
+        [Test]
+        public void Clientup2()
+        {
+            transport.is_server = false;
+            session.password = "2345";
+            PwAuth pwAuth = newPwAuth("tcp://fred@host:9999");
+            pwAuth.SetSession(session);
+            pwAuth.SessionNotify(SessionConsts.UP);
+            Assert.IsTrue(session.up);
+            Assert.AreEqual(What.TRANSPORT_MESSAGE, transport.what);
+            Message msg1 = transport.msg;
+            Assert.AreEqual("_Etch_PwAuthReq", msg1.GetXType.Name);
+            Assert.AreEqual("fred", msg1.Get(new Field("user")));
+            Assert.AreEqual("2345", msg1.Get(new Field("password")));
+        }
+
+        [Test]
+        public void Clientup3()
+        {
+            transport.is_server = false;
+            session.user = "mary";
+            session.password = "3456";
+            PwAuth pwAuth = newPwAuth("tcp://host:9999");
+            pwAuth.SetSession(session);
+            pwAuth.SessionNotify(SessionConsts.UP);
+            Assert.IsTrue(session.up);
+            Assert.AreEqual(What.TRANSPORT_MESSAGE, transport.what);
+            Message msg1 = transport.msg;
+            Assert.AreEqual("_Etch_PwAuthReq", msg1.GetXType.Name);
+            Assert.AreEqual("mary", msg1.Get(new Field("user")));
+            Assert.AreEqual("3456", msg1.Get(new Field("password")));
+        }
+
+        [Test]
+        [ExpectedException(typeof(Exception))]
+        public void Clientup4()
+        {
+            transport.is_server = false;
+            session.user = "mary";
+            PwAuth pwAuth = newPwAuth("tcp://host:9999");
+            pwAuth.SetSession(session);
+            pwAuth.SessionNotify(SessionConsts.UP);         
+        }
+
+        [Test]
+        [ExpectedException(typeof(Exception))]
+        public void Clientup5()
+        {
+            transport.is_server = false;
+            session.password = "1234";
+            PwAuth pwAuth = newPwAuth("tcp://host:9999");
+            pwAuth.SetSession(session);
+            pwAuth.SessionNotify(SessionConsts.UP);         
+        }
+
+        [Test]
+        [ExpectedException(typeof(Exception))]
+        public void Clientup6()
+        {
+            transport.is_server = false;
+            session.user = "fred";
+            session.password = new Exception("password failed");
+            PwAuth pwAuth = newPwAuth("tcp://host:9999");
+            pwAuth.SetSession(session);
+            pwAuth.SessionNotify(SessionConsts.UP);
+        }
+
+        [Test]
+        [ExpectedException(typeof(Exception))]
+        public void Clientup7()
+        {
+            transport.is_server = false;
+            session.user = new Exception("user failed");
+            session.password = "1234";
+            PwAuth pwAuth = newPwAuth("tcp://host:9999");
+            pwAuth.SetSession(session);
+            pwAuth.SessionNotify(SessionConsts.UP);
+        }
+
+        [Test]
+        public void Clientdown1()
+        {
+            transport.is_server = false;
+            
+            PwAuth pwAuth = newPwAuth("tcp://host:9999");
+            pwAuth.SetSession(session);
+            pwAuth.SessionNotify(SessionConsts.DOWN);
+
+            Assert.IsFalse(session.up);
+        }
+
+
+        [Test]
+        public void Serverup1()
+        {
+            transport.is_server = true;
+
+            PwAuth pwAuth = newPwAuth("tcp://host:9999");
+            pwAuth.SetSession(session);
+            pwAuth.SessionNotify(SessionConsts.UP);
+
+            Assert.IsTrue(session.up);
+        }
+
+        [Test]
+        public void Serverdown1()
+        {
+            transport.is_server = true;
+
+            PwAuth pwAuth = newPwAuth("tcp://host:9999");
+            pwAuth.SetSession(session);
+            pwAuth.SessionNotify(SessionConsts.DOWN);
+
+            Assert.IsFalse(session.up);
+            Assert.IsNull(session.userPassword.user);
+            Assert.IsNull(session.userPassword.password);
+        }
+
+
+
+        public enum What
+        {
+            TRANSPORT_MESSAGE,
+            SESSION_MESSAGE
+        }
+
+        static Object cook( Object o ) 
+	    {
+		if (o is Exception)
+		{
+			Exception e = (Exception) o;
+		    e.GetBaseException();
+			throw e;
+		}
+		return o;
+	    }
+
+        public class MyTransport : TransportMessage
+        {
+
+            /** */
+            public What what;
+            /** */
+            public Who recipient;
+            /** */
+            public Message msg;
+            /** */
+            public Object is_server;
+
+            private SessionMessage session;
+
+
+            #region TransportMessage Members
+
+            public void TransportMessage(Who recipient, Org.Apache.Etch.Bindings.Csharp.Msg.Message msg)
+            {
+                this.what = What.TRANSPORT_MESSAGE;
+                this.recipient = recipient;
+                this.msg = msg;
+            }
+
+            #endregion
+
+            #region Transport<SessionMessage> Members
+
+            public object TransportQuery(object query)
+            {
+                if ((string)query == TransportConsts.IS_SERVER)
+                    return cook(is_server); 
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void TransportControl(object control, object value)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void TransportNotify(object eventObj)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SetSession(SessionMessage session)
+            {
+                this.session = session;
+            }
+
+            public SessionMessage GetSession()
+            {
+                return session;
+            }
+
+            #endregion
+        }
+
+        public class MySession : SessionMessage
+        {
+
+            /** */
+            public What what;
+            /** */
+            public Who sender;
+            /** */
+            public Message msg;
+            /** */
+            public bool handled;
+            /** */
+            public Object user;
+            /** */
+            public Object password;
+            /** */
+            public Boolean up;
+            /** */
+            public PwAuth.UserPassword 
+                userPassword = new PwAuth.UserPassword(null,null);
+
+            #region SessionMessage Members
+
+            public bool SessionMessage(Who sender, Org.Apache.Etch.Bindings.Csharp.Msg.Message msg)
+            {
+                this.what = What.SESSION_MESSAGE;
+                this.sender = sender;
+                this.msg = msg;
+                return handled;
+            }
+
+            #endregion
+
+            #region Session Members
+
+            public object SessionQuery(object query)
+            {
+                if ((string)query == PwAuth.USER)
+                    return cook(user);
+
+                if ((string)query == PwAuth.PASSWORD)
+                    return cook(password);
+			
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SessionControl(object control, object value)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SessionNotify(object eventObj)
+            {
+                if (eventObj.Equals(SessionConsts.UP))
+			    {
+				    up = true;
+				    return;
+			    }
+
+                if (eventObj.Equals(SessionConsts.DOWN))
+			    {
+				    up = false;
+				    return;
+			    }
+    			
+			    if (eventObj is PwAuth.UserPassword)
+			    {
+				    userPassword = (PwAuth.UserPassword) eventObj;
+				    return;
+			    }
+
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+        }
+
+        public class MyValueFactory : DefaultValueFactory
+        {
+
+            public MyValueFactory( String uri ) : base(uri, types, class2type)
+		    {
+			}
+		
+		    private readonly static TypeMap types = new TypeMap();
+		
+		    private readonly static Class2TypeMap class2type = new Class2TypeMap();
+
+		    static MyValueFactory()
+		    {
+			    DefaultValueFactory.Init( types, class2type );
+		    }
+            
+        }
+
+
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Transport/Fmt/Binary/TestBinaryTaggedDataInOut.cs b/binding-csharp/runtime/src/test/csharp/Etch/Transport/Fmt/Binary/TestBinaryTaggedDataInOut.cs
new file mode 100644
index 0000000..4af00c9
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Transport/Fmt/Binary/TestBinaryTaggedDataInOut.cs
@@ -0,0 +1,1004 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport.Fmt.Binary
+{
+    /// <summary>
+    /// Test binary input and output.
+    /// </summary>
+     [TestFixture]
+    public class TestBinaryTaggedDataInOut
+    {
+
+    //    private static readonly double DOUBLE_MIN_NORMAL = 0x1.0-1022; // Double.MIN_NORMAL;
+	 //   private static readonly float FLOAT_MIN_NORMAL = 0x1.0p-126f; // Float.MIN_NORMAL;
+         
+         [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine( "TestBinaryTaggedDataInOut" );
+        }
+
+        MyValueFactory vf;
+        private XType mt_foo;
+        private Field mf_x;
+
+        public TestBinaryTaggedDataInOut()
+        {
+            vf = new MyValueFactory();
+            mt_foo = vf.GetType( "foo" );
+            mf_x = new Field( "x" );
+        }
+        
+        [Test]
+        public void Test_Check_Value() 
+        {
+            BinaryTaggedDataOutput btdo = new BinaryTaggedDataOutput(vf, "none:");
+
+            foreach (sbyte i in GetBytes( SByte.MinValue, 256 ))
+			if (i >= TypeCode.MIN_TINY_INT && i <= TypeCode.MAX_TINY_INT)
+				Assert.AreEqual( i, btdo.CheckValue( i ) );
+			else
+                Assert.AreEqual(TypeCode.BYTE, btdo.CheckValue(i));
+
+            // short values
+		    foreach (short i in GetShorts( short.MinValue, 65536 ))
+			if (i >= TypeCode.MIN_TINY_INT && i <= TypeCode.MAX_TINY_INT)
+				Assert.AreEqual( (sbyte) i, btdo.CheckValue( i ) );
+			else if (i >= SByte.MinValue && i <= SByte.MaxValue)
+				Assert.AreEqual( TypeCode.BYTE, btdo.CheckValue( i ) );
+			else
+				Assert.AreEqual( TypeCode.SHORT, btdo.CheckValue( i ) );
+		
+		// int values
+		foreach (int i in GetTestInts())
+			if (i >= TypeCode.MIN_TINY_INT && i <= TypeCode.MAX_TINY_INT)
+				Assert.AreEqual( (sbyte) i, btdo.CheckValue( i ) );
+			else if (i >= SByte.MinValue && i <= SByte.MaxValue)
+				Assert.AreEqual( TypeCode.BYTE, btdo.CheckValue( i ) );
+			else if (i >= short.MinValue && i <= short.MaxValue)
+				Assert.AreEqual( TypeCode.SHORT, btdo.CheckValue( i ) );
+			else
+				Assert.AreEqual( TypeCode.INT, btdo.CheckValue( i ) );
+		
+		// long values
+		foreach (long i in GetTestLongs())
+			if (i >= TypeCode.MIN_TINY_INT && i <= TypeCode.MAX_TINY_INT)
+				Assert.AreEqual( (sbyte) i, btdo.CheckValue( i ) );
+			else if (i >= SByte.MinValue && i <= SByte.MaxValue)
+				Assert.AreEqual( TypeCode.BYTE, btdo.CheckValue( i ) );
+			else if (i >= short.MinValue && i <= short.MaxValue)
+				Assert.AreEqual( TypeCode.SHORT, btdo.CheckValue( i ) );
+			else if (i >= int.MinValue && i <= int.MaxValue)
+				Assert.AreEqual( TypeCode.INT, btdo.CheckValue( i ) );
+			else
+				Assert.AreEqual( TypeCode.LONG, btdo.CheckValue( i ) );
+
+        // null value
+        Assert.AreEqual(TypeCode.NULL, btdo.CheckValue(null));
+
+        // boolean values
+        Assert.AreEqual(TypeCode.BOOLEAN_FALSE, btdo.CheckValue(false));
+        Assert.AreEqual(TypeCode.BOOLEAN_TRUE, btdo.CheckValue(true));
+
+        // float
+        Assert.AreEqual(TypeCode.FLOAT, btdo.CheckValue(3.14159f));
+
+        // double
+        Assert.AreEqual(TypeCode.DOUBLE, btdo.CheckValue(3.14159));
+
+        // byte array
+        Assert.AreEqual(TypeCode.BYTES, btdo.CheckValue(new sbyte[0]));
+        Assert.AreEqual(TypeCode.BYTES, btdo.CheckValue(new sbyte[1]));
+
+        // string
+        Assert.AreEqual(TypeCode.EMPTY_STRING, btdo.CheckValue(""));
+        Assert.AreEqual(TypeCode.STRING, btdo.CheckValue("abc"));
+
+        // struct
+        Assert.AreEqual(TypeCode.CUSTOM, btdo.CheckValue(new StructValue(new XType("foo"), vf)));
+
+        // custom
+        Assert.AreEqual(TypeCode.CUSTOM, btdo.CheckValue(new DateTime()));
+
+        // none
+        Assert.AreEqual(TypeCode.NONE, btdo.CheckValue(BinaryTaggedData.NONE));
+
+
+         
+        }
+
+        [Test]
+        public void Test_boolean() 
+	    {
+            // 2 dimensional
+            bool[][] array1 = new bool[][] { new bool[] { false, true }, new bool[] { true, false } };
+            TestX( array1 , Validator_boolean.Get( 2 ) );
+
+            // 3 dimensional
+            TestX(
+                new bool[][][] {
+                    new bool[][] { new bool[] { true, false, false }, new bool[] { true, false, true } },
+                    new bool[][] { new bool[] { false, true, false }, new bool[] { false, true, false } },
+                    new bool[][] { new bool[] { false, false, false }, new bool[] { true, true, true } }
+                },
+                Validator_boolean.Get( 3 ) );
+	    }
+
+        [Test]
+        public void Test_byte() 
+	    {
+            // 2 dimensional
+            TestX( new sbyte[][] { new sbyte[] { SByte.MinValue, -1, 0, 1, SByte.MaxValue }, new sbyte[] { 23 } },
+                Validator_byte.Get( 2 ) );
+
+            // 3 dimensional
+            TestX(
+                new sbyte[][][] 
+                {
+                    new sbyte[][] { new sbyte[] { SByte.MinValue, -1, 0, 1, SByte.MaxValue }, new sbyte[] { 23 } },
+                    new sbyte[][] { new sbyte[] { SByte.MinValue, 1, 0, -1, SByte.MaxValue }, new sbyte[] { 23 } },
+                    new sbyte[][] { new sbyte[] { SByte.MaxValue, -1, 0, 1, SByte.MinValue }, new sbyte[] { 23 } }
+                },
+                Validator_byte.Get( 3 ) );
+	    }
+
+        [Test]
+        public void Test_short() 
+	    {
+            // 2 dimensional
+            TestX( new short[][] { new short[] { short.MinValue, SByte.MinValue, -1, 0, 1,
+			    SByte.MaxValue, short.MaxValue }, new short[] { 23 } },
+                Validator_short.Get( 2 ) );
+
+            // 3 dimensional
+            TestX( 
+                new short[][][] 
+                {
+                    new short[][] { new short[] { short.MinValue, SByte.MinValue, -1, 0, 1,
+			        SByte.MaxValue, short.MaxValue }, new short[] { 23 } },
+                    new short[][] { new short[] { short.MaxValue, SByte.MinValue, -1, 0, 1,
+			        SByte.MaxValue, short.MinValue }, new short[] { 23 } },
+                    new short[][] { new short[] { short.MaxValue, SByte.MaxValue, 1, 0, -1,
+			        SByte.MinValue, short.MinValue }, new short[] { 23 } }
+                },
+                Validator_short.Get( 3 ) );
+   
+	    }
+
+        [Test]
+        public void Test_int() 
+	    {
+
+            // 2 Dimensional
+            TestX( new int[][] { new int[] { int.MinValue, short.MinValue, SByte.MinValue,
+			    -1, 0, 1, sbyte.MaxValue, short.MaxValue, int.MaxValue}, new int[] { 23 } },
+                Validator_int.Get( 2 ) );
+
+            // 3 dimensional
+            TestX(
+                new int[][][]
+                {
+                    new int[][] { new int[] { int.MinValue, short.MinValue, SByte.MinValue,
+			        -1, 0, 1, sbyte.MaxValue, short.MaxValue, int.MaxValue}, new int[] { 23 } },
+                    new int[][] { new int[] { int.MaxValue, short.MinValue, SByte.MinValue,
+			        -1, 0, 1, sbyte.MaxValue, short.MinValue, int.MaxValue}, new int[] { 23 } },
+                    new int[][] { new int[] { int.MaxValue, short.MaxValue, SByte.MaxValue,
+			        -1, 0, 1, sbyte.MinValue, short.MinValue, int.MinValue}, new int[] { 23 } }
+                },
+                Validator_int.Get( 3 ) );
+	    }
+
+        [Test]
+        public void Test_long() 
+	    {
+            // 2 dimensional
+            TestX( new long[][] { new long[] { long.MinValue, int.MinValue, short.MinValue,
+			    SByte.MinValue, -1, 0, 1, sbyte.MaxValue, short.MaxValue,
+			    int.MaxValue, long.MaxValue}, new long[] { 23 } },
+                Validator_long.Get( 2 ) );
+
+            // 3 dimensional
+            TestX(
+                new long[][][]
+                {
+                    new long[][] { new long[] { long.MinValue, int.MinValue, short.MinValue,
+			        SByte.MinValue, -1, 0, 1, sbyte.MaxValue, short.MaxValue,
+			        int.MaxValue, long.MaxValue}, new long[] { 23 } },
+                    new long[][] { new long[] { long.MinValue, int.MaxValue, short.MaxValue,
+			        SByte.MinValue, -1, 0, 1, sbyte.MaxValue, short.MinValue,
+			        int.MinValue, long.MaxValue}, new long[] { 23 } },
+                    new long[][] { new long[] { long.MaxValue, int.MaxValue, short.MaxValue,
+			        SByte.MaxValue, -1, 0, 1, sbyte.MinValue, short.MinValue,
+			        int.MinValue, long.MinValue}, new long[] { 23 } }
+                },
+                Validator_long.Get( 3 ) );
+	    }
+
+        [Test]
+        public void Test_float() 
+	    {
+            // 2 dimensional
+            TestX( new float[][] { new float[] { -1, 0, 1, float.MinValue, float.Epsilon,
+			    float.MaxValue, float.NaN, float.NegativeInfinity,
+			    float.PositiveInfinity, -0.0f, 1.1f,
+			    3.141592653589793238462643383279f }, new float[] { 23 } },
+                Validator_float.Get( 2 ) );
+
+            // 3 dimensional
+            TestX(
+                new float[][][]
+                {
+                    new float[][] { new float[] { -1, 0, 1, float.MinValue, float.Epsilon,
+			        float.MaxValue, float.NaN, float.NegativeInfinity,
+			        float.PositiveInfinity, -0.0f, 1.1f,
+			        3.141592653589793238462643383279f }, new float[] { 23 } },
+
+                    new float[][] { new float[] { -1, 0, 1, float.MaxValue, float.Epsilon,
+			        float.MinValue, float.NaN, float.NegativeInfinity,
+			        float.PositiveInfinity, 0.0f, -1.1f,
+			        3.141592653589793238462643383279f }, new float[] { 23 } },
+
+                    new float[][] { new float[] { -1, 0, 1, float.MaxValue, float.Epsilon,
+			        float.MaxValue, float.NaN, float.PositiveInfinity,
+			        float.NegativeInfinity, -0.0f, 1.1f,
+			        -3.141592653589793238462643383279f }, new float[] { 23 } }
+                },
+                Validator_float.Get( 3 ) );
+	    }
+
+        [Test]
+        public void Test_double() 
+	    {
+            // 2 dimensional
+            TestX( new double[][] { new double[]{ -1, 0, 1, double.MinValue, double.Epsilon,
+			    double.MaxValue, double.NaN, double.NegativeInfinity,
+			    double.PositiveInfinity, -0.0f, 1.1f,
+			    3.141592653589793238462643383279 }, new double[]{ 23 } },
+                Validator_double.Get( 2 ) );
+
+            // 3 dimensional
+            TestX(
+                new double[][][]
+                {
+                    new double[][] { new double[]{ -1, 0, 1, double.MinValue, double.Epsilon,
+			        double.MaxValue, double.NaN, double.NegativeInfinity,
+			        double.PositiveInfinity, -0.0f, 1.1f,
+			        3.141592653589793238462643383279 }, new double[]{ 23 } },
+
+                    new double[][] { new double[]{ -1, 0, 1, double.MaxValue, double.Epsilon,
+			        double.MinValue, double.NaN, double.NegativeInfinity,
+			        double.PositiveInfinity, 0.0f, -1.1f,
+			        3.141592653589793238462643383279 }, new double[]{ 23 } },
+
+                    new double[][] { new double[]{ -1, 0, 1, double.MaxValue, double.Epsilon,
+			        double.MinValue, double.NaN, double.PositiveInfinity,
+			        double.NegativeInfinity, 0.0f, -1.1f,
+			        -3.141592653589793238462643383279 }, new double[]{ 23 } }
+                },
+                Validator_double.Get( 3 ) );
+	    }
+
+        [Test]
+        public void Test_String() 
+	    {
+            
+            // 2 dimensional
+            TestX( new String[][] { new String[] { "", "a", "ab", "abc" }, new String[] { "23" } },
+                Validator_string.Get( 2 ) );
+
+            // 3 dimensional
+            TestX(
+                new String[][][]
+                {
+                    new String[][] { new String[] { "", "a", "ab", "abc" }, new String[] { "23" } },
+                    new String[][] { new String[] { "abc", "ab", "a", "" }, new String[] { "23" } },
+                    new String[][] { new String[] { "ab", "abc", "", "a" }, new String[] { "23" } }
+                },
+                Validator_string.Get( 3 ) );
+	    }
+
+        [Test]
+        public void Test_Add()
+        {
+            XType add = vf.GetType( "add" );
+            
+            Field x = new Field( "x" );
+            add.PutValidator( x, Validator_int.Get( 0 ) );
+
+            Field y = new Field ("y" );
+            add.PutValidator( y, Validator_int.Get( 0 ) );
+
+            Field _mf__messageId = DefaultValueFactory._mf__messageId;
+            add.PutValidator( _mf__messageId, Validator_long.Get( 0 ) );
+
+            long msgid = 0x0102030405060708L;
+
+            Message msg = new Message( add, vf );
+            msg.Add( x, 1 );
+            msg.Add( y, 2 );
+            msg.Add( _mf__messageId, msgid );
+            testmsg2bytes(msg, null, new sbyte[] { 3, -122, 39, -23, -73, -100, 3, -122, 21, 10, 44, -77, 1, -122, 99, 6, -76, 104, -121, 1, 2, 3, 4, 5, 6, 7, 8, -122, 21, 10, 44, -76, 2, -127 });
+            testmsg2bytes(msg, false, new sbyte[] { 3, -122, 39, -23, -73, -100, 3, -122, 21, 10, 44, -77, 1, -122, 99, 6, -76, 104, -121, 1, 2, 3, 4, 5, 6, 7, 8, -122, 21, 10, 44, -76, 2, -127 });
+            testmsg2bytes(msg, true, new sbyte[] { 3, -109, 3, 97, 100, 100, 3, -109, 1, 120, 1, -109, 10, 95, 109, 101, 115, 115, 97, 103, 101, 73, 100, -121, 1, 2, 3, 4, 5, 6, 7, 8, -109, 1, 121, 2, -127 });
+
+            msg = new Message( add, vf );
+            msg.Add( x, 1000000000 );
+            msg.Add( y, 2000000000 );
+            msg.Add( _mf__messageId, msgid );
+            testmsg2bytes(msg, null, new sbyte[] { 3, -122, 39, -23, -73, -100, 3, -122, 21, 10, 44, -77, -122, 59, -102, -54, 0, -122, 99, 6, -76, 104, -121, 1, 2, 3, 4, 5, 6, 7, 8, -122, 21, 10, 44, -76, -122, 119, 53, -108, 0, -127 });
+            testmsg2bytes(msg, false, new sbyte[] { 3, -122, 39, -23, -73, -100, 3, -122, 21, 10, 44, -77, -122, 59, -102, -54, 0, -122, 99, 6, -76, 104, -121, 1, 2, 3, 4, 5, 6, 7, 8, -122, 21, 10, 44, -76, -122, 119, 53, -108, 0, -127 });
+            testmsg2bytes(msg, true, new sbyte[] { 3, -109, 3, 97, 100, 100, 3, -109, 1, 120, -122, 59, -102, -54, 0, -109, 10, 95, 109, 101, 115, 115, 97, 103, 101, 73, 100, -121, 1, 2, 3, 4, 5, 6, 7, 8, -109, 1, 121, -122, 119, 53, -108, 0, -127 });
+        }
+	
+	    private void testmsg2bytes( Message msg, bool? stringTypeAndField,
+		    sbyte[] sexpected )
+	    {
+            byte[] expected = ToSByteArray(sexpected);
+		    byte[] actual = Msg2bytes( msg, stringTypeAndField );
+		    try
+		    {
+                AssertArrayEquals(expected, actual);
+		    }
+		    catch ( Exception )
+		    {
+			    Dump( expected );
+			    Dump( actual );
+			    throw;
+		    }
+	    }
+
+        private byte[] ToSByteArray(sbyte[] a)
+        {
+            return (byte[])(Array)a;
+        }
+
+        [Test]
+        public void test_add_in() 
+	    {
+            XType add = vf.GetType( "add" );
+    		
+		    Field x = new Field( "x" );
+		    add.PutValidator( x, Validator_int.Get( 0 ) );
+    		
+		    Field y = new Field( "y" );
+		    add.PutValidator( y, Validator_int.Get( 0 ) );
+    		
+		    Field _mf__messageId = DefaultValueFactory._mf__messageId;
+		    add.PutValidator( _mf__messageId, Validator_long.Get( 0 ) );
+    		
+		    long msgid = 0x0123456789abcdefL;
+    		
+		    //sbyte[] _buf = { 1, -9, -100, -73, -23, 39, -9, 104, -76, 6, 99, -13, -17, -51, -85, -119, 103, 69, 35, 1, -9, -76, 44, 10, 21, 66, -9, -77, 44, 10, 21, 65, -22 } ;
+            sbyte[] _buf = { 3, // version
+                             -122, // INT (Type)
+			                39, -23, -73, -100, // add
+			                3, // length
+                            -122,
+			                99, 6, -76, 104,
+			                -121, // LONG (value)
+			                1, 35, 69, 103, -119, -85, -51, -17,
+			                -122, // INT (key)
+			                21, 10, 44, -76, // y
+			                2, // tiny int = 2 (value)
+			                -122, // INT (key)
+			                21, 10, 44, -77, // x
+			                1, // tiny int =1 
+			                -127 // NONE 
+                            };
+            byte[] buf = new byte[_buf.Length];
+            Buffer.BlockCopy(_buf,0,buf,0,_buf.Length);
+
+            Message msg = Bytes2msg( buf );
+		    msg.CheckType( add );
+		    Assert.AreEqual( 3, msg.Count );
+		    Assert.AreEqual( 1, msg[ x ] );
+		    Assert.AreEqual( 2, msg[ y ] );
+		    Assert.AreEqual( msgid, msg[ _mf__messageId ] );
+    		
+		    //_buf = new sbyte[] { 1, -9, -100, -73, -23, 39, -9, 104, -76, 6, 99, -13, -17, -51, -85, -119, 103, 69, 35, 1, -9, -76, 44, 10, 21, -9, 0, -108, 53, 119, -9, -77, 44, 10, 21, -9, 0, -54, -102, 59, -22 };
+           // _buf = new sbyte[] { 3, -9, 39, -23, -73, -100, -9, 99, 6, -76, 104, -13, 1, 35, 69, 103, -119, -85, -51, -17, -9, 21, 10, 44, -76, -9, 119, 53, -108, 0, -9, 21, 10, 44, -77, -9, 59, -102, -54, 0, -22 };
+            _buf = new sbyte[]
+		    {
+			    3, // version
+			    -122, // INT (type)
+			    39, -23, -73, -100, // add
+			    3, // length
+			    -122, // INT (key)
+			    99, 6, -76, 104,
+			    -121, // LONG (value)
+			    1, 35, 69, 103, -119, -85, -51, -17,
+			    -122, // INT (key)
+			    21, 10, 44, -76, // y
+			    -122, // INT (value)
+			    119, 53, -108, 0,
+			    -122, // INT (key)
+			    21, 10, 44, -77, // x
+			    -122, // INT (value)
+			    59, -102, -54, 0,
+			    -127 // NONE
+		    };
+
+          buf = new byte[_buf.Length];
+            Buffer.BlockCopy(_buf, 0, buf, 0, _buf.Length);
+
+            msg = Bytes2msg( buf ); 
+		    msg.CheckType( add );
+		    Assert.AreEqual( 3, msg.Count );
+		    Assert.AreEqual( 1000000000, msg[x ] );
+		    Assert.AreEqual( 2000000000, msg[ y ] );
+		    Assert.AreEqual( msgid, msg[ _mf__messageId ] );
+	    }
+
+
+
+        [Test]
+        public void Test_add_perf()
+        {
+            vf = new MyValueFactory();
+
+            XType add = vf.GetType( "add" );
+
+            Field x = new Field( "x" );
+            add.PutValidator( x, Validator_int.Get( 0 ) );
+
+            Field y = new Field( "y" );
+            add.PutValidator( y, Validator_int.Get( 0 ) );
+
+            Field _mf__messageId = DefaultValueFactory._mf__messageId;
+            add.PutValidator( _mf__messageId, Validator_long.Get( 0 ) );
+
+            long msgid = 0x0123456789abcdefL;
+
+            Message msg = new Message( add, vf );
+            msg.Add( x, 123456789 );
+            msg.Add( y, 876543210 );
+            msg.Add( _mf__messageId, msgid );
+            
+            Resources res = new Resources();
+            res.Add(TransportConsts.VALUE_FACTORY, vf);
+             MyPacketSource ps = new MyPacketSource();
+            Messagizer m = new Messagizer(ps,"foo:?Messagizer.format=binary", res);
+            m.TransportMessage(null,msg);
+          
+
+            int n = 900973;
+            for ( int i = 0; i < 3; i++ )
+            {
+                TestPerf( "test_add_perf", i, m, msg, n );
+            }
+        }
+
+        [Test]
+        public void Test_sum_perf()
+        {
+            XType sum = vf.GetType( "sum" );
+
+            Field values = new Field( "values" );
+            sum.PutValidator( values, Validator_int.Get( 1 ) );
+
+            Field _mf__messageId = DefaultValueFactory._mf__messageId;
+            sum.PutValidator( _mf__messageId, Validator_long.Get( 0 ) );
+
+            long msgid = 0x0123456789abcdefL;
+
+            int[] array = new int[ 2 ];
+            for ( int i = 0; i < array.Length; i++ )
+                array[ i ] = 123456789;
+
+            Message msg = new Message( sum, vf );
+            msg.Add( values, array );
+            msg.Add( _mf__messageId, msgid );
+
+            Resources res = new Resources();
+            res.Add(TransportConsts.VALUE_FACTORY, vf);
+            MyPacketSource ps = new MyPacketSource();
+            Messagizer m = new Messagizer(ps,"foo:?Messagizer.format=binary", res);
+           
+            m.TransportMessage( null, msg );
+
+            int n = 509520;
+            for (int i = 0; i < 1; i++)
+                TestPerf( "test_sum_perf", i, m, msg, n );
+        }
+
+        [Test]
+	    public void testValueToBytes()
+        {
+            assertValueToBytes(null,
+                new sbyte[] { 3, 1, 0, -127 });
+
+            assertValueToBytes(new object[] { null },
+                new sbyte[] { 3, 1, 1, 2, -111, -106, 1, 1, -128, -127, -127 });
+
+            assertValueToBytes(false,
+                new sbyte[] { 3, 1, 1, 2, -126, -127 });
+
+            assertValueToBytes(true,
+                new sbyte[] { 3, 1, 1, 2, -125, -127 });
+
+            // tiny int:
+            
+            assertValueToBytes(0,
+                new sbyte[] { 3, 1, 1, 2, 0, -127 });
+            
+            assertValueToBytes(1,
+                new sbyte[] { 3, 1, 1, 2, 1, -127 });
+            
+            assertValueToBytes(-1,
+                new sbyte[] { 3, 1, 1, 2, -1, -127 });
+
+            // byte:
+            
+            assertValueToBytes(-100,
+                new sbyte[] { 3, 1, 1, 2, -124, -100, -127 });
+
+            // short:
+            
+            assertValueToBytes(10000,
+                new sbyte[] { 3, 1, 1, 2, -123, 39, 16, -127 });
+            
+            assertValueToBytes(-10000,
+                new sbyte[] { 3, 1, 1, 2, -123, -40, -16, -127 });
+
+            // int:
+            
+            assertValueToBytes(1000000000,
+                new sbyte[] { 3, 1, 1, 2, -122, 59, -102, -54, 0, -127 });
+            
+            assertValueToBytes(-1000000000,
+                new sbyte[] { 3, 1, 1, 2, -122, -60, 101, 54, 0, -127 });
+
+            // long:
+            
+            assertValueToBytes(1000000000000000000L,
+                new sbyte[] { 3, 1, 1, 2, -121, 13, -32, -74, -77, -89, 100, 0, 0, -127 });
+            
+            assertValueToBytes(-1000000000000000000L,
+                new sbyte[] { 3, 1, 1, 2, -121, -14, 31, 73, 76, 88, -100, 0, 0, -127 });
+
+            // float:
+            
+            assertValueToBytes(12345f,
+                new sbyte[] { 3, 1, 1, 2, -120, 70, 64, -28, 0, -127 });
+
+            // double:
+            
+            assertValueToBytes(23456d,
+                new sbyte[] { 3, 1, 1, 2, -119, 64, -42, -24, 0, 0, 0, 0, 0, -127 });
+
+            // boolean[]:
+            
+            assertValueToBytes(new Boolean[] { true, false },
+                new sbyte[] { 3, 1, 1, 2, -111, -125, 1, 2, -125, -126, -127, -127 });
+
+            // byte[]:
+            
+            assertValueToBytes(new sbyte[] { 1, 2, 3 },
+                new sbyte[] { 3, 1, 1, 2, -117, 3, 1, 2, 3, -127 });
+
+            // byte[][]:
+            
+            assertValueToBytes(new sbyte[][] { new sbyte[] { 1, 2, 3 }, new sbyte[] { 2, 3, 4 } },
+                new sbyte[] { 3, 1, 1, 2, -111, -124, 2, 2, -117, 3, 1, 2, 3, -117, 3, 2, 3, 4, -127, -127 });
+
+            // short[]:
+            
+            assertValueToBytes(new short[] { 1, 2, 3 },
+                new sbyte[] { 3, 1, 1, 2, -111, -123, 1, 3, 1, 2, 3, -127, -127 });
+
+            // int[]:
+            
+            assertValueToBytes(new int[] { 1, 2, 3 },
+                new sbyte[] { 3, 1, 1, 2, -111, -122, 1, 3, 1, 2, 3, -127, -127 });
+
+            // long[]:
+            
+            assertValueToBytes(new long[] { 1, 2, 3 },
+                new sbyte[] { 3, 1, 1, 2, -111, -121, 1, 3, 1, 2, 3, -127, -127 });
+
+            // float[]:
+            
+            assertValueToBytes(new float[] { 1, 2, 3 },
+                new sbyte[] { 3, 1, 1, 2, -111, -120, 1, 3, -120, 63, -128, 0, 0, -120, 64, 0, 0, 0, -120, 64, 64, 0, 0, -127, -127 });
+
+            // double[]:
+            
+            assertValueToBytes(new double[] { 1, 2, 3 },
+                new sbyte[] { 3, 1, 1, 2, -111, -119, 1, 3, -119, 63, -16, 0, 0, 0, 0, 0, 0, -119, 64, 0, 0, 0, 0, 0, 0, 0, -119, 64, 8, 0, 0, 0, 0, 0, 0, -127, -127 });
+
+            // empty string:
+            
+            assertValueToBytes("",
+                new sbyte[] { 3, 1, 1, 2, -110, -127 });
+
+            // string:
+
+            assertValueToBytes("abc",
+                new sbyte[] { 3, 1, 1, 2, -109, 3, 97, 98, 99, -127 });
+
+            // string[]:
+
+            assertValueToBytes(new String[] { "a", "", "c" },
+                new sbyte[] { 3, 1, 1, 2, -111, -109, 1, 3, -109, 1, 97, -110, -109, 1, 99, -127, -127 });
+
+            // Date:
+            
+            assertValueToBytes(new DateTime(2008, 1, 2, 3, 4, 5, 6, DateTimeKind.Utc),
+                new sbyte[] { 3, 1, 1, 2, -107, -122, 43, 57, 107, -52, 1, -122, 102, 0, 26, 64, -121, 0, 0, 1, 23, 56, 116, -88, -114, -127, -127 });
+
+            // Date[]:
+            
+            assertValueToBytes(new DateTime[] { new DateTime(2008, 1, 2, 3, 4, 5, 6, DateTimeKind.Utc), new DateTime(2008, 2, 3, 4, 5, 6, 7, DateTimeKind.Utc) },
+                new sbyte[] { 3, 1, 1, 2, -111, -107, -122, 43, 57, 107, -52, 1, 2, -107, -122, 43, 57, 107, -52, 1, -122, 102, 0, 26, 64, -121, 0, 0, 1, 23, 56, 116, -88, -114, -127, -107, -122, 43, 57, 107, -52, 1, -122, 102, 0, 26, 64, -121, 0, 0, 1, 23, -35, 120, 5, 87, -127, -127, -127 });
+        }
+
+        [Test]
+        public void badtype()
+        {
+            Message msg = Bytes2msg(new sbyte[] { 3, 1, 0, -127 });
+            Assert.AreEqual(1, msg.GetXType.Id);
+        }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentException))]
+        public void badmsglen1()
+        {
+            Message msg = Bytes2msg(new sbyte[] { 3, 1, -1, -127 });
+            Console.WriteLine("msg = " + msg);
+        }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentException))]
+        public void badmsglen2()
+        {
+            Message msg = Bytes2msg(new sbyte[] { 3, 1, 99, -127 });
+            Console.WriteLine("msg = " + msg);
+        }
+
+        [Test]
+        public void badfield()
+        {
+            Message msg = Bytes2msg(new sbyte[] { 3, 1, 1, 2, 2, -127 }, Validator.Level.MISSING_OK);
+            Console.WriteLine("msg = " + msg);
+        }
+    	
+	    private void assertValueToBytes( Object value, sbyte[] expectedBytes ) 
+	    {
+            XType t = new XType(1, "a");
+            Field f = new Field(2, "b");
+            t.PutValidator(f, Validator_object.Get(0));
+
+            Message msg = new Message(t, vf);
+            msg.Add(f, value);
+
+		    BinaryTaggedDataOutput btdo = new BinaryTaggedDataOutput( vf, "none:" );
+		    FlexBuffer buf = new FlexBuffer();
+            btdo.WriteMessage(msg, buf);
+
+		    buf.SetIndex( 0 );
+		    byte[] b = buf.GetAvailBytes();
+            sbyte[] b1 = new sbyte[b.Length];
+            Buffer.BlockCopy(b,0,b1,0,b.Length);
+            Dump( b );
+		    AssertArrayEquals( expectedBytes, b1 );
+	    }
+
+        private static void TestPerf( String name, int iter, Messagizer m, Message msg, int n )
+        {
+            long t0 = HPTimer.Now();
+
+            for ( int i = 0; i < n; i++ )
+                m.TransportMessage( null, msg );
+
+            long t1 = HPTimer.NsSince( t0 );
+
+            double timeDiff = t1 / 1000000000.0;
+            double r = n / timeDiff;
+
+            Console.WriteLine( name + " -- iteration : " + iter + " time : " + timeDiff + 
+                " count : " + n + " rate : " + r );
+        }
+
+        #region MyPacketSource
+        public class MyPacketSource : TransportPacket
+        {
+
+            public int HeaderSize()
+            {
+                return 0;
+            }
+
+            public void Packet( Who recepient, FlexBuffer buf )
+            {
+                // ignore
+            }
+
+            #region Source Members
+
+            public object GetHandler()
+            {
+                return null;
+            }
+
+            public void SetHandler( object handler )
+            {
+                // ignore
+            }
+
+            #endregion
+
+            #region Transport Members
+
+            public object TransportQuery( object query )
+            {
+                return null;
+            }
+
+            public void TransportControl( object control, object value )
+            {
+                // ignore
+            }
+
+            public void TransportNotify( object eventObj )
+            {
+                // ignore
+            }
+
+            #endregion
+
+            #region TransportPacket Members
+
+
+            public void TransportPacket(Who recipient, FlexBuffer buf)
+            {
+                
+            }
+
+            #endregion
+
+            #region Transport<SessionPacket> Members
+
+
+            public void SetSession(SessionPacket session)
+            {
+               
+            }
+
+            #endregion
+
+            #region Transport<SessionPacket> Members
+
+
+            public SessionPacket GetSession()
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+        }
+        #endregion MyPacketSource
+
+        private byte[] Msg2bytes(Message msg, bool? stringTypeAndField)
+        {
+            FlexBuffer buf = new FlexBuffer();
+
+            URL u = new URL("none:");
+            if (stringTypeAndField != null)
+                u.AddTerm(BinaryTaggedDataOutput.STRING_TYPE_AND_FIELD, stringTypeAndField.ToString());
+
+            BinaryTaggedDataOutput btdo = new BinaryTaggedDataOutput(vf, u.ToString());
+            btdo.WriteMessage( msg, buf );
+            buf.SetIndex( 0 );
+            return buf.GetAvailBytes();
+        }
+
+        private Message Bytes2msg(byte[] buf, Validator.Level level)
+        {
+            BinaryTaggedDataInput btdi = new BinaryTaggedDataInput(vf, "none:");
+            return btdi.ReadMessage(new FlexBuffer(buf));
+        }
+
+        private Message Bytes2msg(byte[] buf)
+        {
+            return Bytes2msg(buf, Validator.Level.FULL);
+        }
+
+        private Message Bytes2msg(sbyte[] buf, Validator.Level level)
+        {
+            return Bytes2msg((byte[])(Array)buf, level);
+        }
+
+        private Message Bytes2msg(sbyte[] buf)
+        {
+            return Bytes2msg(buf, Validator.Level.FULL);
+        }
+
+        private void TestX( Object x, Validator v )
+	    {
+            
+            if ( x is Array )
+		    {
+                int n = ( ( Array ) x ).GetLength( 0 );
+			    for (int i = 0; i < n; i++)
+			    {
+                    Object getValue = ( ( Array ) x ).GetValue( i );
+                    TestX( getValue, v.ElementValidator() );
+			    }
+		    }
+
+            Test(x, v, null);
+            Test(x, v, false);
+            Test(x, v, true);
+	    }
+
+
+        private void Test(Object x, Validator v, bool? stringTypeAndField)
+	    {
+		    //Console.WriteLine( "-----------------------------------------" );
+
+            mt_foo.ClearValidator( mf_x );
+            mt_foo.PutValidator( mf_x, v );
+
+		    Message msg = new Message( mt_foo, vf );
+		    msg.Add( mf_x, x );
+		    //Console.WriteLine( "msg = "+msg );
+
+            byte[] bufx = Msg2bytes(msg, stringTypeAndField);
+            Dump(bufx);
+            Message msg2 = Bytes2msg( bufx );
+    		
+		    //Console.WriteLine( "msg2 = "+msg2 );
+		    msg2.CheckType( mt_foo );
+		    Assert.AreEqual( 1, msg2.Count );
+		    Assert.IsTrue(msg.ContainsKey( mf_x ));
+            Object y = msg2.Get(mf_x);
+            AreEqual(x, y);
+	    }
+
+        public void Dump(byte[] buf)
+        {
+            Console.Write("buf = {");
+            for (int i = 0; i < buf.Length; i++)
+            {
+                if (i > 0)
+                    Console.Write(", ");
+                else
+                    Console.Write(" ");
+                Console.Write((sbyte)buf[i]);
+            }
+            Console.WriteLine(" }");
+        }
+
+        private void AreEqual( Object a, Object b )
+        {
+            if (a == null || b == null)
+		    {
+			    Assert.AreEqual( a, b );
+			    return;
+		    }
+    		
+            Type aType = a.GetType();
+            Type bType = b.GetType();
+    		
+		    if (aType == bType)
+		    {
+                if ( ( a is Array ) && ( b is Array ) )
+                    AssertArrayEquals( a, b );
+                else
+                    Assert.AreEqual( a, b );
+		    }
+		    //else if (a instanceof Number && b instanceof Number)
+		    else
+		    {
+                Console.WriteLine( "a {0}, b {1}\n", aType, bType );
+			    Assert.AreEqual( a, b );
+		    }
+        }
+
+        private void AssertArrayEquals( Object a, Object b )
+        {
+            // jagged arrays ... one dimension
+            int an = ( ( Array ) a ).GetLength( 0 );
+            int bn = ( ( Array ) b ).GetLength( 0 );
+
+            AreEqual( an, bn );
+
+            for ( int i = 0; i < an; i++ )
+                AreEqual( ( ( Array ) a ).GetValue( 0 ), ( ( Array ) b ).GetValue( 0 ) );
+        }
+
+        private long[] GetTestLongs()
+        {
+            int n = 65536 + 2 + 6;
+            int k = 65536 + 2;
+            int min = short.MinValue - 1;
+            long[] vals = new long[n];
+            int i = 0;
+            while (k-- > 0)
+                vals[i++] = min++;
+            vals[i++] = int.MinValue;
+            vals[i++] = int.MaxValue;
+            vals[i++] = int.MinValue - 1L;
+            vals[i++] = int.MaxValue + 1L;
+            vals[i++] = long.MinValue;
+            vals[i++] = long.MaxValue;
+            return vals;
+        }
+
+        private int[] GetTestInts()
+        {
+            int n = 65536 + 2 + 2;
+            int k = 65536 + 2;
+            int min = short.MinValue - 1;
+            int[] vals = new int[n];
+            int i = 0;
+            while (k-- > 0)
+                vals[i++] = min++;
+            vals[i++] = int.MinValue;
+            vals[i++] = int.MaxValue;
+            return vals;
+        }
+
+        private short[] GetShorts(short min, int n)
+        {
+            short[] vals = new short[n];
+            int i = 0;
+            while (n-- > 0)
+                vals[i++] = min++;
+            return vals;
+        }
+
+
+        private sbyte[] GetBytes(sbyte min, int n)
+        {
+            sbyte[] vals = new sbyte[n];
+            int i = 0;
+            while (n-- > 0)
+                vals[i++] = min++;
+            return vals;
+        }
+
+
+        public class MyValueFactory : DefaultValueFactory
+        {
+	        private readonly static TypeMap types = new TypeMap();
+
+            private readonly static Class2TypeMap class2type = 
+                new Class2TypeMap();
+
+	        static MyValueFactory()
+            {
+                DefaultValueFactory.Init( types, class2type );
+	        }
+
+	        public MyValueFactory()
+                : base ("none:", types, class2type)
+	        {
+		        // nothing to do.
+	        }
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Transport/TestArrayValue.cs b/binding-csharp/runtime/src/test/csharp/Etch/Transport/TestArrayValue.cs
new file mode 100644
index 0000000..edf9e4a
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Transport/TestArrayValue.cs
@@ -0,0 +1,105 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+
+    [TestFixture]
+    public class TestArrayValue
+    {
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestArrayValue" );
+        }
+
+
+        [Test]
+	    public void Constructor1()
+	    {
+		    ArrayValue av = new ArrayValue( new sbyte[0] );
+		    Assert.AreEqual( (sbyte) 0, av.Type );
+		    Assert.IsNull( av.CustomStructType );
+		    Assert.AreEqual( 0, av.Dim );
+	    }
+    	
+	    [Test]
+	    public void Constructor2()
+	    {
+		    XType t1 = new XType( "t1" );
+		    ArrayValue av = new ArrayValue( new sbyte[0], (sbyte) 1, t1, 2 );
+		    Assert.AreEqual( (sbyte) 1, av.Type );
+		    Assert.AreEqual( t1, av.CustomStructType );
+		    Assert.AreEqual( 2, av.Dim );
+	    }
+    	
+	    [Test]
+	    public void constructor3()
+	    {
+		    XType t2 = new XType( "t2" );
+            ArrayValue av = new ArrayValue( new sbyte[ 0 ], ( sbyte ) 3, t2, 4 );
+		    Assert.AreEqual( (byte) 3, av.Type );
+		    Assert.AreEqual( t2, av.CustomStructType );
+		    Assert.AreEqual( 4, av.Dim );
+	    }
+    	
+	    [Test]
+	    public void AddMany1()
+	    {
+		    DateTime dt = new DateTime();
+		    ArrayValue av = new ArrayValue( new Object[] { false, (sbyte) 1, (short) 2, 3, (long) 4, (float) 1.5, 1.6, "abc", null, dt } );
+		    Assert.AreEqual( 10, av.Size() );
+		    int index = 0;
+		    Assert.AreEqual( false, av.Get( index++ ) );
+		    Assert.AreEqual( (sbyte) 1, av.Get( index++ ) );
+		    Assert.AreEqual( (short) 2, av.Get( index++ ) );
+		    Assert.AreEqual( 3, av.Get( index++ ) );
+		    Assert.AreEqual( (long) 4, av.Get( index++ ) );
+		    Assert.AreEqual( (float) 1.5, av.Get( index++ ) );
+		    Assert.AreEqual( 1.6, av.Get( index++ ) );
+		    Assert.AreEqual( "abc", av.Get( index++ ) );
+		    Assert.AreEqual( null, av.Get( index++ ) );
+		    Assert.AreEqual( dt, av.Get( index++ ) );
+	    }
+    	
+	    [Test]
+	    public void AddMany2()
+	    {
+		    DateTime dt = new DateTime();
+		    ArrayValue av = new ArrayValue( new Object[] { (float) 1.5, 1.6, "abc", null, dt, false, (sbyte) 1, (short) 2, 3, (long) 4 } );
+		    Assert.AreEqual( 10, av.Size() );
+		    int index = 0;
+		    Assert.AreEqual( (float) 1.5, av.Get( index++ ) );
+		    Assert.AreEqual( 1.6, av.Get( index++ ) );
+		    Assert.AreEqual( "abc", av.Get( index++ ) );
+		    Assert.AreEqual( null, av.Get( index++ ) );
+		    Assert.AreEqual( dt, av.Get( index++ ) );
+		    Assert.AreEqual( false, av.Get( index++ ) );
+		    Assert.AreEqual( (sbyte) 1, av.Get( index++ ) );
+		    Assert.AreEqual( (short) 2, av.Get( index++ ) );
+		    Assert.AreEqual( 3, av.Get( index++ ) );
+		    Assert.AreEqual( (long) 4, av.Get( index++ ) );
+	    }
+    }
+}
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Transport/TestDefaultDeliveryService.cs b/binding-csharp/runtime/src/test/csharp/Etch/Transport/TestDefaultDeliveryService.cs
new file mode 100644
index 0000000..4c46482
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Transport/TestDefaultDeliveryService.cs
@@ -0,0 +1,293 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    //[TestFixture]
+    //public class TestDefaultDeliveryService
+    //{
+    //    private DefaultDeliveryService<MyStub> svc;
+
+    //    private MyStub ms;
+
+    //    private readonly ValueFactory vf = new MyValueFactory();
+
+    //    private Message msg;
+
+    //    private MyDataSource ds = new MyDataSource();
+
+    //    XType mt_add = new XType( "add" );
+    //    XType mt_add_result = new XType( "add_result" );
+    //    Field mf_x = new Field( "x" );
+    //    Field mf_y = new Field( "y" );
+    //    Field mf_result = new Field( "result" );
+
+    //    public Message ConstructSimpleMessage()
+    //    {   
+    //        return new Message( MyValueFactory.mt_function, vf );
+            
+    //    }
+
+    //    public Message ConstructAddMessage() 
+    //    {
+
+    //        msg = new Message( MyValueFactory.mt_add, vf );
+    //        msg.Add( MyValueFactory.mf_x, 4 );
+    //        msg.Add( MyValueFactory.mf_y, 5 );
+    		
+    //        return msg;
+    //    }
+
+    //    /// <summary>
+    //    /// Setup method to be called before every test.
+    //    /// </summary>
+    //    [SetUp]
+    //    public void Setup()
+    //    {
+    //        ms = new MyStub( null, null );
+
+    //        DefaultDeliveryService<MyStub> dds = new MyDefaultDeliveryService( ms );
+
+    //        svc = DefaultDeliveryService<MyStub>.SetUp( dds, ds, vf );
+    //    }
+
+    //    //[Test]
+    //    //public void Up()
+    //    //{
+    //    //    Setup();
+    //    //    svc.Up( new MailboxManager( svc, 0 ) );
+    //    //    Assert.AreEqual( ms.what, What.MYSTUBCREATED );
+    //    //}
+
+    //    //[Test]
+    //    //public void Down()
+    //    //{
+    //    //    Setup();
+    //    //    svc.Up( new MailboxManager( svc, 0 ) );
+    //    //    svc.Down( new MailboxManager( svc, 0 ) );
+    //    //    Assert.AreEqual( ms.what, What.MYSTUBMESSAGE );
+    //    //}
+
+    //    [Test]
+    //    public void ShutdownOutput()
+    //    {
+    //        svc.TransportControl( TransportConsts.STOP, null );
+    //        Assert.AreEqual( ds.what, What.MYDATASOURCESHUTDOWNOUTPUT );
+    //    }
+
+    //    [Test]
+    //    public void Message()
+    //    {
+    //        svc.SessionNotify( SessionConsts.UP );
+    //        svc.Message( null, ConstructSimpleMessage() );
+    //        Assert.AreEqual( ms.what, What.MYSTUBMESSAGE );
+    //    }
+
+    //    [Test]
+    //    public void Send()
+    //    {
+    //        svc.Send( ConstructSimpleMessage() );
+    //        Assert.AreEqual( ds.what, What.MYDATASOURCEDATA );
+    //    }
+
+    //    [Test]
+    //    public void Call()
+    //    {
+    //        try
+    //        {
+    //            svc.EndCall( svc.BeginCall( ConstructAddMessage() ), mt_add_result,
+    //                mf_result, 1 );
+    //        }
+    //        catch ( Exception )
+    //        {
+    //            Assert.AreEqual( ds.what, What.MYDATASOURCEDATA );
+    //        }
+    //    }
+
+    //    public class MyDefaultDeliveryService : DefaultDeliveryService<MyStub>
+    //    {
+    //        private MyStub ms;
+
+    //        public MyDefaultDeliveryService( MyStub ms )
+    //        {
+    //            this.ms = ms;
+    //        }
+
+    //        protected override MyStub NewStub( MailboxMessageSource src )
+    //        {
+    //            return ms;
+    //        }
+
+    //        public override string ToString()
+    //        {
+    //            return "MyDefaultDeliveryService testing";
+    //        }
+    //    }
+
+    //    public enum What
+    //    {
+    //        MYSTUBCREATED,
+    //        MYSTUBMESSAGE,
+    //        MYDATASOURCESHUTDOWNOUTPUT,
+    //        MYDATASOURCEDATA
+    //    };
+
+    //    public class MyDataSource : DataSource
+    //    {
+    //        public Enum what;
+
+    //        #region DataSource Members
+
+    //        public void Data( Who recipient, FlexBuffer buf )
+    //        {
+    //            what = What.MYDATASOURCEDATA;
+    //        }
+
+    //        #endregion
+
+
+    //        #region Source Members
+
+    //        public object GetHandler()
+    //        {
+    //            return null;
+    //        }
+
+    //        public void SetHandler( object handler )
+    //        {
+    //            // nothing to do. 
+    //        }
+
+    //        #endregion
+
+    //        #region Transport Members
+
+    //        public object TransportQuery( object query )
+    //        {
+    //            return null;
+    //        }
+
+    //        public void TransportControl( object control, object value )
+    //        {
+    //            if ( control.Equals( TransportConsts.STOP ) )
+    //                what = What.MYDATASOURCESHUTDOWNOUTPUT;
+    //        }
+
+    //        public void TransportNotify( object eventObj )
+    //        {
+    //            // ignore
+    //        }
+
+    //        #endregion
+    //    }
+
+    //    public class MyStub : StubBase
+    //    {
+    //        public Enum what;
+
+    //        public MyStub( MessageSource src, Object obj ) : base ( src, obj, null, null )
+    //        {
+    //            what = What.MYSTUBCREATED;
+    //        }
+
+    //        public override bool Message( Who sender, Message msg )
+    //        {
+    //            what = What.MYSTUBMESSAGE;
+    //            return true;
+    //        }
+    //    }
+
+    //    public class MyValueFactory : DefaultValueFactory
+    //    {
+    //        private readonly static TypeMap types = new TypeMap();
+
+    //        private readonly static FieldMap fields = new FieldMap();
+
+    //        private readonly static Class2TypeMap class2type = 
+    //            new Class2TypeMap();
+
+    //        public readonly static XType mt_function = types.Get( "function" );
+
+    //        public readonly static XType mt_add = types.Get( "add" );
+
+    //        public readonly static XType mt_add_result = types.Get( "add_result" );
+
+    //        public readonly static Field mf_x = fields.Get( "x" );
+
+    //        public readonly static Field mf_y = fields.Get( "y" );
+
+    //        public readonly static Field mf_result = fields.Get( "xresult" );
+
+    //        static MyValueFactory()
+    //        {
+    //            DefaultValueFactory.Init( types, fields, class2type );
+
+    //            mt_function.PutValidator( DefaultValueFactory._mf__messageId, Validator_long.Get( 0 ) );
+
+    //            mt_add.PutValidator( mf_x, Validator_int.Get( 0 ) );
+    //            mt_add.PutValidator( mf_y, Validator_int.Get( 0 ) );
+    //            mt_add.PutValidator( DefaultValueFactory._mf__messageId, Validator_long.Get( 0 ) );
+
+    //            mt_add_result.PutValidator( mf_result, Validator_int.Get( 0 ) );
+    //            mt_add_result.PutValidator( DefaultValueFactory._mf__messageId, Validator_long.Get( 0 ) );
+    //            mt_add_result.PutValidator( DefaultValueFactory._mf__inReplyTo, Validator_long.Get( 0 ) );
+    //        }
+
+    //        public override XType GetType( int? id )
+    //        {
+    //            return types.Get( id );
+    //        }
+
+    //        public override XType GetType( string name )
+    //        {
+    //            return types.Get( name );
+    //        }
+
+    //        public override ICollection<XType> GetTypes()
+    //        {
+    //            return types.Values();
+    //        }
+
+    //        public override Field GetField( int? id )
+    //        {
+    //            return fields.Get( id );
+    //        }
+
+    //        public override Field GetField( string name )
+    //        {
+    //            return fields.Get( name );
+    //        }
+
+    //        public override ICollection<Field> GetFields()
+    //        {
+    //            return fields.Values();
+    //        }
+
+    //        public override StructValue ExportCustomValue( Object value )
+    //        {
+    //            return ExportCustomValue( this, class2type, value );
+    //        }
+
+    //        public override XType GetCustomStructType( Type c )
+    //        {
+    //            return class2type.Get( c );
+    //        }
+    //    }
+    //}
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Transport/TestMessagizer.cs b/binding-csharp/runtime/src/test/csharp/Etch/Transport/TestMessagizer.cs
new file mode 100644
index 0000000..4fe3749
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Transport/TestMessagizer.cs
@@ -0,0 +1,673 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    [TestFixture]
+    public class TestMessagizer
+    {
+
+        private const sbyte VERSION = 3; // BinaryTaggedData.VERSION;
+	private const sbyte NONE = -127; // TypeCode.NONE;
+	private const sbyte BYTE = -124; // TypeCode.BYTE;
+        
+        private readonly Who who = new MyWho();
+
+        //static Etch.Support.DefaultValueFactory vf = new Etch.Support.DefaultValueFactory();
+        public DefaultValueFactory vf;
+        public MyMessageHandler mh;
+        public MyPacketSource ps;
+        Messagizer m;
+
+        public TestMessagizer()
+        {
+            //ps = new MyPacketSource( this );
+        }
+
+        /// <summary>
+        /// Call before the test fixture
+        /// </summary>
+        [TestFixtureSetUp]
+        public void SetUpBeforeClass() 
+	    {
+            vf = new MyValueFactory();
+            ps = new MyPacketSource();
+            mh = new MyMessageHandler();
+            Resources res = new Resources();
+            res.Add(TransportConsts.VALUE_FACTORY, vf);
+            m = new Messagizer(ps,"foo:?Messagizer.format=binary", res);
+            m.SetSession(mh);
+            Console.WriteLine();
+            Console.Write( "TestMessagizer" );
+	    }
+
+      /*  public void SetUpBeforeEveryTest()
+        {
+
+            ps = new MyPacketSource();
+            mh = new MyMessageHandler();
+
+            m = new Messagizer( mh, vf );
+            m.SetSource( ps );
+
+        } */
+
+        #region Test PacketHandler methods 
+	    
+        public class MyWho : Who
+        {
+            public MyWho()
+            {
+                //nothing
+            }
+        }
+
+        //[Test]
+        //public void Up() 
+        //{
+        //    SetUpBeforeEveryTest();
+
+        //    PacketHandler ph = m;
+
+        //    Assert.IsNull(mh.what);
+        //    Assert.IsNull( mh.src );
+
+        //    ph.Up( ps );
+
+        //    Assert.AreEqual( mh.src, m );
+        //    Assert.AreEqual(mh.what, What.TESTMESSAGEHANDLERUP);
+        //    Assert.AreEqual( ps, m.GetPacketSource() );
+        //}
+
+        [Test]
+        public void Packet1()
+        {
+           
+
+        //    PacketHandler ph = m;
+            SessionPacket ph = m;
+
+            FlexBuffer buf = new FlexBuffer( new byte[] { (byte)VERSION, 
+                unchecked((byte)BYTE), 1, 0, unchecked((byte)NONE) } );
+
+            mh.handled = true;
+
+         //   ph.Packet( who, buf );
+            ph.SessionPacket(who,buf);
+
+            Assert.AreEqual( What.TESTMESSAGEHANDLERMESSAGE, mh.what );
+            Assert.AreEqual( ps, m.GetTransport() );
+            Assert.AreEqual( who, mh.xsender);
+            Assert.IsNotNull( mh.xmsg );
+            Assert.AreEqual( MyValueFactory.mt_add, mh.xmsg.GetXType );
+            Assert.AreEqual( 0, mh.xmsg.Count );
+
+        }
+
+        [Test]
+        public void Packet2()
+        {
+           
+
+            SessionPacket ph = m;
+
+            FlexBuffer buf = new FlexBuffer(new byte[] { (byte)VERSION, 
+                unchecked((byte)BYTE), 1, 0, unchecked((byte)NONE) });
+
+            mh.handled = false;
+
+            ph.SessionPacket( who, buf );
+
+            Assert.AreEqual(What.OOB_NOTIFY_HANDLER, mh.what);
+            Assert.AreEqual( ps, m.GetTransport() );
+            Assert.AreEqual( who, mh.xsender );
+            Assert.IsNotNull( mh.xmsg );
+            Assert.AreEqual( MyValueFactory.mt_add, mh.xmsg.GetXType );
+            Assert.AreEqual( 0, mh.xmsg.Count );
+
+        }
+
+        [Test]
+        public void Packet3()
+        {
+          
+
+            SessionPacket ph = m;
+
+            FlexBuffer buf = new FlexBuffer(new byte[] { (byte)VERSION, 
+                unchecked((byte)BYTE), 2, 0, unchecked((byte)NONE) });
+            mh.handled = true;
+
+            ph.SessionPacket( who, buf );
+
+            Assert.AreEqual( What.TESTMESSAGEHANDLERMESSAGE, mh.what );
+            Assert.AreEqual( ps, m.GetTransport() );
+            Assert.AreEqual( who, mh.xsender );
+            Assert.IsNotNull( mh.xmsg );
+            Assert.AreEqual( MyValueFactory.mt_add_result, mh.xmsg.GetXType );
+            Assert.AreEqual( 0, mh.xmsg.Count );
+
+        }
+
+        [Test]
+        public void Packet4()
+        {
+           
+
+            SessionPacket ph = m;
+
+            FlexBuffer buf = new FlexBuffer(new byte[] { (byte)VERSION, 
+                unchecked((byte)BYTE), 2, 0, unchecked((byte)NONE) });
+
+            mh.handled = false;
+
+            ph.SessionPacket( who, buf );
+
+            Assert.AreEqual(What.OOB_NOTIFY_HANDLER, mh.what);
+            Assert.AreEqual( ps, m.GetTransport() );
+            Assert.AreEqual( who, mh.xsender );
+            Assert.IsNotNull( mh.xmsg );
+            Assert.AreEqual( MyValueFactory.mt_add_result, mh.xmsg.GetXType );
+            Assert.AreEqual( 0, mh.xmsg.Count );
+
+        }
+
+        //[Test]
+        //public void Down() 
+        //{
+        //    SetUpBeforeEveryTest();
+        //    PacketHandler ph = m;
+
+        //    Assert.IsNull( mh.what );
+        //    Assert.IsNull( mh.src );
+
+        //    ph.Down(ps);
+
+        //    Assert.AreEqual( mh.src, m );
+        //    Assert.AreEqual( mh.what, What.TESTMESSAGEHANDLERDOWN );
+        //    Assert.AreEqual( ps, m.GetPacketSource() );
+        //}
+
+        #endregion Test PacketHandler methods
+
+        #region MessagizerMessageSource methods
+
+        //[Test]
+        //public void Close1() 
+        //{
+        //    SetUpBeforeEveryTest();
+
+        //    MessagizerMessageSource mms = m;
+        //    Assert.IsNull( ps.what );
+
+        //    mms.Close( true );
+
+        //    Assert.AreEqual(ps.what, What.PACKETSOURCECLOSE);
+        //    Assert.IsTrue( ps.reset );
+        //}
+
+        //[Test]
+        //public void Close2()
+        //{
+        //    SetUpBeforeEveryTest();
+
+        //    MessagizerMessageSource mms = m;
+        //    Assert.IsNull( ps.what );
+
+        //    mms.Close( false );
+
+        //    Assert.AreEqual( ps.what, What.PACKETSOURCECLOSE );
+        //    Assert.IsFalse( ps.reset );
+        //}
+
+        //[Test]
+        //public void LocalAddress() 
+        //{
+        //    SetUpBeforeEveryTest();
+
+        //    MessagizerMessageSource mms = m;
+        //    EndPoint isa = new IPEndPoint( IPAddress.Parse( "127.0.0.1" ), 23 );
+        //    ps.localAddress  =  isa;
+
+        //    Assert.AreEqual( isa, mms.LocalAddress() );
+        //}
+    	
+        //[Test]
+        //public void RemoteAddress() 
+        //{
+        //    SetUpBeforeEveryTest();
+
+        //    MessagizerMessageSource mms = m;
+        //    EndPoint isa = new IPEndPoint( IPAddress.Parse( "127.0.0.1" ), 23 );
+        //    ps.remoteAddress = isa;
+
+        //    Assert.AreEqual( isa, mms.RemoteAddress() );
+        //}
+    	
+        //[Test]
+        //public void ShutdownInput() 
+        //{
+        //    SetUpBeforeEveryTest();
+
+        //    MessagizerMessageSource mms = m;
+        //    Assert.IsNull( ps.what );
+        //    m.ShutdownInput();
+        //    Assert.AreEqual( ps.what, What.PACKETSOURCESHUTDOWNINPUT );
+        //}
+    	
+        //[Test]
+        //public void ShutdownOutput() 
+        //{
+        //    SetUpBeforeEveryTest();
+
+        //    MessagizerMessageSource mms = m;
+        //    Assert.IsNull( ps.what );
+        //    m.ShutdownOutput();
+
+        //    Assert.AreEqual( ps.what, What.PACKETSOURCESHUTDOWNOUTPUT );
+        //}
+    	
+        //[Test]
+        //public void Stop() 
+        //{
+        //    SetUpBeforeEveryTest();
+
+        //    MessagizerMessageSource mms = m;
+        //    Assert.IsNull( ps.what );
+
+        //    mms.Stop();
+        //    Assert.AreEqual(ps.what, What.PACKETSOURCESTOP);
+        //}
+
+   /*     public void Message1()
+        {
+          
+            
+            MessagizerMessageSource mms = m;
+
+            Message msg = new Message( MyValueFactory.mt_add, vf );
+            ps.headerSize = 0;
+
+            Assert.IsNull( ps.what );
+
+            mms.Messagex( who, msg );
+
+            Assert.AreEqual( What.PACKETSOURCEPACKET, ps.what );
+            Assert.AreEqual( who, ps.xrecipient );
+            Assert.IsNotNull( ps.xbuf );
+            Assert.AreEqual( 4, ps.xbuf.Length );
+            Assert.AreEqual( VERSION, ps.xbuf[ 0 ] );
+            Assert.AreEqual((byte)1, ps.xbuf[1]);
+            Assert.AreEqual((byte)0, ps.xbuf[2]);
+            Assert.AreEqual( NONE, ps.xbuf[ 3 ] );
+        }
+
+        public void Message2()
+        {
+          
+            MessagizerMessageSource mms = m;
+
+            Message msg = new Message( MyValueFactory.mt_add, vf );
+            ps.headerSize = 8;
+
+            Assert.IsNull( ps.what );
+
+            mms.Messagex( who, msg );
+
+            Assert.AreEqual( What.PACKETSOURCEPACKET, ps.what );
+            Assert.AreEqual( who, ps.xrecipient );
+            Assert.IsNotNull( ps.xbuf );
+            Assert.AreEqual( 12, ps.xbuf.Length );
+            Assert.AreEqual( ( byte ) 0, ps.xbuf[ 0 ] );
+            Assert.AreEqual( ( byte ) 0, ps.xbuf[ 1 ] );
+            Assert.AreEqual( ( byte ) 0, ps.xbuf[ 2 ] );
+            Assert.AreEqual( ( byte ) 0, ps.xbuf[ 3 ] );
+            Assert.AreEqual( ( byte ) 0, ps.xbuf[ 4 ] );
+            Assert.AreEqual( ( byte ) 0, ps.xbuf[ 5 ] );
+            Assert.AreEqual( ( byte ) 0, ps.xbuf[ 6 ] );
+            Assert.AreEqual( ( byte ) 0, ps.xbuf[ 7 ] );
+            Assert.AreEqual( VERSION, ps.xbuf[ 8 ] );
+            Assert.AreEqual( ( byte ) 1, ps.xbuf[ 9 ] );
+            Assert.AreEqual((byte)0, ps.xbuf[9]);
+            Assert.AreEqual( NONE, ps.xbuf[ 11 ] );
+        } */
+
+	    
+        #endregion MessagizerMessageSource methods
+
+        // Do following test in stress testing.
+	    /*
+        [Test]
+	    public void SendreceiveMessageIterative() 
+	    {
+            SetUpBeforeEveryTest();
+		    report = false;
+
+            int n = 100000;
+    		
+		    //long t0 = Timer.Init();
+            //Timer t0 = new Timer().Init();
+		    for (int i = 0; i < n; i++) {
+			    MyMessageHandler.Send( m, ps );
+			    Assert.IsTrue(ps.checkFlag);
+		    }
+		    //long t1 = t0.ElapsedNanos();
+		    //double t = (t1-t0) / 1000000000.0;
+		    //Console.WriteLine( "took " + t + " to send " + n  + " ( " + n/t + " + per sec)\n" );
+	    }
+        */
+
+        public enum What
+        {
+            PACKETSOURCEPACKET,
+            TESTMESSAGEHANDLERMESSAGE,
+            OOB_QUERY_SOURCE,
+		    OOB_CONTROL_SOURCE,
+		    OOB_NOTIFY_SOURCE,
+		    OOB_QUERY_HANDLER,
+		    OOB_CONTROL_HANDLER,
+		    OOB_NOTIFY_HANDLER
+        };
+
+        #region MyPacketSource
+        public class MyPacketSource : TransportPacket
+        {
+            TestMessagizer _tm;
+
+            public What what;
+            
+            public bool checkFlag = true;
+            //public PktSrcMessageHandler mh;
+            
+            public Messagizer m;
+
+            public SessionPacket handler;
+            public int headerSize = 0;
+            public bool reset;
+            public Who xrecipient;
+
+            public Object xquery;
+            /** */
+            public Object xquery_result;
+            /** */
+            public Object xcontrol;
+            /** */
+            public Object xvalue;
+            /** */
+            public Object xevent;
+
+            public byte[] xbuf;
+
+            public int HeaderSize()
+            {
+                return headerSize;
+            }
+
+            public MyPacketSource()
+            {
+                // nothing to do.
+            }
+
+            public MyPacketSource( TestMessagizer tm )
+            {
+                _tm = tm;
+
+            }
+            /**
+            public class PktSrcMessageHandler : MessageHandler<MessagizerMessageSource>
+            {
+                MyPacketSource _mps;
+
+                public PktSrcMessageHandler()
+                {
+                    // nothing to do.
+                }
+
+                public PktSrcMessageHandler( MyPacketSource mps )
+                {
+                    _mps = mps;
+                    
+                }
+
+                public void Up( MessagizerMessageSource src ) 
+                {
+                    Console.WriteLine( "up" );
+                }
+
+                public bool Message( MessagizerMessageSource src, Who sender, Message msg )
+				{
+				    if (report)
+					    Console.WriteLine( "got reply " + msg );
+    				
+				    
+				    if ( (int)(msg.Get(mf_result)) != 9 ) 
+					    _mps.checkFlag = false;
+
+                    return true;
+    				
+			    }
+
+                public void Down( MessagizerMessageSource src ) 
+                {
+                    Console.WriteLine( "down" );
+                }
+            }
+    		**/
+		    public void Packet( Who recipient, FlexBuffer buf ) 
+		    {
+                what = What.PACKETSOURCEPACKET;
+                this.xrecipient = recipient;
+                this.xbuf = buf.GetAvailBytes();
+		    }
+		    
+
+            #region Transport Members
+
+            public object TransportQuery( object query )
+            {
+                what = What.OOB_QUERY_SOURCE;
+                xquery = query;
+                return xquery_result;
+            }
+
+            public void TransportControl( object control, object value )
+            {
+                what = What.OOB_CONTROL_SOURCE;
+                xcontrol = control;
+                xvalue = value;
+            }
+
+            public void TransportNotify( object eventObj )
+            {
+                what = What.OOB_NOTIFY_SOURCE;
+                xevent = eventObj;
+            }
+
+            #endregion
+
+           
+            #region TransportPacket Members
+
+
+            public void TransportPacket(Who recipient, FlexBuffer buf)
+            {
+                what = What.PACKETSOURCEPACKET;
+                this.xrecipient = recipient;
+                this.xbuf = buf.GetAvailBytes();
+            }
+
+            #endregion
+
+            #region Transport<SessionPacket> Members
+
+
+            public void SetSession(SessionPacket session)
+            {
+                this.handler = session;
+            }
+
+            #endregion
+
+            #region Transport<SessionPacket> Members
+
+
+            public SessionPacket GetSession()
+            {
+                return handler;
+            }
+
+            #endregion
+        }
+
+        #endregion MyPacketSource
+
+        #region MyMessageHandler
+
+        public class MyMessageHandler : SessionMessage
+        {
+            public Enum what;
+            public Who xsender;
+            public Message xmsg;
+            public bool handled;
+
+            public Object xquery;
+            public Object xquery_result;
+            public Object xcontrol;
+            public Object xvalue;
+            public Object xevent;
+
+            
+
+            public bool Message( Who sender, Message msg ) 
+		    {
+
+                what = What.TESTMESSAGEHANDLERMESSAGE;
+                this.xsender = sender;
+                this.xmsg = msg;
+                return handled;
+
+                /**
+			    if (report)
+		    	    Console.WriteLine( "message: "+msg );
+    		    
+		        if (msg.IsType( mt_add ))
+		        {
+		    	    int? x = (int?)( msg.Get( mf_x ) );
+                    int? y = ( int? ) ( msg.Get( mf_y ) );
+
+                    Int32 r = ( int ) ( x + y );
+    		    	
+		    	    Message rmsg = msg.Reply( mt_add_result );
+		    	    rmsg.Add( mf_result, r );
+    		    	
+		    	    if (report)
+		    		    Console.WriteLine( "replying with "+rmsg );
+    		    	
+		    	    src.Message( sender, rmsg );
+		        }
+
+                return true;
+                 * */
+	        }
+
+         
+
+            #region Session Members
+
+            public object SessionQuery( object query )
+            {
+                what = What.OOB_QUERY_HANDLER;
+                xquery = query;
+                return xquery_result;
+            }
+
+            public void SessionControl( object control, object value )
+            {
+                what = What.OOB_CONTROL_HANDLER;
+                xcontrol = control;
+                xvalue = value;
+            }
+
+            public void SessionNotify( object eventObj )
+            {
+                what = What.OOB_NOTIFY_HANDLER;
+                xevent = eventObj;
+            }
+
+            #endregion
+
+            #region SessionMessage Members
+
+            public bool SessionMessage(Who sender, Message msg)
+            {
+                what = What.TESTMESSAGEHANDLERMESSAGE;
+                this.xsender = sender;
+                this.xmsg = msg;
+                return handled;
+            }
+
+            #endregion
+        }
+        #endregion MyMessageHandler
+
+        public class MyValueFactory : DefaultValueFactory
+        {
+            private readonly static TypeMap types = new TypeMap();
+
+           
+            private readonly static Class2TypeMap class2type = 
+                new Class2TypeMap();
+
+            public readonly static XType mt_add = types.Add( new XType( 1, "add" ) );
+
+            public readonly static XType mt_add_result = types.Add( new XType( 2, "add_result" ) );
+
+            public static readonly Field mf_x = new Field(3, "x");
+
+            public static readonly Field mf_y = new Field(4, "y"); 
+
+            public readonly static Field mf_result =  new Field( 5, "xresult");
+
+            static MyValueFactory()
+            {
+                DefaultValueFactory.Init( types,  class2type );
+
+                mt_add.PutValidator( mf_x, Validator_int.Get( 0 ) );
+                mt_add.PutValidator( mf_y, Validator_int.Get( 0 ) );
+                mt_add.PutValidator( DefaultValueFactory._mf__messageId, Validator_long.Get( 0 ) );
+                
+                mt_add_result.PutValidator( mf_result, Validator_int.Get( 0 ) );
+                mt_add_result.PutValidator( DefaultValueFactory._mf__messageId, Validator_long.Get( 0 ) );
+                mt_add_result.PutValidator( DefaultValueFactory._mf__inReplyTo, Validator_long.Get( 0 ) );
+
+            }
+
+            public MyValueFactory() : base("none:", types, class2type)
+            {
+                // nothing.
+            }
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Transport/TestPlainMailbox.cs b/binding-csharp/runtime/src/test/csharp/Etch/Transport/TestPlainMailbox.cs
new file mode 100644
index 0000000..e124f81
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Transport/TestPlainMailbox.cs
@@ -0,0 +1,848 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    [TestFixture]
+    public class TestPlainMailbox : MailboxManager
+    {
+        [SetUp]
+        public void Init()
+        {
+            unregistered = false;
+
+            //     AlarmManager.SetAlarmManager(null);
+
+            redelivered = new List<Element>();
+
+            vf = new MyValueFactory();
+
+            mt_foo = new XType("foo");
+
+            foo_msg = new Message(mt_foo, vf);
+
+            fred_who = new WhoAmI();
+
+            mt_bar = new XType("bar");
+
+            bar_msg = new Message(mt_bar, vf);
+
+            alice_who = new WhoAmI();
+
+            notify = new MyNotify();
+
+            notify1x = new MyNotify();
+        }
+        
+        [Test]
+        public void construct1()
+        {
+            testConstruct(1L);
+        }
+
+
+        [Test]
+        [ExpectedException(typeof(NullReferenceException))]
+        public void construct2()
+        {
+            new PlainMailbox(null, 1L);
+        }
+
+
+        [Test]
+        public void closeDelivery1()
+        {
+            // open mailbox and close it for delivery while empty.
+
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkCloseDelivery(mb, true);
+            checkMailbox(mb, true, false, true, true, 0);
+        }
+
+
+        [Test]
+        public void closeDelivery2()
+        {
+            // open mailbox and close it for delivery while not empty.
+
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkDeliver(mb, true, alice_who, foo_msg);
+            checkMailbox(mb, false, true, false, false, 0);
+
+            checkCloseDelivery(mb, true);
+            checkMailbox(mb, false, true, true, true, 0);
+        }
+
+
+        [Test]
+        public void closeDelivery3()
+        {
+            // open mailbox and close it for delivery twice.
+
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkCloseDelivery(mb, true);
+            checkMailbox(mb, true, false, true, true, 0);
+
+            checkCloseDelivery(mb, false);
+            checkMailbox(mb, true, false, true, true, 0);
+        }
+
+
+        [Test]
+        public void closeRead1()
+        {
+            // open mailbox and close it for reading while empty.
+
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkCloseRead(mb, true);
+            checkMailbox(mb, true, false, true, true, 0);
+        }
+
+
+        [Test]
+        public void closeRead2()
+        {
+            // open mailbox and close it for reading while not empty.
+
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkDeliver(mb, true, alice_who, foo_msg);
+            checkMailbox(mb, false, true, false, false, 0);
+
+            checkCloseRead(mb, true);
+            checkMailbox(mb, true, false, true, true, 1);
+            checkRedelivered(0, alice_who, foo_msg);
+        }
+
+
+        [Test]
+        public void closeRead3()
+        {
+            // open mailbox and close it for reading twice while empty.
+
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkCloseRead(mb, true);
+            checkMailbox(mb, true, false, true, true, 0);
+
+            checkCloseRead(mb, false);
+            checkMailbox(mb, true, false, true, true, 0);
+        }
+
+
+        [Test]
+        public void closeRead4()
+        {
+            // open mailbox and close it for reading twice while not empty.
+
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkDeliver(mb, true, alice_who, foo_msg);
+            checkMailbox(mb, false, true, false, false, 0);
+
+            checkCloseRead(mb, true);
+            checkMailbox(mb, true, false, true, true, 1);
+            checkRedelivered(0, alice_who, foo_msg);
+
+            checkCloseRead(mb, false);
+            checkMailbox(mb, true, false, true, true, 1);
+            checkRedelivered(0, alice_who, foo_msg);
+        }
+
+
+        [Test]
+        public void full1()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkDeliver(mb, true, fred_who, foo_msg);
+            checkMailbox(mb, false, true, false, false, 0);
+
+            checkDeliver(mb, false, alice_who, bar_msg);
+            checkMailbox(mb, false, true, false, false, 0);
+        }
+
+
+        [Test]
+        public void full2()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkDeliver(mb, true, fred_who, foo_msg);
+            checkMailbox(mb, false, true, false, false, 0);
+
+            checkDeliver(mb, false, alice_who, bar_msg);
+            checkMailbox(mb, false, true, false, false, 0);
+
+            checkDeliver(mb, false, fred_who, bar_msg);
+            checkMailbox(mb, false, true, false, false, 0);
+        }
+
+
+        [Test]
+        public void read1()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkDeliver(mb, true, alice_who, bar_msg);
+            checkMailbox(mb, false, true, false, false, 0);
+
+            checkRead(mb, true, alice_who, bar_msg);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkCloseDelivery(mb, true);
+            checkMailbox(mb, true, false, true, true, 0);
+        }
+
+
+        [Test]
+        public void read2()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkDeliver(mb, true, alice_who, bar_msg);
+            checkMailbox(mb, false, true, false, false, 0);
+
+            checkCloseDelivery(mb, true);
+            checkMailbox(mb, false, true, true, true, 0);
+
+            checkRead(mb, true, alice_who, bar_msg);
+            checkMailbox(mb, true, false, true, true, 0);
+        }
+
+
+        [Test]
+        public void read3()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkDeliver(mb, true, alice_who, bar_msg);
+            checkMailbox(mb, false, true, false, false, 0);
+
+            checkCloseDelivery(mb, true);
+            checkMailbox(mb, false, true, true, true, 0);
+
+            checkRead(mb, true, alice_who, bar_msg);
+            checkMailbox(mb, true, false, true, true, 0);
+        } 
+
+
+        [Test]
+        public void read4()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkCloseDelivery(mb, true);
+            checkMailbox(mb, true, false, true, true, 0);
+
+            checkRead(mb, false, null, null);
+            checkMailbox(mb, true, false, true, true, 0);
+        } 
+
+        
+        [Test]
+        [Ignore]
+        public void read5()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            Thread.Sleep(1000);
+
+            checkRead(mb, false, null, null);
+            checkMailbox(mb, true, false, true, true, 0);
+        }
+
+
+       
+        [Test]
+        [Ignore]
+        public void read6()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkRead(mb, false, null, null);
+            checkMailbox(mb, true, false, true, true, 0);
+        }
+
+        
+        [Test]
+        public void read7()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkRead(mb, -1, false, null, null);
+            checkMailbox(mb, true, false, false, false, 0);
+        }
+
+        
+        [Test]
+        public void read8()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkRead(mb, 1, false, null, null);
+            checkMailbox(mb, true, false, false, false, 0);
+        }
+
+
+        [Test]
+        public void deliver1()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            checkMailbox(mb, true, false, false, false, 0);
+
+            checkCloseDelivery(mb, true);
+            checkMailbox(mb, true, false, true, true, 0);
+
+            checkDeliver(mb, false, fred_who, bar_msg);
+            checkMailbox(mb, true, false, true, true, 0);
+        }
+
+
+        [Test]
+        public void notify1()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            notify.checkMailboxStatus(false, null, null, false);
+
+            Object state = new Object();
+
+            mb.RegisterNotify(notify, state, 0);
+            notify.checkMailboxStatus(false, null, null, false);
+
+            checkCloseDelivery(mb, true);
+            notify.checkMailboxStatus(true, mb, state, true);
+        }
+
+
+        [Test]
+        public void notify2()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            notify.checkMailboxStatus(false, null, null, false);
+
+            Object state = new Object();
+
+            mb.RegisterNotify(notify, state, 1000);
+            notify.checkMailboxStatus(false, null, null, false);
+
+            Thread.Sleep(2000);
+            notify.checkMailboxStatus(true, mb, state, true);
+        }
+
+
+        [Test]
+        public void notify3()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            notify.checkMailboxStatus(false, null, null, false);
+
+            Object state = new Object();
+
+            mb.RegisterNotify(notify, state, 0);
+            notify.checkMailboxStatus(false, null, null, false);
+
+            Thread.Sleep(2000);
+            notify.checkMailboxStatus(false, null, null, false);
+        }
+
+
+        [Test]
+        public void notify4()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            notify.checkMailboxStatus(false, null, null, false);
+
+            Object state = new Object();
+
+            mb.RegisterNotify(notify, state, 0);
+            notify.checkMailboxStatus(false, null, null, false);
+
+            mb.Message(alice_who, foo_msg);
+            notify.checkMailboxStatus(true, mb, state, false);
+        }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentNullException))]
+        public void reg1()
+        {
+            // notify == null
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            mb.RegisterNotify(null, null, 0);
+        }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentException))]
+        public void reg2()
+        {
+            // maxDelay < 0
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            mb.RegisterNotify(notify, null, -1);
+        }
+
+        [Test]
+        public void reg3()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            mb.RegisterNotify(notify, null, 0);
+        }
+
+        [Test]
+        [ExpectedException(typeof(Exception))]
+        public void reg4()
+        {
+            // this.notify != null
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            mb.RegisterNotify(notify, null, 0);
+            mb.RegisterNotify(notify, null, 0);
+        }
+
+        [Test]
+        [ExpectedException(typeof(Exception))]
+        public void reg5()
+        {
+            // this.notify != null
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            mb.RegisterNotify(notify, null, 0);
+            mb.RegisterNotify(notify1x, null, 0);
+        }
+
+        [Test]
+        public void unreg1()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            mb.UnregisterNotify(notify);
+        }
+
+        [Test]
+        public void unreg2()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            mb.RegisterNotify(notify, null, 0);
+            mb.UnregisterNotify(notify);
+        }
+
+        [Test]
+        public void unreg3()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            mb.RegisterNotify(notify, null, 0);
+            mb.UnregisterNotify(notify);
+            mb.UnregisterNotify(notify);
+            mb.UnregisterNotify(notify1x);
+        }
+
+        [Test]
+        public void unreg4()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            mb.RegisterNotify(notify, null, 0);
+            mb.UnregisterNotify(notify);
+            mb.RegisterNotify(notify, null, 0);
+            mb.UnregisterNotify(notify);
+            mb.RegisterNotify(notify1x, null, 0);
+            mb.UnregisterNotify(notify1x);
+        }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentException))]
+        public void unreg5()
+        {
+            // notify != this.notify
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            mb.RegisterNotify(notify, null, 0);
+            mb.UnregisterNotify(notify1x);
+        }
+
+        [Test]
+        public void unreg6()
+        {
+            PlainMailbox mb = new PlainMailbox(this, 1L);
+            mb.RegisterNotify(notify, null, 30);
+            mb.UnregisterNotify(notify);
+        }
+
+        ///////////////////
+        // HELPFUL STUFF //
+        ///////////////////
+
+        private static ValueFactory vf;
+
+        private static XType mt_foo;
+
+        private Message foo_msg;
+
+        private Who fred_who;
+
+        private static XType mt_bar;
+
+        private Message bar_msg;
+
+        private Who alice_who;
+
+        private MyNotify notify;
+
+        private MyNotify notify1x;
+
+        private void testConstruct(long messageId)
+        {
+            PlainMailbox mb = new PlainMailbox(this, messageId);
+            Assert.AreEqual(this, mb.GetMailboxManager());
+            Assert.AreEqual(messageId, mb.GetMessageId());
+        }
+
+        private void checkDeliver(PlainMailbox mb, bool handled, Who who,
+            Message msg)
+        {
+            Assert.AreEqual(handled, mb.Message(who, msg));
+        }
+
+        private void checkRead(PlainMailbox mb, bool present, Who who, Message msg)
+        {
+            Element e = mb.Read();
+            if (present)
+                checkElement(e, who, msg);
+            else
+                Assert.IsNull(e);
+        }
+
+        private void checkRead(PlainMailbox mb, int maxDelay, bool present,
+            Who who, Message msg)
+        {
+            Element e = mb.Read(maxDelay);
+            if (present)
+                checkElement(e, who, msg);
+            else
+                Assert.IsNull(e);
+        }
+
+        private void checkRedelivered(int index, Who who, Message msg)
+        {
+            Element e = redelivered[index];
+            checkElement(e, who, msg);
+        }
+
+        private void checkElement(Element e, Who who, Message msg)
+        {
+            Assert.IsNotNull(e);
+            Assert.AreSame(who, e.sender);
+            Assert.AreSame(msg, e.msg);
+        }
+
+        private void checkMailbox(PlainMailbox mb, bool empty, bool full,
+            bool closed, bool unreg, int size)
+        {
+            Assert.AreEqual(empty, mb.IsEmpty());
+            Assert.AreEqual(full, mb.IsFull());
+            Assert.AreEqual(closed, mb.IsClosed());
+            Assert.AreEqual(unreg, unregistered);
+            Assert.AreEqual(size, redelivered.Count);
+        }
+
+        private void checkCloseRead(PlainMailbox mb, bool closed)
+        {
+            Assert.AreEqual(closed, mb.CloseRead());
+        }
+
+        private void checkCloseDelivery(PlainMailbox mb, bool closed)
+        {
+            Assert.AreEqual(closed, mb.CloseDelivery());
+        }
+
+        ////////////////////////////////
+        // MailboxManagerIntf methods //
+        ////////////////////////////////
+
+        public void Redeliver(Who sender, Message msg)
+        {
+            redelivered.Add(new Element(sender, msg));
+        }
+
+        private  List<Element> redelivered;
+
+        public void Unregister(Mailbox mb)
+        {
+            unregistered = true;
+        }
+
+        private bool unregistered;
+
+        ////////////////////
+        // MyValueFactory //
+        ////////////////////
+
+        public class MyValueFactory : ValueFactory
+        {
+            public StructValue ExportCustomValue(Object value)
+            {
+                throw new NotSupportedException();
+            }
+
+            public XType GetCustomStructType(Type c)
+            {
+                throw new NotSupportedException();
+
+            }
+
+            public long? GetInReplyTo(Message msg)
+            {
+                throw new NotSupportedException();
+
+            }
+
+            public long? GetMessageId(Message msg)
+            {
+                throw new NotSupportedException();
+
+            }
+
+            public Encoding GetStringEncoding()
+            {
+                throw new NotSupportedException();
+
+            }
+
+            public XType GetType(int id)
+            {
+                throw new NotSupportedException();
+
+            }
+
+            public XType GetType(String name)
+            {
+                throw new NotSupportedException();
+
+            }
+
+            public ICollection<XType> GetTypes()
+            {
+                throw new NotSupportedException(); ;
+            }
+
+            public XType Get_mt__Etch_AuthException()
+            {
+                throw new NotSupportedException();
+
+            }
+
+            public XType Get_mt__Etch_RuntimeException()
+            {
+                throw new NotSupportedException(); ;
+            }
+
+            public XType get_mt__exception()
+            {
+                throw new NotSupportedException();
+            }
+
+            public Object ImportCustomValue(StructValue sv)
+            {
+                throw new NotSupportedException();
+            }
+
+            public void SetInReplyTo(Message msg, long? msgid)
+            {
+                throw new NotSupportedException(); ;
+            }
+
+            public void SetMessageId(Message msg, long? msgid)
+            {
+                throw new NotSupportedException(); ;
+            }
+
+
+            public void AddType(XType type)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void LockDynamicTypes()
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void UnlockDynamicTypes()
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public Field Get_mf__messageId()
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public Field Get_mf__inReplyTo()
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public Validator.Level GetLevel()
+            {
+                return Validator.Level.FULL;
+            }
+
+            public Validator.Level SetLevel(Validator.Level level)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+        }
+
+        public class WhoAmI : Who
+        {
+            
+        }
+
+        public class MyNotify : Notify
+        {
+            public void mailboxStatus(Mailbox mb, Object state, bool closed)
+            {
+                mailboxStatus1 = true;
+                this.mailbox = mb;
+                this.state = state;
+                this.closed = closed;
+            }
+
+            private bool mailboxStatus1;
+
+            private Mailbox mailbox;
+
+            private Object state;
+
+            private bool closed;
+
+            public void checkMailboxStatus(bool mailboxStatus, Mailbox mailbox,
+                Object state, bool closed)
+            {
+                Assert.AreEqual(mailboxStatus, this.mailboxStatus1);
+                Assert.AreSame(mailbox, this.mailbox);
+                Assert.AreSame(state, this.state);
+                Assert.AreEqual(closed, this.closed);
+            }
+        }
+
+        #region MailboxManager Members
+
+
+        public Mailbox TransportCall(Who recipient, Message msg)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        #endregion
+
+        #region TransportMessage Members
+
+        public void TransportMessage(Who recipient, Message msg)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        #endregion
+
+        #region Transport<SessionMessage> Members
+
+        public object TransportQuery(object query)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public void TransportControl(object control, object value)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public void TransportNotify(object eventObj)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public void SetSession(SessionMessage session)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public SessionMessage GetSession()
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        #endregion
+
+        #region SessionMessage Members
+
+        public bool SessionMessage(Who sender, Message msg)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        #endregion
+
+        #region Session Members
+
+        public object SessionQuery(object query)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public void SessionControl(object control, object value)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public void SessionNotify(object eventObj)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        #endregion
+    }
+}
+
+
+   
\ No newline at end of file
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Transport/TestPlainMailboxManager.cs b/binding-csharp/runtime/src/test/csharp/Etch/Transport/TestPlainMailboxManager.cs
new file mode 100644
index 0000000..335ef6f
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Transport/TestPlainMailboxManager.cs
@@ -0,0 +1,405 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    [TestFixture]
+    public class TestPlainMailboxManager
+    {
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestMailboxManager" );
+        }
+
+        private PlainMailboxManager mmgr;
+        private Message msg;
+        private MyMessageHandler mh;
+        private MyMessagizer m;
+
+        private bool duplexFlag = true;
+        private bool registerFlag = false;
+
+        private readonly ValueFactory vf = new MyValueFactory();
+
+        public Message ConstructSimpleMessage()
+        {
+            Message msg = new Message( MyValueFactory.mt_function, vf );
+            return msg;
+        }
+
+        public Message ConstructAddMessage() 
+	    {
+		    msg = new Message( MyValueFactory.mt_add, vf );
+		    msg.Add( MyValueFactory.mf_x, 4 );
+		    msg.Add( MyValueFactory.mf_y, 5 );
+    		
+		    return msg;
+	    }
+
+        [SetUp]
+        public void SetUp()
+        {
+            duplexFlag = true;
+          
+            m = new MyMessagizer(this);
+            mmgr = new PlainMailboxManager(m, "none:", null);
+            mh = new MyMessageHandler(mmgr);
+       
+        }
+    	
+	    [Test]
+	    public void SimplexMessage() 
+	    {
+            Assert.IsNull(m.what);
+    		
+		    Message message = ConstructSimpleMessage();
+		    mmgr.TransportMessage( null, message );
+    		
+		    Assert.AreEqual(m.what, What.MYMESSAGIZERMESSAGE);
+	    }
+    	
+	    [Test]
+	    public void DuplexMessage() 
+	    {
+            Assert.IsNull(m.what);
+		    Assert.IsNull(mh.what);
+
+            mmgr.SessionNotify(SessionConsts.UP);
+            Message message = ConstructAddMessage();
+            mmgr.TransportCall( null, message);
+    		
+		    Assert.AreEqual(m.what, What.MYMESSAGIZERMESSAGE);
+    		
+		    /* 
+		     * Because PlainMailbox will intercept messages ...
+		     * The Default messagehandler won't be called.
+		     */
+            Assert.AreEqual(What.OOB_NOTIFY_HANDLER, mh.what);
+	    }
+    	
+	    [Test]
+	    public void DuplicateRegistration() 
+	    {
+            mmgr.SessionNotify(SessionConsts.UP);
+
+            Message message = ConstructAddMessage();
+		    Mailbox mb = 
+                ( Mailbox ) mmgr.TransportCall( null, message);
+
+		    /*
+		     * Check for duplicate registration
+		     */
+		    try 
+		    {
+			    mmgr.Register(mb);
+		    }
+		    catch (Exception)
+		    {
+			    registerFlag = true;
+		    }
+		    Assert.IsTrue(registerFlag);
+	    }
+    	
+	    [Test]
+	    public void TestUnregistration() 
+	    {
+            mmgr.SessionNotify(SessionConsts.UP);
+            Message message = ConstructAddMessage();
+		    Mailbox mb =  mmgr.TransportCall( null, message );
+
+		    /*
+		     * Unregister and then register again ... 
+		     */
+		    mmgr.Unregister(mb);
+            registerFlag = false;
+		    try 
+		    {
+                mmgr.Register( ( Mailbox ) mb );
+		    }
+		    catch (Exception)
+		    {
+                registerFlag = true;
+		    }
+		    Assert.IsFalse(registerFlag);
+
+	    }
+    	
+	    [Test]
+	    public void NoMailboxOrReplyToId() 
+	    {
+            Assert.IsNull(mh.what);
+		    Assert.IsNull(m.what);
+    		
+		    duplexFlag = false;
+		    Message message = ConstructAddMessage();
+    		
+		    m.TransportMessage(null, message);
+    		
+		    Assert.AreEqual(m.what, What.MYMESSAGIZERMESSAGE);
+		    /*
+		     * Since no mailbox, default message handler receives
+		     * messages.
+		     */
+		    Assert.AreEqual(mh.what, What.MMGRMESSAGEHANDLERMESSAGE);
+	    }
+
+        public enum What
+        {
+            MMGRMESSAGEHANDLERSTARTED,
+            MMGRMESSAGEHANDLERUP,
+            MMGRMESSAGEHANDLERDown,
+            MMGRMESSAGEHANDLERSTOPPED,
+            MYMESSAGIZERClose,
+            MYMESSAGIZERLocalAddress,
+            MYMESSAGIZERRemoteAddress,
+            MYMESSAGIZERShutdownInput,
+            MYMESSAGIZERShutdownOutput,
+            MYMESSAGIZERSTOP,
+            MYMESSAGIZERMESSAGE,
+            MMGRMESSAGEHANDLERMESSAGE, 
+            OOB_CONTROL_HANDLER, 
+            OOB_NOTIFY_HANDLER, 
+            OOB_QUERY_HANDLER
+        };
+
+        public class MyMessageHandler : SessionMessage
+        {
+            public Enum what;
+
+            public Who xsender;
+
+            public Message xmsg;
+
+            public Object xcontrol;
+
+            public Object xvalue;
+
+            public Object xquery;
+
+            public Object xevent;
+
+            public Object xquery_result;
+
+            public TransportMessage _tmm;
+
+            public MyMessageHandler()
+            {
+                // nothing to do.
+            }
+
+            public MyMessageHandler( TransportMessage tmm )
+            {
+                _tmm = tmm;
+                _tmm.SetSession(this);
+            }
+    		
+            //public bool Message( Who sender, Message msg ) 
+            //{
+            //    what = What.MMGRMESSAGEHANDLERMESSAGE;
+            //    xsender = sender;
+            //    xmsg = msg;
+            //    return true;
+            //}
+
+           
+
+            #region Session Members
+
+            public object SessionQuery( object query )
+            {
+                what = What.OOB_QUERY_HANDLER;
+                xquery = query;
+                return xquery_result;
+            }
+
+            public void SessionControl( object control, object value )
+            {
+                what = What.OOB_CONTROL_HANDLER;
+                xcontrol = control;
+                xvalue = value;
+            }
+
+            public void SessionNotify( object eventObj )
+            {
+                what = What.OOB_NOTIFY_HANDLER;
+                xevent = eventObj;
+            }
+
+            #endregion
+
+            #region SessionMessage Members
+
+            public bool SessionMessage(Who sender, Message msg)
+            {
+                what = What.MMGRMESSAGEHANDLERMESSAGE;
+                xsender = sender;
+                xmsg = msg;
+                return true;
+            }
+
+            #endregion
+        }
+
+        public class MyMessagizer : TransportMessage
+        {
+            private SessionMessage handler;
+
+            public Enum what;
+
+            public TestPlainMailboxManager _tmm;
+
+            public MyMessagizer( TestPlainMailboxManager tmm )
+            {
+                _tmm = tmm;
+            }
+
+      
+
+            public override string ToString()
+            {
+                return "My Messagizer";
+            }
+
+          
+            //public void Messagex( Who recipient, Message msg ) 
+            //{
+            //    // message from mailbox manager
+            //    what = What.MYMESSAGIZERMESSAGE;
+    			
+            //    // send message back ... 
+            //    if ( _tmm.duplexFlag == true )
+            //        msg.InReplyTo = msg.MessageId;
+				    
+            //    handler.Message(null, msg);
+            //}
+
+           
+           
+
+            #region Transport Members
+
+            public object TransportQuery( object query )
+            {
+                return null;
+            }
+
+            public void TransportControl( object control, object value )
+            {
+                // ignore
+            }
+
+            public void TransportNotify( object eventObj )
+            {
+                // ignore
+            }
+
+            #endregion
+
+            #region TransportMessage Members
+
+            public void TransportMessage(Who recipient, Message msg)
+            {
+                // message from mailbox manager
+                what = What.MYMESSAGIZERMESSAGE;
+
+                // send message back ... 
+                if (_tmm.duplexFlag == true)
+                    msg.InReplyTo = msg.MessageId;
+
+                handler.SessionMessage(null, msg);
+            }
+
+            #endregion
+
+            #region Transport<SessionMessage> Members
+
+
+            public void SetSession(SessionMessage session)
+            {
+                this.handler = session;
+            }
+
+            #endregion
+
+            #region Transport<SessionMessage> Members
+
+
+            public SessionMessage GetSession()
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+        }
+
+        public class MyValueFactory : DefaultValueFactory
+        {
+            private readonly static TypeMap types = new TypeMap();
+
+            
+
+            private readonly static Class2TypeMap class2type = 
+                new Class2TypeMap();
+
+            public readonly static XType mt_function = types.Get( "function" );
+
+            public readonly static XType mt_add = types.Get( "add" );
+
+            public readonly static XType mt_add_result = types.Get( "add_result" );
+
+            public readonly static Field mf_x = new Field( "x" );
+
+            public readonly static Field mf_y = new Field( "y" );
+
+            public readonly static Field mf_result = new Field( "xresult" );
+
+            static MyValueFactory()
+            {
+                DefaultValueFactory.Init( types, class2type );
+
+                mt_function.PutValidator( DefaultValueFactory._mf__messageId, Validator_long.Get( 0 ) );
+                mt_function.PutValidator( DefaultValueFactory._mf__inReplyTo, Validator_long.Get( 0 ) );
+
+                mt_add.PutValidator( mf_x, Validator_int.Get( 0 ) );
+                mt_add.PutValidator( mf_y, Validator_int.Get( 0 ) );
+                mt_add.PutValidator( DefaultValueFactory._mf__messageId, Validator_long.Get( 0 ) );
+                mt_add.PutValidator( DefaultValueFactory._mf__inReplyTo, Validator_long.Get( 0 ) );
+
+                mt_add_result.PutValidator( mf_result, Validator_int.Get( 0 ) );
+                mt_add_result.PutValidator( DefaultValueFactory._mf__messageId, Validator_long.Get( 0 ) );
+                mt_add_result.PutValidator( DefaultValueFactory._mf__inReplyTo, Validator_long.Get( 0 ) );
+            }
+
+            public MyValueFactory()
+                : base("none:", types, class2type)
+            {
+             
+            }
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Util/TestAlarmManager.cs b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestAlarmManager.cs
new file mode 100644
index 0000000..9bccf9f
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestAlarmManager.cs
@@ -0,0 +1,435 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Threading;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    [TestFixture]
+    public class TestAlarmManager
+    {
+        private const int Q1 = 50;
+
+        private const int Q2 = 100;
+
+        private const int Q3 = 150;
+
+        private readonly Object s1 = new Object();
+
+        private readonly Object s2 = new Object();
+
+        [Test]
+        public void start1()
+        {
+            AlarmManager am = new AlarmManager();
+            Assert.IsFalse(am.IsStarted());
+            am.Start();
+            Assert.IsTrue(am.IsStarted());
+        }
+
+        [Test]
+        [ExpectedException(typeof(Exception))]
+        public void start2()
+        {
+            // already started
+            AlarmManager am = new AlarmManager();
+            Assert.IsFalse(am.IsStarted());
+            am.Start();
+            Assert.IsTrue(am.IsStarted());
+            am.Start();
+        }
+
+        [Test]
+        [ExpectedException(typeof(Exception))]
+        public void stop1()
+        {
+            // is not started
+            AlarmManager am = new AlarmManager();
+            Assert.IsFalse(am.IsStarted());
+            am.Stop();
+        }
+
+        [Test]
+        public void stop2()
+        {
+            AlarmManager am = new AlarmManager();
+            Assert.IsFalse(am.IsStarted());
+            am.Start();
+            Assert.IsTrue(am.IsStarted());
+            am.Stop();
+            Assert.IsFalse(am.IsStarted());
+        }
+
+        [Test]
+        public void static1()
+        {
+            AlarmManager.shutdown();
+
+            Assert.IsNull(AlarmManager.GetAlarmManager(false));
+            Assert.IsNull(AlarmManager.GetAlarmManager(false));
+
+            AlarmManager am1 = AlarmManager.GetAlarmManager(true);
+            Assert.IsNotNull(am1);
+            Assert.IsTrue(am1.IsStarted());
+
+            AlarmManager am2 = AlarmManager.GetAlarmManager(true);
+            Assert.AreSame(am2, am1);
+            Assert.IsTrue(am1.IsStarted());
+
+            AlarmManager.shutdown();
+            Assert.IsFalse(am1.IsStarted());
+            Assert.IsNull(AlarmManager.GetAlarmManager(false));
+
+            AlarmManager.shutdown();
+        }
+
+        [Test]
+        public void listener1()
+        {
+            MyAlarmListener listener = new MyAlarmListener(0);
+
+            Assert.AreEqual(0, listener.delay);
+            Assert.IsFalse(listener.wake.Get());
+            Assert.IsNull(listener.state);
+
+            listener.Wakeup(null, null, 12345);
+            Assert.AreEqual(0, listener.delay);
+            Assert.IsTrue(listener.wake.Get());
+            Assert.IsNull(listener.state);
+
+            listener.Wakeup(null, s1, 23456);
+            Assert.AreEqual(0, listener.delay);
+            Assert.IsTrue(listener.wake.Get());
+            Assert.AreSame(s1, listener.state);
+
+            MyAlarmListener listener1 = new MyAlarmListener(1);
+            Assert.AreEqual(1, listener1.delay);
+        }
+
+        [Test]
+        [ExpectedException(typeof(Exception))]
+        public void add1()
+        {
+            // is not started
+            AlarmManager am = new AlarmManager();
+
+            MyAlarmListener listener = new MyAlarmListener(0);
+
+            am.Add(listener, null, Q1);
+        }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentNullException))]
+        public void add2()
+        {
+            // listener == null
+            AlarmManager am = new AlarmManager();
+            am.Start();
+
+            am.Add(null, null, Q1);
+        }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentException))]
+        public void add3()
+        {
+            // delay <= 0
+            AlarmManager am = new AlarmManager();
+            am.Start();
+
+            MyAlarmListener listener = new MyAlarmListener(0);
+
+            am.Add(listener, null, -1);
+        }
+
+        [Test]
+        public void add4()
+        {
+            AlarmManager am = new AlarmManager();
+            am.Start();
+
+            MyAlarmListener listener = new MyAlarmListener(0);
+
+            //Log("Adding");
+            am.Add(listener, null, Q1);
+            //Log("Added");
+            Assert.IsFalse(listener.wake.Get());
+            Assert.IsNull(listener.state);
+
+            Thread.Sleep(Q2);
+            Assert.IsTrue(listener.wake.Get());
+            Assert.IsNull(listener.state);
+        }
+
+        [Test]
+        public void add5()
+        {
+            AlarmManager am = new AlarmManager();
+            am.Start();
+
+            MyAlarmListener listener = new MyAlarmListener(0);
+
+            am.Add(listener, s1, Q1);
+            Assert.IsFalse(listener.wake.Get());
+            Assert.IsNull(listener.state);
+
+            Thread.Sleep(Q2);
+            Assert.IsTrue(listener.wake.Get());
+            Assert.AreSame(s1, listener.state);
+        }
+
+        [Test]
+        public void add6()
+        {
+            AlarmManager am = new AlarmManager();
+            am.Start();
+
+            MyAlarmListener listener = new MyAlarmListener(0);
+
+            am.Add(listener, s1, Q3);
+            Assert.IsFalse(listener.wake.Get());
+            Assert.IsNull(listener.state);
+
+            am.Add(listener, s2, Q1);
+            Assert.IsFalse(listener.wake.Get());
+            Assert.IsNull(listener.state);
+
+            Thread.Sleep(Q2);
+            Assert.IsTrue(listener.wake.Get());
+            Assert.AreSame(s2, listener.state);
+        }
+
+        [Test]
+        public void add7()
+        {
+            AlarmManager am = new AlarmManager();
+            am.Start();
+
+            MyAlarmListener listener = new MyAlarmListener(0);
+
+            listener.excp = true;
+            am.Add(listener, s1, Q1);
+            Assert.IsFalse(listener.wake.Get());
+            Assert.IsNull(listener.state);
+
+            Thread.Sleep(Q2);
+            Assert.IsTrue(listener.wake.Get());
+            Assert.AreSame(s1, listener.state);
+        }
+
+        [Test]
+        [ExpectedException(typeof(Exception))]
+        public void remove1()
+        {
+            // is not started
+            AlarmManager am = new AlarmManager();
+
+            MyAlarmListener listener = new MyAlarmListener(0);
+
+            am.Remove(listener);
+        }
+
+        [Test]
+        public void remove2()
+        {
+            AlarmManager am = new AlarmManager();
+            am.Start();
+
+            MyAlarmListener listener = new MyAlarmListener(0);
+
+            am.Remove(listener);
+        }
+
+        [Test]
+        public void remove3()
+        {
+            AlarmManager am = new AlarmManager();
+            am.Start();
+
+            MyAlarmListener listener = new MyAlarmListener(0);
+
+            am.Add(listener, null, Q1);
+            Assert.IsFalse(listener.wake.Get());
+            Assert.IsNull(listener.state);
+
+            am.Remove(listener);
+            Assert.IsFalse(listener.wake.Get());
+            Assert.IsNull(listener.state);
+
+            Thread.Sleep(Q2);
+            Assert.IsFalse(listener.wake.Get());
+            Assert.IsNull(listener.state);
+        }
+
+        [Test]
+        public void repeat1()
+        {
+            AlarmManager am = new AlarmManager();
+            am.Start();
+
+            MyAlarmListener listener = new MyAlarmListener(0);
+
+            listener.delay = Q2;
+            am.Add(listener, null, Q2);
+
+            listener.wake.WaitUntilEqAndSet(true, Q3, false);
+            Console.WriteLine("due0 = {0}", listener.due);
+            long t0 = listener.due;
+
+            listener.wake.WaitUntilEqAndSet(true, Q3, false);
+            Console.WriteLine("due1 = {0}", listener.due);
+            long d1 = listener.due - t0;
+
+            listener.wake.WaitUntilEqAndSet(true, Q3, false);
+            Console.WriteLine("due2 = {0}", listener.due);
+            long d2 = listener.due - t0;
+
+            listener.wake.WaitUntilEqAndSet(true, Q3, false);
+            Console.WriteLine("due3 = {0}", listener.due);
+            long d3 = listener.due - t0;
+
+            Thread.Sleep(Q1);
+            listener.delay = 0;
+
+            listener.wake.WaitUntilEqAndSet(true, Q3, false);
+            Console.WriteLine("due4 = {0}", listener.due);
+            long d4 = listener.due - t0;
+
+            long m1 = (long) Math.Round(d1 / (double)d1);
+            long m2 = (long) Math.Round(d2 / (double)d1);
+            long m3 = (long) Math.Round(d3 / (double)d1);
+            long m4 = (long) Math.Round(d4 / (double)d1);
+
+            Console.WriteLine("times {0} {1} {2} {3} {4}", t0, d1, d2, d3, d4);
+
+            Assert.AreEqual(1, m1);
+            Assert.AreEqual(2, m2);
+            Assert.AreEqual(3, m3);
+            Assert.AreEqual(4, m4);
+        }
+
+        [Test]
+        public void repeat2()
+        {
+            AlarmManager am = new AlarmManager();
+            am.Start();
+
+            MyAlarmListener listener = new MyAlarmListener(0);
+
+            listener.delay = -Q2;
+            am.Add(listener, null, Q2);
+
+            listener.wake.WaitUntilEqAndSet(true, Q3, false);
+            Console.WriteLine("due0 = {0}", listener.due);
+            long t0 = listener.due;
+
+            listener.wake.WaitUntilEqAndSet(true, Q3, false);
+            Console.WriteLine("due1 = {0}", listener.due);
+            long d1 = listener.due - t0;
+
+            listener.wake.WaitUntilEqAndSet(true, Q3, false);
+            Console.WriteLine("due2 = {0}", listener.due);
+            long d2 = listener.due - t0;
+
+            listener.wake.WaitUntilEqAndSet(true, Q3, false);
+            Console.WriteLine("due3 = {0}", listener.due);
+            long d3 = listener.due - t0;
+
+            Thread.Sleep(Q1);
+            listener.delay = 0;
+
+            listener.wake.WaitUntilEqAndSet(true, Q3, false);
+            Console.WriteLine("due4 = {0}", listener.due);
+            long d4 = listener.due - t0;
+
+            long m1 = (long) Math.Round(d1 / (double)d1);
+            long m2 = (long) Math.Round(d2 / (double)d1);
+            long m3 = (long) Math.Round(d3 / (double)d1);
+            long m4 = (long) Math.Round(d4 / (double)d1);
+
+            Console.WriteLine("times {0} {1} {2} {3} {4}", t0, d1, d2, d3, d4);
+
+            Assert.AreEqual(1, m1);
+            Assert.AreEqual(2, m2);
+            Assert.AreEqual(3, m3);
+            Assert.AreEqual(4, m4);
+        }
+
+        [Test]
+        [ExpectedException(typeof(ThreadInterruptedException))]
+        public void repeat3()
+        {
+            // timeout
+            AlarmManager am = new AlarmManager();
+            am.Start();
+
+            MyAlarmListener listener = new MyAlarmListener(0);
+
+            listener.delay = Q2;
+            am.Add(listener, null, Q2);
+
+            listener.wake.WaitUntilEqAndSet(true, Q3, false);
+
+            listener.wake.WaitUntilEqAndSet(true, Q3, false);
+
+            listener.wake.WaitUntilEqAndSet(true, Q3, false);
+
+            Thread.Sleep(Q1);
+            listener.delay = 0;
+
+            listener.wake.WaitUntilEqAndSet(true, Q3, false);
+            // alarm is now canceled
+
+            // this should timeout...
+            listener.wake.WaitUntilEqAndSet(true, Q3, false);
+        }
+    }
+
+    class MyAlarmListener : AlarmListener
+    {
+        public MyAlarmListener(int delay)
+        {
+            this.delay = delay;
+        }
+
+        public int delay;
+
+        public bool excp;
+
+        public Monitor<bool> wake = new Monitor<bool>("wake", false);
+
+        public object state;
+
+        public long due;
+
+        public int Wakeup(AlarmManager manager, object state, long due)
+        {
+            this.state = state;
+            this.due = due;
+            wake.Set(true);
+
+            if (excp)
+                throw new Exception();
+
+            return delay;
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Util/TestCharIterator.cs b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestCharIterator.cs
new file mode 100644
index 0000000..380173c
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestCharIterator.cs
@@ -0,0 +1,71 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    [TestFixture]
+    public class TestCharIterator
+    {
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestCharIterator" );
+        }
+
+
+        [Test]
+        public void TestString1()
+        {
+            String str1 = "tcp";
+            CharIterator ct = new CharIterator( str1 );
+
+            Assert.IsTrue( ct.MoveNext() );
+            Assert.AreEqual( 't', ct.Current );
+            Assert.IsTrue( ct.MoveNext() );
+            Assert.AreEqual( 'c', ct.Current );
+            Assert.IsTrue( ct.MoveNext() );
+            Assert.AreEqual( 'p', ct.Current );
+
+            Assert.IsFalse( ct.MoveNext() );
+        }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentNullException))]
+        public void TestNullString()
+        {
+            String str1 = null;
+            CharIterator ct = new CharIterator( str1 );
+        }
+
+        [Test]
+        public void TestEmptyString()
+        {
+            String str1 = "";
+            CharIterator ct = new CharIterator( str1 );
+
+            Assert.IsFalse( ct.MoveNext() );
+            
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Util/TestCircularQueue.cs b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestCircularQueue.cs
new file mode 100644
index 0000000..aa0c63f
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestCircularQueue.cs
@@ -0,0 +1,754 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Threading;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    internal delegate void run();
+    
+    [TestFixture]
+    public class TestCircularQueue
+    {
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write("TestCircularQueue");
+        }
+
+        
+        [Test]
+       [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+	    public void construct1() 
+	    {
+		    new CircularQueue<int?>( 0 );
+	    }
+
+        
+	[Test]
+        [ExpectedException(typeof(ArgumentOutOfRangeException))]
+	public void construct2() 
+	{
+		new CircularQueue<int?>( -1 );
+	}
+	
+	
+	[Test]
+	public void construct3() 
+	{
+		CircularQueue<int?> queue = new CircularQueue<int?>( 1 );
+		Assert.AreEqual( 1, queue.Size() );
+	}
+	
+	
+	[Test]
+	public void construct4() 
+	{
+		CircularQueue<int?> queue = new CircularQueue<int?>( 2 );
+		Assert.AreEqual( 2, queue.Size() );
+	}
+	
+	
+	[Test]
+	public void construct5() 
+	{
+		CircularQueue<int?> queue = new CircularQueue<int?>();
+		Assert.AreEqual( 10, queue.Size() );
+	}
+	
+	
+	[Test]
+	public void putget1() 
+	{
+		CircularQueue<int?> queue = new CircularQueue<int?>();
+		
+		Assert.AreEqual( 0, queue.Count() );
+		Assert.IsTrue( queue.IsEmpty() );
+		Assert.IsFalse( queue.IsFull() );
+		
+		for (int i = 0; i < 10000; i++)
+		{
+			queue.Put( i );
+			Assert.AreEqual( 1, queue.Count() );
+			Assert.IsFalse( queue.IsEmpty() );
+			
+			Assert.AreEqual( i, queue.Get() );
+			Assert.AreEqual( 0, queue.Count() );
+			Assert.IsTrue( queue.IsEmpty() );
+		}
+	}
+	
+	
+	[Test]
+	public void putget2() 
+	{
+		CircularQueue<int?> queue = new CircularQueue<int?>();
+		
+		Assert.IsNull( queue.Get( 1 ) );
+		Assert.IsNull( queue.Get( -1 ) );
+		Assert.IsNull( queue.Get( 10 ) );
+		
+		queue.Put( 9 );
+		Assert.AreEqual( 9, queue.Get( 1 ) );
+		
+		queue.Put( 9 );
+		Assert.AreEqual( 9, queue.Get( -1 ) );
+		
+		queue.Put( 9 );
+		Assert.AreEqual( 9, queue.Get( 10 ) );
+		
+		Assert.IsNull( queue.Get( 1 ) );
+		Assert.IsNull( queue.Get( -1 ) );
+		Assert.IsNull( queue.Get( 10 ) );
+		
+	/*	long t0;
+		double t;
+		
+	
+	    t0 = HPTimer.Now();
+	    Assert.IsNull(queue.Get(10));
+        t = ( HPTimer.Now() - t0) / 1000000.0;
+		assertRelError( 10, t, 1 );
+		
+		
+        t0 = HPTimer.Now();
+	    Assert.IsNull(queue.Get(20));
+        t = (HPTimer.Now() - t0) / 1000000.0;
+		assertRelError( 20, t, 1 );
+		
+	
+        t0 = HPTimer.Now();
+		Assert.IsNull( queue.Get( 30 ) );
+        t = (HPTimer.Now() - t0) / 1000000.0;
+		assertRelError( 30, t, 1 ); */
+	}
+	
+	
+	[Test]
+	public void putget3() 
+	{
+		CircularQueue<int?> queue = new CircularQueue<int?>();
+		
+		Assert.IsTrue( queue.Put( 1 ) );
+		Assert.IsTrue( queue.Put( 2 ) );
+		Assert.IsTrue( queue.Put( 3 ) );
+		Assert.AreEqual( 1, queue.Get() );
+		Assert.AreEqual( 2, queue.Get() );
+		Assert.AreEqual( 3, queue.Get() );
+		
+		Assert.IsTrue( queue.Put( 1, 0 ) );
+		Assert.IsTrue( queue.Put( 2, 0 ) );
+		Assert.IsTrue( queue.Put( 3, 0 ) );
+		Assert.AreEqual( 1, queue.Get( 0 ) );
+		Assert.AreEqual( 2, queue.Get( 0 ) );
+		Assert.AreEqual( 3, queue.Get( 0 ) );
+		
+		Assert.IsTrue( queue.Put( 1, -1 ) );
+		Assert.IsTrue( queue.Put( 2, -1 ) );
+		Assert.IsTrue( queue.Put( 3, -1 ) );
+		Assert.AreEqual( 1, queue.Get( -1 ) );
+		Assert.AreEqual( 2, queue.Get( -1 ) );
+		Assert.AreEqual( 3, queue.Get( -1 ) );
+		
+		Assert.IsTrue( queue.Put( 1, 1 ) );
+		Assert.IsTrue( queue.Put( 2, 1 ) );
+		Assert.IsTrue( queue.Put( 3, 1 ) );
+		Assert.AreEqual( 1, queue.Get( 1 ) );
+		Assert.AreEqual( 2, queue.Get( 1 ) );
+		Assert.AreEqual( 3, queue.Get( 1 ) );
+	}
+	
+	
+	[Test]
+	public void get() 
+	{
+		CircularQueue<int?> queue = new CircularQueue<int?>( 1 );
+		
+	//	System.nanoTime();
+        HPTimer.Now();
+		Assert.IsNull( queue.Get( 10 ) );
+		assertRelError( 1, 1, 1 );
+
+	    foreach (int i in new int[] { 10, 20, 30, 50, 80, 130, 210, 340, 550, 890, 1440 })	   
+		{
+		//	Console.WriteLine( "get delay = {0}\n", i );
+            long t0 = HPTimer.Now();
+			Assert.IsNull( queue.Get( i ) );
+      /*      double t = (HPTimer.Now() - t0) / 1000000.0;
+			assertRelError( i, t, 2 ); */
+		}
+	}
+	
+	
+	[Test]
+        [ExpectedException(typeof(ArgumentNullException))]
+	public void put() 
+	{
+		CircularQueue<int?> queue = new CircularQueue<int?>();
+		queue.Put( null );
+	}
+	
+	
+	[Test]
+	public void full() 
+	{
+		CircularQueue<int?> queue = new CircularQueue<int?>( 1 );
+		
+		Assert.IsFalse( queue.IsFull() );
+		Assert.IsTrue( queue.Put( 0 ) );
+		Assert.IsTrue( queue.IsFull() );
+		Assert.AreEqual( 0, queue.Get() );
+		Assert.IsFalse( queue.IsFull() );
+		
+		Assert.IsTrue( queue.Put( 0 ) );
+		Assert.IsFalse( queue.Put( 0, -1 ) );
+		Assert.IsFalse( queue.Put( 0, 1 ) );
+		Assert.IsFalse( queue.Put( 0, 10 ) );
+	}
+	
+	
+	[Test]
+	public void close1() 
+	{
+		CircularQueue<int?> queue = new CircularQueue<int?>();
+		
+		Assert.IsFalse( queue.IsClosed() );
+		queue.Close();
+		Assert.IsTrue( queue.IsClosed() );
+		
+		Assert.IsNull( queue.Get() );
+		Assert.IsNull( queue.Get( -1 ) );
+		Assert.IsNull( queue.Get( 0 ) );
+		Assert.IsNull( queue.Get( 1 ) );
+		
+		queue.Close();
+		Assert.IsTrue( queue.IsClosed() );
+	}
+	
+	
+	[Test]
+	public void close2() 
+	{
+		CircularQueue<int?> queue = new CircularQueue<int?>();
+
+		Assert.IsFalse( queue.IsClosed() );
+		queue.Close();
+		Assert.IsTrue( queue.IsClosed() );
+		
+		Assert.IsFalse( queue.Put( 0 ) );
+		Assert.IsFalse( queue.Put( 0, -1 ) );
+		Assert.IsFalse( queue.Put( 0, 0 ) );
+		Assert.IsFalse( queue.Put( 0, 1 ) );
+		
+		queue.Close();
+		Assert.IsTrue( queue.IsClosed() );
+	}
+	
+	
+	[Test]
+	public void close3() 
+	{
+		CircularQueue<int?> queue = new CircularQueue<int?>();
+		queue.Put( 1 );
+		queue.Put( 2 );
+		queue.Put( 3 );
+		queue.Close();
+		Assert.AreEqual( 1, queue.Get() );
+		Assert.AreEqual( 2, queue.Get() );
+		Assert.AreEqual( 3, queue.Get() );
+		Assert.IsNull( queue.Get() );
+	}
+	
+	
+	[Test]
+	public void delay1() 
+	{
+		CircularQueue<int?> queue = new CircularQueue<int?>();
+		
+		Delay( 10, delegate() {queue.Put( 99 ); } );
+		Assert.AreEqual( 99, queue.Get() );
+		
+		Delay( 10, delegate() { queue.Close(); } );
+		Assert.IsNull( queue.Get() ); 
+	}
+	
+	
+	[Test]
+	public void delay2() 
+	{
+		 CircularQueue<int?> queue = new CircularQueue<int?>( 1 );
+		
+		Assert.IsTrue( queue.Put( 1 ) );
+		Delay( 10, delegate() { Assert.AreEqual( 1, queue.Get() ); } );
+		Assert.IsTrue( queue.Put( 2 ) );
+		Assert.AreEqual( 2, queue.Get() );
+		
+		Assert.IsTrue( queue.Put( 1 ) );
+	    Delay(10, delegate() { queue.Close(); });
+		Assert.IsFalse( queue.Put( 2 ) );
+		Assert.AreEqual( 1, queue.Get() );
+		Assert.IsNull( queue.Get() );
+	}
+	
+	
+	[Test]
+	public void stress1() 
+	{
+		 CircularQueue<int?> queue = new CircularQueue<int?>( 1 );
+		 int n = 10000;
+
+         Thread t = new Thread(
+             delegate()
+             {
+                for (int i = 0; i < n; i++)
+				{
+					try
+					{
+						queue.Put( i );
+					}
+					catch ( ThreadInterruptedException e )
+					{
+						Console.WriteLine(e);
+					}
+				}  
+             }
+        );
+		
+		t.Start();
+		
+		for (int i = 0; i < n; i++)
+			Assert.AreEqual( i, queue.Get() );
+	}
+	
+	
+	[Test]
+	public void stress2() 
+	{
+		CircularQueue<int?> queue = new CircularQueue<int?>( 1 );
+		 int n = 1000;
+
+         Thread t = new Thread(
+             delegate()
+             {
+                for (int i = 0; i < n; i++)
+				{
+					try
+					{
+						Thread.Sleep( 5 );
+                        queue.Put( i );
+					}
+					catch ( ThreadInterruptedException e )
+					{
+						Console.WriteLine(e);
+					}
+				}  
+             }
+        );
+		
+		t.Start();
+     
+		for (int i = 0; i < n; i++)
+			Assert.AreEqual( i, queue.Get() );
+	}
+	
+	
+	[Test]
+	public void stress3() 
+	{
+		
+        CircularQueue<int?> queue = new CircularQueue<int?>( 1 );
+		 int n = 1000;
+
+         Thread t = new Thread(
+             delegate()
+             {
+                for (int i = 0; i < n; i++)
+				{
+					try
+					{
+						
+                        queue.Put( i );
+					}
+					catch ( ThreadInterruptedException e )
+					{
+						Console.WriteLine(e);
+					}
+				}  
+             }
+        );
+		
+		t.Start();
+        
+        
+		
+		for (int i = 0; i < n; i++)
+		{
+			Thread.Sleep( 5 );
+			Assert.AreEqual( i, queue.Get() );
+		}
+	}
+	
+	
+	[Test]
+	public void stress4() 
+	{
+		 CircularQueue<int?> queue = new CircularQueue<int?>();
+		
+		// we will setup two threads waiting to get and
+		// then in a single synchronized step put two
+		// items in the queue. the first thread will be
+		// woken to get, and once done the second thread
+		// should be woken by the first.
+		
+		Thread t1 = new Thread( 
+            delegate()
+		    {			
+				try
+				{
+					Assert.IsNotNull( queue.Get() );
+				}
+				catch ( ThreadInterruptedException e )
+				{
+					Console.WriteLine(e);
+				}
+			}
+		);
+		
+		Thread t2 = new Thread( 
+            delegate()
+		    {
+				try
+				{
+					Assert.IsNotNull( queue.Get() );
+				}
+				catch ( ThreadInterruptedException e )
+				{
+                    Console.WriteLine(e);
+				}
+		    }
+        );
+
+		t1.Start();
+		t2.Start();
+		
+		// wait until both threads are waiting on queue...
+		
+		Thread.Sleep( 100 );
+		
+		lock(queue)
+		{
+			queue.Put( 1 );
+			queue.Put( 2 );
+		}
+
+		harvest( t1 );
+		harvest( t2 );
+	}
+	
+	
+	[Test]
+	public void stress5() 
+	{
+		 CircularQueue<int?> queue = new CircularQueue<int?>( 3 );
+		
+		// we will setup two threads waiting to put to the queue,
+		// then in a single synchronized step, read two items from
+		// the queue. the first thread will be woken to put, and
+		// once done the second thread should be woken by the first.
+		
+		queue.Put( 0 );
+		queue.Put( 1 );
+		queue.Put( 2 );
+		Assert.IsTrue( queue.IsFull() );
+		
+		Thread t1 = new Thread( 
+            delegate()
+		    {
+			
+				try
+				{
+					Assert.IsTrue( queue.Put( 3 ) );
+				}
+				catch ( ThreadInterruptedException e )
+				{
+                    Console.WriteLine(e);
+				}
+			}
+		 );
+		
+		Thread t2 = new Thread(
+            delegate()
+		    {
+				try
+				{
+					Assert.IsTrue( queue.Put( 4 ) );
+				}
+				catch ( ThreadInterruptedException e )
+				{
+                    Console.WriteLine(e);
+				}
+			}
+		);
+		
+		t1.Start();
+		t2.Start();
+		
+		// wait until both threads are waiting on queue...
+		
+		Thread.Sleep( 100 );
+		
+		lock(queue)
+		{
+			Assert.IsNotNull( queue.Get() );
+			Assert.IsNotNull( queue.Get() );
+		}
+
+		harvest( t1 );
+		harvest( t2 );
+	}
+	
+	
+	[Test]
+	public void stress6() 
+	{
+		CircularQueue<int?> queue = new CircularQueue<int?>( 5 );
+		
+		// start two getters and two putters and let 'em duke it out...
+		
+		Thread t1 = new Thread( 
+            delegate()
+		    {
+				try
+				{
+					for (int i = 0; i < 100; i++)
+						Assert.IsTrue( queue.Put( i ) );
+				}
+				catch ( ThreadInterruptedException e )
+				{
+                    Console.WriteLine(e);
+				}
+			}
+		);
+		
+		Thread t2 = new Thread(
+            delegate()
+		    {
+				try
+				{
+					for (int i = 0; i < 100; i++)
+						Assert.IsTrue( queue.Put( i ) );
+				}
+				catch ( ThreadInterruptedException e )
+				{
+                    Console.WriteLine(e);
+				}
+			}
+		);
+		
+		Thread t3 = new Thread(
+            delegate()
+		    {
+				try
+				{
+					for (int i = 0; i < 100; i++)
+						Assert.IsNotNull( queue.Get() );
+				}
+				catch ( ThreadInterruptedException e )
+				{
+                    Console.WriteLine(e);
+				}
+			}
+		);
+		
+		Thread t4 = new Thread(
+            delegate()
+		    {
+				try
+				{
+					for (int i = 0; i < 100; i++)
+						Assert.IsNotNull( queue.Get() );
+				}
+				catch ( ThreadInterruptedException e )
+				{
+                    Console.WriteLine(e);
+				}
+			}
+		);
+		
+		t1.Start();
+		t2.Start();
+		t3.Start();
+		t4.Start();
+
+		harvest( t1 );
+		harvest( t2 );
+		harvest( t3 );
+		harvest( t4 );
+	}
+	
+	
+	[Test]
+	public void harvest1() 
+	{
+		Thread t = new Thread(
+            delegate()
+            {
+            }
+        );
+		t.Start();
+		harvest( t );
+	}
+	
+	
+	[Test]
+    [ExpectedException( typeof( TimeoutException ) )]
+	public void harvest2() 
+	{
+		Thread t = new Thread( 
+            delegate() 
+		    {
+				try
+				{
+					Thread.Sleep( 10000 );
+				}
+				catch ( ThreadInterruptedException e )
+				{
+                    Console.WriteLine(e);
+				}
+			}
+		);
+		t.Start();
+		harvest( t );
+	} 
+	
+	private void harvest( Thread t ) 
+	{
+		t.Join( 1000 );
+		if (t.IsAlive)
+		{
+			t.Interrupt();
+			throw new TimeoutException( t.Name+" is stuck" );
+		}
+	}
+	
+	
+	[Test]
+	public void testRelError1() 
+	{
+		assertRelError( 10, 9, .11 );
+		assertRelError( 10, 11, .14 );
+		assertRelError( 20, 19, .07 );
+		assertRelError( 19, 23, .22 );
+	}
+	
+	
+	[Test]
+     [ExpectedException( typeof(AssertionException ) )]
+	public void testRelError2() 
+	{
+		assertRelError( 9, 8, .1 );
+	}
+	
+	
+	[Test]
+    [ExpectedException( typeof(AssertionException ) )]
+	public void testRelError3() 
+	{
+		assertRelError( 9, 10, .1 );
+	}
+	
+	
+	[Test]
+	public void testAbsError1() 
+	{
+		AssertAbsError( 11, 15, 4 );
+		AssertAbsError( 15, 10, 5 );
+		AssertAbsError( 5, 3, 2 );
+		AssertAbsError( 4, 7, 3 );
+	}
+	
+	
+	[Test]
+    [ExpectedException( typeof(AssertionException ) )]
+	public void testAbsError2() 
+	{
+		AssertAbsError( 11, 15, 3 );
+	}
+	
+	
+	[Test]
+    [ExpectedException(typeof(AssertionException))]
+	public void testAbsError3() 
+	{
+		AssertAbsError( 19, 15, 3 );
+	} 
+	
+	private void Delay(  int delay, run del )
+	{
+
+        Thread t = new Thread(delegate()
+                                  {
+                                      try
+                                      {
+                                          Thread.Sleep(delay);
+                                          del();
+                                      }
+                                      catch (Exception e)
+                                      {
+                                          Console.WriteLine(e);
+                                      }
+                                  });
+        t.Start();
+
+      
+	}
+	
+	
+
+	private void assertRelError( double expected, double actual, double error )
+	{
+		double relError = RelError( expected, actual );
+		if (relError > error)
+			Assert.Fail( String.Format( "expected: {0} but was: {1} relative error: {2}", expected, actual, relError ) );
+	}
+	
+	private void AssertAbsError( double expected, double actual, double error )
+	{
+		double absError = AbsError( expected, actual );
+		if (absError > error)
+           
+			Assert.Fail( String.Format( "expected: {0} but was: {1} absolute error: {2}", expected, actual, absError ) );
+	}
+	
+	private double RelError( double expected, double actual )
+	{
+		return AbsError( expected, actual ) / expected;
+	}
+	
+	private double AbsError( double expected, double actual )
+	{
+		return Math.Abs( expected - actual );
+	}
+
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Util/TestDateSerializer.cs b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestDateSerializer.cs
new file mode 100644
index 0000000..53af295
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestDateSerializer.cs
@@ -0,0 +1,66 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    [TestFixture]
+    public class TestDateSerializer
+    {
+        private readonly ValueFactory vf = new DummyValueFactory();
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestDateSerializer" );
+        }
+
+
+        [Test]
+        public void TestImport()
+        {
+            DateTime date = new DateTime();
+            TestDate( date );
+        }
+
+        private void TestDate( DateTime date )
+        {
+            XType type = new XType( "date" );
+          
+            Class2TypeMap class2type = 
+                new Class2TypeMap();
+            
+            DateSerializer.Init( type, class2type );
+
+            ImportExportHelper helper = type.GetImportExportHelper();
+            StructValue sv = helper.ExportValue( vf, date );
+
+            Assert.AreEqual( sv.GetXType, type );
+
+            DateTime date2 = ( DateTime ) helper.ImportValue( sv );
+
+            Assert.AreEqual( date, date2 );
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Util/TestFlexBuffer.cs b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestFlexBuffer.cs
new file mode 100644
index 0000000..9ae6ab4
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestFlexBuffer.cs
@@ -0,0 +1,1336 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.IO;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    [TestFixture]
+    public class TestFlexBuffer
+    {
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write("TestFlexBuffer");
+        }
+
+
+        private FlexBuffer buf = new FlexBuffer();
+
+        // General test function
+        private void CheckBuf( int length, int index, int avail )
+        {
+            Assert.AreEqual( length, buf.Length() );
+            Assert.AreEqual( index, buf.Index() );
+            Assert.AreEqual( avail, buf.Avail() );
+        }
+
+        #region Basic Tests
+
+        [Test]
+        public void Initial1()
+        {
+            buf = new FlexBuffer();
+            CheckBuf( 0, 0, 0 );
+        }
+
+        [Test]
+        public void Initial2()
+        {
+            buf = new FlexBuffer( new byte[ 5 ] );
+            CheckBuf( 5, 0, 5 );
+        }
+
+        [Test]
+        public void Initial3()
+        {
+            buf = new FlexBuffer( new byte[ 5 ], 2 );
+            CheckBuf( 2, 0, 2 );
+        }
+
+        [Test]
+        public void Initial4()
+        {
+            buf = new FlexBuffer( new byte[ 5 ], 1, 3 );
+            CheckBuf( 4, 1, 3 );
+        }
+
+        [Test]
+        public void SetLength0()
+        {
+            buf.SetLength( 0 );
+            CheckBuf( 0, 0, 0 );
+        }
+
+        [Test]
+        public void SetLength1()
+        {
+            buf.SetLength( 1 );
+            CheckBuf( 1, 0, 1 );
+        }
+
+        [Test]
+        public void SetLength2()
+        {
+            buf.SetLength( 2 );
+            CheckBuf( 2, 0, 2 );
+        }
+
+        [Test]
+        public void SetLength3()
+        {
+            buf.SetLength( 2 );
+            buf.SetLength( 0 );
+            CheckBuf( 0, 0, 0 );
+        }
+
+        [Test]
+        [ExpectedException ( typeof ( ArgumentOutOfRangeException ) )]
+        public void SetLength4()
+        {
+            buf.SetLength( -1 );
+        }
+
+        [Test]
+        public void SetIndex0()
+        {
+            buf.Reset();
+            buf.SetIndex( 0 );
+            CheckBuf( 0, 0, 0 );
+        }
+
+        [Test]
+        [ExpectedException ( typeof ( ArgumentOutOfRangeException ) )]
+        public void SetIndex1()
+        {
+            buf.Reset();
+            buf.SetIndex( 1 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+        public void SetIndex2()
+        {
+            buf.SetIndex( -1 );
+        }
+        
+        [Test]
+        public void SetIndex3()
+        {
+            buf.SetLength( 5 );
+            buf.SetIndex( 1 );
+            CheckBuf( 5, 1, 4 );
+        }
+
+        [Test]
+        public void SetIndex4()
+        {
+            buf.SetLength( 5 );
+            buf.SetIndex( 4 );
+            CheckBuf( 5, 4, 1 );
+        }
+
+        [Test]
+        public void SetIndex5()
+        {
+            buf.SetLength( 5 );
+            buf.SetIndex( 5 );
+            CheckBuf( 5, 5, 0 );
+        }
+
+        [Test]
+        public void SetIndex6()
+        {
+            buf.SetLength( 5 );
+            buf.SetIndex( 5 );
+            buf.SetLength( 0 );
+            CheckBuf( 0, 0, 0 );
+        }
+
+        [Test]
+        public void SetIndex7()
+        {
+            buf.SetLength( 5 );
+            buf.SetIndex( 5 );
+            buf.SetLength( 2 );
+            CheckBuf( 2, 2, 0 );
+        }
+
+        [Test]
+        public void Reset()
+        {
+            buf.SetLength( 2 );
+            buf.SetIndex( 1 );
+            buf.Reset();
+            CheckBuf( 0, 0, 0 );
+        }
+        #endregion Basic Tests
+
+        #region Cases for put ( int )
+        // put once or twice (the put 0 case has already been tested).
+
+        [Test]
+        public void Put1a()
+        {
+            buf.Reset();
+            buf.Put( 1 );
+            CheckBuf( 1, 1, 0 );
+        }
+        
+        [Test]
+        public void Put1b()
+        {
+            buf.Reset();
+            buf.Put( 1 );
+            buf.Put( 2 );
+            CheckBuf( 2, 2, 0 );
+        }
+
+        #endregion Cases for put ( int )
+
+        #region Cases for put ( byte[] buf )
+        // buf.length = null, 0, 1, 2
+
+        private void TestPutBytes( int bufLen )
+        {
+            buf.Reset();
+            buf.Put( 1 );
+            buf.Put( bufLen >= 0 ? new byte[ bufLen ] : null );
+            CheckBuf( bufLen + 1, bufLen + 1, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof ( NullReferenceException ) )]
+        public void Put2a()
+        {
+            TestPutBytes( -1 );
+        }
+
+        [Test]
+        public void Put2b()
+        {
+            TestPutBytes( 0 );
+        }
+
+        [Test]
+        public void Put2c()
+        {
+            TestPutBytes( 1 );
+        }
+
+        [Test]
+        public void Put2d()
+        {
+            TestPutBytes( 2 );
+        }
+
+        #endregion Cases for put ( byte[] buf )
+
+        #region Cases for put( byte[] buf, int off, int len )
+        // buf.length, off, len // failure reason
+        // --- group 3:
+        // null, 0, 0 // fail (buf is null)
+        // null, 0, 1 // fail (buf is null)
+        // null, 1, 0 // fail (buf is null)
+        // --- group 4:
+        // 0, 0, 0
+        // 0, 0, 1 // fail (off+len > buf.length)
+        // 0, 1, 0 // fail (off > buf.length)
+        // --- group 5:
+        // 1, 0, 0
+        // 1, 0, 1
+        // 1, 0, 2 // fail (off+len > buf.length)
+        // 1, 1, 0
+        // 1, 1, 1 // fail (off+len > buf.length)
+        // 1, 1, 2 // fail (off+len > buf.length)
+        // 1, 2, 0 // fail (off > buf.length)
+        // 1, 2, 1 // fail (off > buf.length)
+        // 1, 2, 2 // fail (off > buf.length)
+        // --- group 6:
+        // 2, 0, 0
+        // 2, 0, 1
+        // 2, 0, 2
+        // 2, 1, 0
+        // 2, 1, 1
+        // 2, 1, 2 // fail (off+len > buf.length)
+        // 2, 2, 0	
+        // 2, 2, 1 // fail (off+len > buf.length)
+        // 2, 2, 2 // fail (off+len > buf.length)
+
+        private void TestPutBytesOffLen( int bufLen, int offset, int length )
+        {
+            buf.Reset();
+            buf.Put( 1 );
+            buf.Put( bufLen >= 0 ? new byte[ bufLen ] : null, offset, length );
+            CheckBuf( length + 1, length + 1, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( NullReferenceException ) )]
+        public void Put3a()
+        {
+            TestPutBytesOffLen( -1, 0, 0 ); // fail (buf is null)
+        }
+        
+        [Test]
+        [ExpectedException( typeof( NullReferenceException ) )]
+        public void Put3b()
+        {
+            TestPutBytesOffLen( -1, 0, 1 ); // fail (buf is null)
+        }
+
+        [Test]
+        [ExpectedException( typeof( NullReferenceException ) )]
+        public void Put3c()
+        {
+            TestPutBytesOffLen( -1, 1, 0 ); // fail (buf is null)
+        }
+
+        [Test]
+        public void Put4a()
+        {
+            TestPutBytesOffLen( 0, 0, 0 ); 
+        }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentOutOfRangeException))]
+        public void Put4b()
+        {
+            TestPutBytesOffLen( 0, 0, 1 ); // fail (off+len > buf.length)
+        }
+
+        [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+        public void Put4c()
+        {
+            TestPutBytesOffLen( 0, 1, 0 ); // fail (off > buf.length)
+        }
+
+        [Test]
+        public void Put5a()
+        {
+            TestPutBytesOffLen( 1, 0, 0 );
+        }
+        
+        [Test]
+        public void Put5b()
+        {
+            TestPutBytesOffLen( 1, 0, 1 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+        public void Put5c()
+        {
+            TestPutBytesOffLen( 1, 0, 2 ); // fail (off+len > buf.length)
+        }
+
+        [Test]
+        public void Put5d()
+        {
+            TestPutBytesOffLen( 1, 1, 0 ); 
+        }
+
+        [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+        public void Put5e()
+        {
+            TestPutBytesOffLen( 1, 1, 1 ); // fail (off+len > buf.length)
+        }
+
+        [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+        public void Put5f()
+        {
+            TestPutBytesOffLen( 1, 1, 2 ); // fail (off+len > buf.length)
+        }
+
+        [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+        public void Put5g()
+        {
+            TestPutBytesOffLen( 1, 2, 0 ); // fail (off > buf.length)
+        }
+
+        [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+        public void Put5h()
+        {
+            TestPutBytesOffLen( 1, 2, 1 ); // fail (off > buf.length)
+        }
+
+        [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+        public void Put5i()
+        {
+            TestPutBytesOffLen( 1, 2, 2 ); // fail (off > buf.length)
+        }
+
+        [Test]
+        public void Put6a()
+        {
+            TestPutBytesOffLen( 2, 2, 0 ); 
+        }
+
+        [Test]
+        public void Put6b()
+        {
+            TestPutBytesOffLen( 2, 0, 1 ); 
+        }
+
+        [Test]
+        public void Put6c()
+        {
+            TestPutBytesOffLen( 2, 0, 2 );
+        }
+
+        [Test]
+        public void Put6d()
+        {
+            TestPutBytesOffLen( 2, 1, 0 );
+        }
+
+        [Test]
+        public void Put6e()
+        {
+            TestPutBytesOffLen( 2, 1, 1 );
+        }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentOutOfRangeException))]
+        public void Put6f()
+        {
+            TestPutBytesOffLen( 2, 1, 2 ); // fail (off+len > buf.length)
+        }
+
+        [Test]
+        public void Put6g()
+        {
+            TestPutBytesOffLen( 2, 2, 0 ); 
+        }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentOutOfRangeException))]
+        public void Put6h()
+        {
+            TestPutBytesOffLen( 2, 2, 1 ); // fail (off+len > buf.length)
+        }
+
+        [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+        public void Put6i()
+        {
+            TestPutBytesOffLen( 2, 2, 2 ); // fail (off+len > buf.length)
+        }
+
+        #endregion Cases for put( byte[] buf, int off, int len )
+
+        #region Cases for Put( int ), Get() 
+        // put 0, get 0. // already tested above
+        // put 0, get 1. // fails with EOFException
+        // put 1, get 0.
+        // put 1, get 1.
+        // put 1, get 2. // fails with EOFException
+        // put 2, get 0.
+        // put 2, get 1.
+        // put 2, get 2.
+        // put 2, get 3. // fails with EOFException
+        // put 10000, get 10000.
+
+        // just like above, putting byte array instead
+        // just like above, getting byte array instead.
+        // just like above, putting and getting byte array.
+
+        private void TestPutGet( int nPuts, int nGets )
+        {
+            buf.Reset();
+
+            for ( int i = 0; i < nPuts; i++ )
+                buf.Put( i );
+
+            buf.SetIndex( 0 );
+
+            for ( int i =0; i < nGets; i++ )
+                Assert.AreEqual( ( byte ) i, ( byte ) buf.Get() );
+
+            CheckBuf( nPuts, nGets, nPuts - nGets );
+        }
+
+        private void TestPutBytesGet( int nPuts, int nGets )
+        {
+            buf.Reset();
+
+            byte[] buffer = new byte[ nPuts ];
+            for ( int i = 0; i < nPuts; i++ )
+                buffer[ i ] = ( byte ) i;
+
+            buf.Put( buffer );
+            buf.SetIndex( 0 );
+
+            for ( int i =0; i<nGets; i++ )
+                Assert.AreEqual( ( byte ) i, ( byte ) buf.Get() );
+
+            CheckBuf( nPuts, nGets, nPuts-nGets );
+        }
+
+        private void TestPutGetBytes( int nPuts, int nGets )
+        {
+            buf.Reset();
+
+            for ( int i = 0; i < nPuts; i++ )
+                buf.Put( i );
+
+            buf.SetIndex( 0 );
+
+            byte[] buffer = new byte[ nGets ];
+            int n = buf.Get( buffer );
+            Assert.AreEqual( Math.Min( nPuts, nGets ), n );
+
+            for ( int i =0; i < n; i++ )
+                Assert.AreEqual( ( byte ) i, buffer[ i ] );
+
+            CheckBuf( nPuts, n, nPuts-n );
+        }
+
+        private void TestPutBytesGetBytes( int nPuts, int nGets )
+        {
+            buf.Reset();
+
+            byte[] buffer = new byte[ nPuts ];
+            for ( int i = 0; i < nPuts; i++ )
+                buffer[ i ] = ( byte ) i;
+
+            buf.Put( buffer );
+            buf.SetIndex( 0 );
+
+            buffer = new byte[ nGets ];
+            int n = buf.Get( buffer );
+            Assert.AreEqual( Math.Min( nPuts, nGets ), n );
+
+            for ( int i =0; i < n; i++ )
+                Assert.AreEqual( ( byte ) i, buffer[ i ] );
+
+            CheckBuf( nPuts, n, nPuts-n );
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void Get1a()
+        {
+            TestPutGet( 0, 1 );
+        }
+
+        [Test]
+        public void Get1b()
+        {
+            TestPutGet( 1, 0 );
+        }
+
+        [Test]
+        public void Get1c()
+        {
+            TestPutGet( 1, 1 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void Get1d()
+        {
+            TestPutGet( 1, 2 );
+        }
+
+        [Test]
+        public void Get1e()
+        {
+            TestPutGet( 2, 0 );
+        }
+
+        [Test]
+        public void Get1f()
+        {
+            TestPutGet( 2, 1 );
+        }
+
+        [Test]
+        public void Get1g()
+        {
+            TestPutGet( 2, 2 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void Get1h()
+        {
+            TestPutGet( 2, 3 );
+        }
+
+        [Test]
+        public void Get1i()
+        {
+            TestPutGet( 10000, 9995 );
+        }
+
+        [Test]
+        public void Get1j()
+        {
+            TestPutGet( 10000, 10000 );
+        }
+
+        [Test]
+        public void Get1k()
+        {
+            TestPutGet( 100000, 100000 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void Get2a()
+        {
+            TestPutBytesGet( 0, 1 );
+        }
+
+        [Test]
+        public void Get2b()
+        {
+            TestPutBytesGet( 1, 0 );
+        }
+
+        [Test]
+        public void Get2c()
+        {
+            TestPutBytesGet( 1, 1 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void Get2d()
+        {
+            TestPutBytesGet( 1, 2 );
+        }
+
+        [Test]
+        public void Get2e()
+        {
+            TestPutBytesGet( 2, 0 );
+        }
+
+        [Test]
+        public void Get2f()
+        {
+            TestPutBytesGet( 2, 1 );
+        }
+
+        [Test]
+        public void Get2g()
+        {
+            TestPutBytesGet( 2, 2 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void Get2h()
+        {
+            TestPutBytesGet( 2, 3 );
+        }
+
+        [Test]
+        public void Get2i()
+        {
+            TestPutBytesGet( 10000, 9995 );
+        }
+
+        [Test]
+        public void Get2j()
+        {
+            TestPutBytesGet( 10000, 10000 );
+        }
+
+        [Test]
+        public void Get2k()
+        {
+            TestPutBytesGet( 100000, 100000 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void Get3a()
+        {
+            TestPutGetBytes( 0, 1 );
+        }
+
+        [Test]
+        public void Get3b()
+        {
+            TestPutGetBytes( 1, 0 );
+        }
+
+        [Test]
+        public void Get3c()
+        {
+            TestPutGetBytes( 1, 1 );
+        }
+
+        [Test]
+        public void Get3d()
+        {
+            TestPutGetBytes( 1, 2 );
+        }
+
+        [Test]
+        public void Get3e()
+        {
+            TestPutGetBytes( 2, 0 );
+        }
+
+        [Test]
+        public void Get3f()
+        {
+            TestPutGetBytes( 2, 1 );
+        }
+
+        [Test]
+        public void Get3g()
+        {
+            TestPutGetBytes( 2, 2 );
+        }
+
+        [Test]
+        public void Get3h()
+        {
+            TestPutGetBytes( 2, 3 );
+        }
+
+        [Test]
+        public void Get3i()
+        {
+            TestPutGetBytes( 10000, 9995 );
+        }
+
+        [Test]
+        public void Get3j()
+        {
+            TestPutGetBytes( 10000, 10000 );
+        }
+
+        [Test]
+        public void Get3k()
+        {
+            TestPutGetBytes( 100000, 100000 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void Get4a()
+        {
+            TestPutBytesGetBytes( 0, 1 );
+        }
+
+        [Test]
+        public void Get4b()
+        {
+            TestPutBytesGetBytes( 1, 0 );
+        }
+
+        [Test]
+        public void Get4c()
+        {
+            TestPutBytesGetBytes( 1, 1 );
+        }
+
+        [Test]
+        public void Get4d()
+        {
+            TestPutBytesGetBytes( 1, 2 );
+        }
+
+        [Test]
+        public void Get4e()
+        {
+            TestPutBytesGetBytes( 2, 0 );
+        }
+
+        [Test]
+        public void Get4f()
+        {
+            TestPutBytesGetBytes( 2, 1 );
+        }
+
+        [Test]
+        public void Get4g()
+        {
+            TestPutBytesGetBytes( 2, 2 );
+        }
+
+        [Test]
+        public void Get4h()
+        {
+            TestPutBytesGetBytes( 2, 3 );
+        }
+
+        [Test]
+        public void Get4i()
+        {
+            TestPutBytesGetBytes( 10000, 9995 );
+        }
+
+        [Test]
+        public void Get4j()
+        {
+            TestPutBytesGetBytes( 10000, 10000 );
+        }
+
+        [Test]
+        public void Get4k()
+        {
+            TestPutBytesGetBytes( 100000, 100000 );
+        }
+
+        [Test]
+        public void Get5a()
+        {
+            buf = new FlexBuffer( new byte[] { 1, 2, 3 } );
+            Assert.AreEqual( 1, buf.Get() );
+            Assert.AreEqual( 2, buf.Get() );
+            Assert.AreEqual( 3, buf.Get() );
+            CheckBuf( 3, 3, 0 );
+        }
+
+        [Test]
+        public void Get5b()
+        {
+            buf = new FlexBuffer( new byte[] { 1, 2, 3 }, 2 );
+            Assert.AreEqual( 1, buf.Get() );
+            Assert.AreEqual( 2, buf.Get() );
+            CheckBuf( 2, 2, 0 );
+        }
+
+        [Test]
+        public void Get5c()
+        {
+            buf = new FlexBuffer( new byte[] { 1, 2, 3, 4, 5 }, 1, 2 );
+            Assert.AreEqual( 2, buf.Get() );
+            Assert.AreEqual( 3, buf.Get() );
+            CheckBuf( 3, 3, 0 );
+        }
+
+        #endregion
+
+        #region Other tests
+
+        [Test]
+        public void Get6()
+        {
+            buf = new FlexBuffer( new byte[] { 5, 6, 7, 8 } );
+            byte[] buffer = new byte[] { 11, 12, 13, 14, 15 };
+            buf.Get( buffer, 1, 3 );
+            Assert.AreEqual( ( byte ) 11, buffer[ 0 ] );
+            Assert.AreEqual( ( byte ) 5, buffer[ 1 ] );
+            Assert.AreEqual( ( byte ) 6, buffer[ 2 ] );
+            Assert.AreEqual( ( byte ) 7, buffer[ 3 ] );
+            Assert.AreEqual( ( byte ) 15, buffer[ 4 ] );
+        }
+
+        [Test]
+        public void Compact()
+        {
+            buf = new FlexBuffer( new byte[] { 1, 2, 3, 4, 5 }, 1, 3 );
+            buf.Compact();
+            CheckBuf( 3, 0, 3 );
+            Assert.AreEqual( 2, buf.Get() );
+            Assert.AreEqual( 3, buf.Get() );
+            Assert.AreEqual( 4, buf.Get() );
+        }
+
+        #endregion
+
+        #region Test data gets ( int, byte, short, etc )
+
+        [Test]
+        public void GetByte1()
+        {
+            buf = new FlexBuffer( new byte[] { 127, 1, 0, unchecked( (byte)-1), unchecked( (byte)-128) } );
+            Assert.AreEqual( ( byte ) 127, buf.GetByte() );
+            Assert.AreEqual( ( byte ) 1, buf.GetByte() );
+            Assert.AreEqual( ( byte ) 0, buf.GetByte() );
+            Assert.AreEqual( -1, buf.GetByte() );
+            Assert.AreEqual( -128 , buf.GetByte() );
+            CheckBuf( 5, 5, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void GetByte2()
+        {
+            buf.GetByte();
+        }
+
+        [Test]
+        public void GetShort1()
+        {
+            buf = new FlexBuffer( new byte[] { 2, 1, unchecked( ( byte ) -2 ), unchecked( ( byte ) -1 ) } );
+            if ( FlexBuffer.littleEndian )
+            {
+                Assert.AreEqual( ( short ) 0x0102, buf.GetShort() );
+                Assert.AreEqual( unchecked( ( short ) 0xfffe ), buf.GetShort() );
+            }
+            else
+            {
+                Assert.AreEqual( ( short ) 0x0201, buf.GetShort() );
+                Assert.AreEqual( unchecked( ( short ) 0xfeff ), buf.GetShort() );
+            }
+            CheckBuf( 4, 4, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void GetShort2()
+        {
+            buf.GetShort();
+        }
+
+        [Test]
+        public void GetInt1()
+        {
+            buf = new FlexBuffer( new byte[] { 4, 3, 2, 1, unchecked( ( byte ) -4 ), unchecked( ( byte ) -3 ), 
+                unchecked( ( byte ) -2 ), unchecked( ( byte ) -1 ) } );
+            if ( FlexBuffer.littleEndian )
+            {
+                Assert.AreEqual( 0x01020304, buf.GetInt() );
+                Assert.AreEqual( unchecked( ( int ) 0xfffefdfc ), buf.GetInt() );
+            }
+            else
+            {
+                Assert.AreEqual( 0x04030201, buf.GetInt() );
+                Assert.AreEqual( unchecked( ( int ) 0xfcfdfeff ), buf.GetInt() );
+            }
+            CheckBuf( 8, 8, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void GetInt2()
+        {
+            buf.GetInt();
+        }
+
+        [Test]
+        public void GetLong1()
+        {
+            buf = new FlexBuffer( new byte[] { 8, 7, 6, 5, 4, 3, 2, 1, unchecked( ( byte ) -8 ), unchecked( ( byte ) -7 ), 
+                unchecked( ( byte ) -6 ), unchecked( ( byte ) -5 ), unchecked( ( byte ) -4 ), unchecked( ( byte ) -3 ), 
+                unchecked( ( byte ) -2 ), unchecked( ( byte ) -1 ) } );
+            if ( FlexBuffer.littleEndian )
+            {
+                Assert.AreEqual( 0x0102030405060708L, buf.GetLong() );
+                Assert.AreEqual( unchecked( ( long ) 0xfffefdfcfbfaf9f8L ), buf.GetLong() );
+            }
+            else
+            {
+                Assert.AreEqual( 0x0807060504030201L, buf.GetLong() );
+                Assert.AreEqual( unchecked( ( long ) 0xf8f9fafbfcfdfeffL ), buf.GetLong() );
+            }
+
+            CheckBuf( 16, 16, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void GetLong2()
+        {
+            buf.GetLong();
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void GetFloat1()
+        {
+            buf = new FlexBuffer( new byte[] { } );
+            Assert.AreEqual( 123456e-10f, buf.GetFloat() );
+            Assert.AreEqual( 123456e10f, buf.GetFloat() );
+            CheckBuf( 0, 0, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void GetFloat2()
+        {
+            buf.GetFloat();
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void GetDouble1()
+        {
+            buf = new FlexBuffer( new byte[] { } );
+            Assert.AreEqual( 123456789123456789e-110, buf.GetDouble() );
+            Assert.AreEqual( 123456789123456789e110, buf.GetDouble() );
+            CheckBuf( 0, 0, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void GetDouble2()
+        {
+            buf.GetDouble();
+        }
+
+        [Test]
+        public void GetFully1()
+        {
+            buf = new FlexBuffer( new byte[] { 1, 2, 3, 4, 5, 6 } );
+            byte[] b = new byte[ 3 ];
+            buf.GetFully( b );
+            Assert.AreEqual( ( byte ) 1, b[ 0 ] );
+            Assert.AreEqual( ( byte ) 2, b[ 1 ] );
+            Assert.AreEqual( ( byte ) 3, b[ 2 ] );
+            buf.GetFully( b );
+            Assert.AreEqual( ( byte ) 4, b[ 0 ] );
+            Assert.AreEqual( ( byte ) 5, b[ 1 ] );
+            Assert.AreEqual( ( byte ) 6, b[ 2 ] );
+            CheckBuf( 6, 6, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void GetFully2()
+        {
+            buf = new FlexBuffer( new byte[] { 1, 2 } );
+            byte[] b = new byte[ 3 ];
+            buf.GetFully( b ); 
+        }
+
+        #endregion
+
+        #region Cases for Flexbuffer Put( FlexBuffer, ... )
+
+        // put, put FlexBuffer with valid buffer
+        // put, put Flexbuffer to a Flexbuffer approaching max length, fails with IOException.
+
+        [Test]
+        public void PutFlexBuffer1()
+        {
+            FlexBuffer buf0 = new FlexBuffer( new byte[] { 1, 2 } );
+            buf = new FlexBuffer( new byte[] { } );
+            buf.Put( buf0 );
+            CheckBuf( buf0.Length(), buf0.Length(), 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( IOException ) )]
+        public void PutFlexBuffer2()
+        {
+            FlexBuffer buf0 = new FlexBuffer( new byte[] { 1, 2 } );
+            int max = 4*1024*1024;
+            buf = new FlexBuffer( new byte[ max ] );
+            buf.SetIndex( max );
+            buf.Put( buf0 );
+            CheckBuf( max+buf0.Length(), max+buf0.Length(), 0 );
+        }
+
+        // put, put FlexBuffer with length larger than available bytes, fails with IllegalArgumentException
+        // put, put FlexBuffer with valid length value
+        // put, put Flexbuffer to a Flexbuffer approaching max length, fails with IOException.
+
+        [Test]
+        [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
+        public void PutFlexBuffer3()
+        {
+            FlexBuffer buf0 = new FlexBuffer( new byte[] { 1, 2 } );
+            buf = new FlexBuffer( new byte[] { } );
+            buf.SetIndex( 0 );
+            buf.Put( buf0, 3 );
+            CheckBuf( 3, 3, 0 );
+        }
+
+        [Test]
+        public void PutFlexBuffer4()
+        {
+            FlexBuffer buf0 = new FlexBuffer( new byte[] { 1, 2 } );
+            buf = new FlexBuffer( new byte[] { } );
+            buf.Put( buf0, 1 );
+            CheckBuf( 1, 1, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( IOException ) )]
+        public void PutFlexBuffer5() 
+	    {
+		    FlexBuffer buf0 = new FlexBuffer( new byte[] { 1, 2 } );
+		    int max = 4*1024*1024;
+		    buf = new FlexBuffer( new byte[max] );
+            buf.SetIndex( max );
+            buf.Put( buf0, 1 );
+		    CheckBuf( max+1, max+1, 0 );
+	    }
+
+        #endregion
+
+        #region Cases for void putByte( byte )
+        // putByte, put byte value and expect getByte to return matched value.
+        // putByte to a Flexbuffer approaching max length, fails with IOException.
+
+        [Test]
+        public void PutByte1()
+        {
+            buf = new FlexBuffer( new byte[] { } );
+            buf.PutByte( ( byte ) 0x01 );
+            CheckBuf( 1, 1, 0 );
+            buf.SetIndex( 0 );
+            Assert.AreEqual( ( byte ) 0x01, buf.GetByte() );
+            CheckBuf( 1, 1, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( IOException ) )]
+        public void PutByte2()
+        {
+            int max = 4*1024*1024;
+            buf = new FlexBuffer( new byte[ max ] );
+            buf.SetIndex( max );
+            buf.PutByte( ( byte ) 0x01 );
+            CheckBuf( max+1, max+1, 0 );
+        }
+
+        #endregion
+
+        #region Cases for void PutDouble( Double )
+        // putDouble, put Double and expect getDouble to return matched value.
+        // putDouble to a Flexbuffer approaching max length, fails with IOException.
+
+        [Test]
+        public void PutDouble1()
+        {
+            buf = new FlexBuffer( new byte[] { } );
+            buf.PutDouble( Double.MaxValue );
+            CheckBuf( 8, 8, 0 );
+            buf.SetIndex( 0 );
+            Assert.AreEqual( Double.MaxValue, buf.GetDouble() );
+            CheckBuf( 8, 8, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( IOException ) )]
+        public void PutDouble2()
+        {
+            int max = 4*1024*1024;
+            buf = new FlexBuffer( new byte[ max ] );
+            buf.SetIndex( max );
+            buf.PutDouble( Double.MinValue );
+            CheckBuf( max+8, max+8, 0 );
+        }
+
+        #endregion
+
+        #region Cases for void putFloat( float )
+        // putFloat, put Float and expect getFloat to return matched value.
+        // putFloat to a Flexbuffer approaching max length, fails with IOException.
+
+        [Test]
+        public void PutFloat1()
+        {
+            buf = new FlexBuffer( new byte[] { } );
+            buf.PutFloat( float.MaxValue );
+            CheckBuf( 4, 4, 0 );
+            buf.SetIndex( 0 );
+            Assert.AreEqual( float.MaxValue, buf.GetFloat() );
+            CheckBuf( 4, 4, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( IOException ) )]
+        public void PutFloat2()
+        {
+            int max = 4*1024*1024;
+            buf = new FlexBuffer( new byte[ max ] );
+            buf.SetIndex( max );
+            buf.PutFloat( float.MinValue );
+            CheckBuf( max+4, max+4, 0 );
+        }
+
+        #endregion
+
+        #region Cases for void PutInt( int )
+        // putInt, put Int and expect getInt to return matched value.
+        // putInt to a Flexbuffer approaching max length, fails with IOException.
+
+        [Test]
+        public void PutInt1()
+        {
+            buf = new FlexBuffer( new byte[] { } );
+            buf.PutInt( int.MaxValue );
+            CheckBuf( 4, 4, 0 );
+            buf.SetIndex( 0 );
+            Assert.AreEqual( int.MaxValue, buf.GetInt() );
+            CheckBuf( 4, 4, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( IOException ) )]
+        public void PutInt2()
+        {
+            int max = 4*1024*1024;
+            buf = new FlexBuffer( new byte[ max ] );
+            buf.SetIndex( max );
+            buf.PutInt( int.MinValue );
+            CheckBuf( max+4, max+4, 0 );
+        }
+
+        #endregion
+
+        #region Cases for void putLong( long )
+        // putLong, put Long and expect getLong to return matched value.
+        // putShort to a Flexbuffer approaching max length, fails with IOException.
+
+        [Test]
+        public void PutLong0()
+        {
+            buf = new FlexBuffer( new byte[] { } );
+            buf.PutLong( long.MaxValue );
+            CheckBuf( 8, 8, 0 );
+            buf.SetIndex( 0 );
+            Assert.AreEqual( long.MaxValue, buf.GetLong() );
+            CheckBuf( 8, 8, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( IOException ) )]
+        public void PutLong1()
+        {
+            int max = 4*1024*1024;
+            buf = new FlexBuffer( new byte[ max ] );
+            buf.SetIndex( max );
+            buf.PutLong( long.MinValue );
+            CheckBuf( max+8, max+8, 0 );
+        }
+
+        #endregion
+
+        #region Cases for void PutShort( short )
+        // putShort, put short and expect getShort to return matched value.
+        // putShort to a Flexbuffer approaching max length, fails with IOException.
+
+        [Test]
+        public void PutShort1()
+        {
+            buf = new FlexBuffer( new byte[] { } );
+            buf.PutShort( short.MaxValue );
+            CheckBuf( 2, 2, 0 );
+            buf.SetIndex( 0 );
+            Assert.AreEqual( short.MaxValue, buf.GetShort() );
+            CheckBuf( 2, 2, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( IOException ) )]
+        public void PutShort2()
+        {
+            int max = 4*1024*1024;
+            buf = new FlexBuffer( new byte[ max ] );
+            buf.SetIndex( max );
+            buf.PutShort( ( short ) 1 );
+            CheckBuf( max+2, max+2, 0 );
+        }
+
+        #endregion
+
+        #region Cases for FlexBuffer Skip( int, bool )
+        // skip length < 0, put = false.  				// fails with illegal argument
+        // skip length > buffer length, put = false.  	// fails with EOFException
+        // skip length = 0, put = false.
+        // skip length = buffer length, put = false.
+        // skip length < buffer length, put = false.
+        // skip length > buffer length, put = true. 
+        // skip length < buffer length, put = true.	
+        // skip length = max buffer length, put = true.	// fails with IOException
+
+
+        [Test]
+        [ExpectedException( typeof( ArgumentException ) )]
+        public void Skip1()
+        {
+            buf = new FlexBuffer( new byte[] { } );
+            buf.Skip( -1, false );		
+        }
+
+        [Test]
+        [ExpectedException( typeof( EndOfStreamException ) )]
+        public void Skip2()
+        {
+            buf = new FlexBuffer( new byte[] { 1, 2 } );
+            buf.Skip( 3, false );
+        }
+
+        [Test]
+        public void Skip3()
+        {
+            buf = new FlexBuffer( new byte[] { } );
+            buf.Skip( 0, false );
+            CheckBuf( 0, 0, 0 );
+        }
+
+        [Test]
+        public void Skip4()
+        {
+            buf = new FlexBuffer( new byte[] { 1, 2 } );
+            buf.Skip( 2, false );
+            CheckBuf( 2, 2, 0 );
+        }
+
+        [Test]
+        public void Skip5()
+        {
+            buf = new FlexBuffer( new byte[] { 1, 2 } );
+            buf.Skip( 1, false );
+            CheckBuf( 2, 1, 1 );
+        }
+
+        [Test]
+        public void Skip6()
+        {
+            buf = new FlexBuffer( new byte[] { 1, 2 } );
+            buf.Skip( 1, true );
+            CheckBuf( 2, 1, 1 );
+        }
+
+        [Test]
+        public void Skip7()
+        {
+            buf = new FlexBuffer( new byte[] { 1, 2 } );
+            buf.Skip( 5, true );
+            CheckBuf( 5, 5, 0 );
+        }
+
+        [Test]
+        [ExpectedException( typeof( IOException ) )]
+        public void Skip8()
+        {
+            buf = new FlexBuffer( new byte[] { 1, 2 } );
+
+            int max = 4*1024*1024;
+            buf.Skip( max+1, true );
+            CheckBuf( max+1, max+1, 0 );
+        }
+
+        #endregion
+
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Util/TestHPTimer.cs b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestHPTimer.cs
new file mode 100644
index 0000000..8e49e3d
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestHPTimer.cs
@@ -0,0 +1,84 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System.Threading;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    [TestFixture]
+    public class TestHPTimer
+    {
+        [Test]
+        public void one()
+        {
+            System.Console.WriteLine("one starting");
+
+            long x = HPTimer.Now();
+            for (int i = 0; i < 10000; i++)
+            {
+                // assert that values from HPTimer.Now() are always monotonically increasing
+                long y = HPTimer.Now();
+                Assert.GreaterOrEqual(y, x);
+                long diff = y - x;
+                Assert.GreaterOrEqual(y, 0);
+                int idiff = (int) diff;
+                Assert.GreaterOrEqual(idiff, 0);
+                x = y;
+                Thread.Sleep(1);
+            }
+
+            System.Console.WriteLine("one done");
+        }
+
+        [Test]
+        public void two()
+        {
+            System.Console.WriteLine("two starting");
+
+            Thread t1 = new Thread(foo);
+            Thread t2 = new Thread(foo);
+
+            t1.Start();
+            t2.Start();
+
+            t1.Join();
+            t2.Join();
+
+            System.Console.WriteLine("two done");
+        }
+
+        public void foo()
+        {
+            long x = HPTimer.Now();
+            for (int i = 0; i < 10000; i++)
+            {
+                // assert that values from HPTimer.Now() are always monotonically increasing
+                long y = HPTimer.Now();
+                Assert.GreaterOrEqual(y, x);
+                long diff = y - x;
+                Assert.GreaterOrEqual(y, 0);
+                int idiff = (int)diff;
+                Assert.GreaterOrEqual(idiff, 0);
+                x = y;
+                Thread.Sleep(1);
+            }
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Util/TestHelp.cs b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestHelp.cs
new file mode 100644
index 0000000..92a26db
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestHelp.cs
@@ -0,0 +1,82 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Threading;
+using NUnit.Framework;
+
+namespace Etch4.Util.Test
+{
+    public class TestHelp
+    {
+
+        public static Thread delayAndStart( int delay, Thread runnable )
+	{
+		Thread t = Delay( delay, runnable );
+		t.Start();
+		return t;
+	}
+
+    public static Thread Delay( int delay,  Thread runnable )
+	{
+		Thread t = new Thread( new ThreadStart(delegate()
+		                                           {
+		                                             try
+				{
+					Thread.Sleep( delay );
+					runnable.Start();
+				}
+				catch ( Exception e )
+				{
+					Console.WriteLine(" The exception in TestHelp->delay is " + e);
+				}  
+		                                           } ));
+		
+			
+		return t;
+	}
+
+    public static void AssertRelError(double expected, double actual, double error)
+    {
+        double relError = RelError(expected, actual);
+        if (relError > error)
+            Assert.Fail(String.Format("expected: {0} but was: {1} relative error: {2}", expected, actual, relError));
+            
+    }
+
+    public static void AssertAbsError(double expected, double actual, double error)
+    {
+        double absError = AbsError(expected, actual);
+        if (absError > error)
+            Assert.Fail(String.Format("expected: {0} but was: {1} relative error: {2}", expected, actual, error));
+    }
+
+    public static double RelError(double expected, double actual)
+    {
+        return AbsError(expected, actual) / expected;
+    }
+
+    public static double AbsError(double expected, double actual)
+    {
+        return Math.Abs(expected - actual);
+    }
+
+
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Util/TestMonitor.cs b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestMonitor.cs
new file mode 100644
index 0000000..ec136b2
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestMonitor.cs
@@ -0,0 +1,424 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Threading;
+using Etch4.Util.Test;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    [TestFixture]
+    public class TestMonitor
+    {
+        private const double REL_ERROR = 100000;
+	
+	/** @ */
+	[Test]
+	public void construct1() 
+	{
+		testconstruct1( null );
+		testconstruct1( "a" );
+		testconstruct1( "b" );
+	}
+	
+	private void testconstruct1( String descr )
+	{
+		Monitor<Object> m = new Monitor<Object>( descr );
+		Assert.AreEqual( descr, m.GetDescription() );
+		Assert.IsNull( m.Get() );
+	}
+
+	/** @ */
+	[Test]
+	public void construct2() 
+	{
+		testconstruct2( null, null );
+		testconstruct2( null, true );
+		testconstruct2( null, 1 );
+		testconstruct2( null, "abc" );
+		testconstruct2( null, 3.14159 );
+		
+		testconstruct2( "a", null );
+		testconstruct2( "b", true );
+		testconstruct2( "c", 1 );
+		testconstruct2( "d", "abc" );
+		testconstruct2( "e", 3.14159 );
+	}
+	
+	private void testconstruct2( String descr, Object value )
+	{
+		Monitor<Object> m = new Monitor<Object>( descr, value );
+		Assert.AreEqual( descr, m.GetDescription() );
+		Assert.AreEqual( value, m.Get() );
+	}
+	
+	/** @ */
+	[Test]
+	public void mToString() 
+	{
+        Assert.AreEqual("Monitor : ", new Monitor<Object>(null, null).ToString());
+		Assert.AreEqual( "Monitor : True", new Monitor<Object>( null, true ).ToString() );
+		Assert.AreEqual( "Monitor : 1", new Monitor<Object>( null, 1 ).ToString() );
+		Assert.AreEqual( "Monitor : abc", new Monitor<Object>( null, "abc" ).ToString() );
+		Assert.AreEqual( "Monitor : 3.14159", new Monitor<Object>( null, 3.14159 ).ToString() );
+
+		Assert.AreEqual( "Monitor a: ", new Monitor<Object>( "a", null ).ToString() );
+		Assert.AreEqual( "Monitor b: True", new Monitor<Object>( "b", true ).ToString() );
+		Assert.AreEqual( "Monitor c: 1", new Monitor<Object>( "c", 1 ).ToString() );
+		Assert.AreEqual( "Monitor d: abc", new Monitor<Object>( "d", "abc" ).ToString() );
+		Assert.AreEqual( "Monitor e: 3.14159", new Monitor<Object>( "e", 3.14159 ).ToString() );
+	}
+	
+	/** @ */
+	[Test]
+	public void Set1() 
+	{
+		Monitor<Object> m = new Monitor<Object>( "a", null );
+		Assert.AreEqual( null, m.Set( 1 ) );
+		Assert.AreEqual( 1, m.Set( 2 ) );
+		Assert.AreEqual( 2, m.Set( null ) );
+		Assert.AreEqual( null, m.Set( null ) );
+	}
+	
+	/** @ */
+	[Test]
+	public void Set2() 
+	{
+		Monitor<Object> m = new Monitor<Object>( "a", 1 );
+		Assert.AreEqual( 1, m.Set( 2 ) );
+		Assert.AreEqual( 2, m.Set( null ) );
+		Assert.AreEqual( null, m.Set( null ) );
+	}
+	
+	/** @ */
+	[Test]
+	public void SetGet() 
+	{
+		Monitor<Object> m = new Monitor<Object>( "a", 1 );
+		
+		Assert.AreEqual( 1, m.Set( 2 ) );
+		Assert.AreEqual( 2, m.Get() );
+		
+		Assert.AreEqual( 2, m.Set( null ) );
+		Assert.AreEqual( null, m.Get() );
+		
+		Assert.AreEqual( null, m.Set( null ) );
+		Assert.AreEqual( null, m.Get() );
+	}
+	
+	/** @ */
+        [Ignore]
+	[Test]
+	public void Setsync() 
+	{
+		 Monitor<int?> m = new Monitor<int?>( "a", null );
+		 bool[] flag = new bool[2000];
+
+        Thread t = new Thread(new ThreadStart( delegate()
+                                                   {
+                                                       for (int i = 0; i < 1000; i++)
+				{
+					int? x = m.Set( i );
+					
+						flag[x.GetValueOrDefault()] = true;
+				}
+                                                   }));
+
+	    Thread t1 = TestHelp.Delay(1000, t);
+
+
+	    Thread t2 = TestHelp.Delay(1000, new Thread(new ThreadStart(delegate()
+	                     {
+                          for (int i = 1000; i < 2000; i++)
+				         {
+					            int? x = m.Set( i );					
+						        flag[x.GetValueOrDefault()] = true;
+				         }
+	                                                                     
+	                     }
+                         )));
+		
+
+		t1.Start();
+		t2.Start();
+		
+		t1.Join();
+		t2.Join();
+		
+		int? x1 = m.Set( null );
+		
+			flag[x1.GetValueOrDefault()] = true;
+		
+		foreach (bool b  in flag)
+			Assert.IsTrue( b );
+	}
+	
+	/** @ */
+	[Test]
+	public void waitUntilEq1() 
+	{
+		Monitor<int?> m = new Monitor<int?>( "a", null );
+		m.WaitUntilEq( null );
+		m.WaitUntilEq( null, 0 );
+		
+		m.Set( 1 );
+		m.WaitUntilEq( 1 );
+		m.WaitUntilEq( 1, 0 );
+		
+		m.Set( 2 );
+		m.WaitUntilEq( 2 );
+		m.WaitUntilEq( 2, 0 );
+	}
+	
+	/** @ */
+	[Test]
+        [ExpectedException(typeof(ThreadInterruptedException))]
+	public void waitUntilEq2() 
+	{
+		Monitor<int?> m = new Monitor<int?>( "a", 1 );
+		m.WaitUntilEq( 2, 1 );
+	}
+	
+	/** @ */
+        [Test]
+        [ExpectedException(typeof(ThreadInterruptedException))]
+	public void waitUntilEq3() 
+	{
+		Monitor<int?> m = new Monitor<int?>( "a", null );
+		m.WaitUntilEq( 2, 1 );
+	}
+	
+	/** @ */
+        [Test]
+        [ExpectedException(typeof(ThreadInterruptedException))]
+	public void waitUntilEq4() 
+	{
+		Monitor<int?> m = new Monitor<int?>( "a", 1 );
+		m.WaitUntilEq( null, 1 );
+	}
+	
+	/** @ */
+	[Test]
+	public void waitUntilNotEq1() 
+	{
+		Monitor<int?> m = new Monitor<int?>( "a", null );
+		m.WaitUntilNotEq( 1 );
+		m.WaitUntilNotEq( 1, 0 );
+		
+		m.Set( 1 );
+		m.WaitUntilNotEq( null );
+		m.WaitUntilNotEq( null, 0 );
+	}
+	
+	/** @ */
+        [Test]
+        [ExpectedException(typeof(ThreadInterruptedException))]
+	public void waitUntilNotEq2() 
+	{
+		Monitor<int?> m = new Monitor<int?>( "a", null );
+		m.WaitUntilNotEq( null, 1 );
+	}
+	
+	/** @ */
+        [Test]
+        [ExpectedException(typeof(ThreadInterruptedException))]
+	public void waitUntilNotEq3() 
+	{
+		Monitor<int?> m = new Monitor<int?>( "a", 1 );
+		m.WaitUntilNotEq( 1, 1 );
+	}
+	
+	/** @ */
+	[Test]
+	public void waitUntilEqAndSet1() 
+	{
+		Monitor<int?> m = new Monitor<int?>( "a", null );
+		Assert.AreEqual( null, m.WaitUntilEqAndSet( null, 1 ) );
+		Assert.AreEqual( 1, m.WaitUntilEqAndSet( 1, 2 ) );
+		Assert.AreEqual( 2, m.WaitUntilEqAndSet( 2, null ) );
+		Assert.AreEqual( null, m.WaitUntilEqAndSet( null, null ) );
+
+		Assert.AreEqual( null, m.WaitUntilEqAndSet( null, 0, 1 ) );
+		Assert.AreEqual( 1, m.WaitUntilEqAndSet( 1, 0, 2 ) );
+		Assert.AreEqual( 2, m.WaitUntilEqAndSet( 2, 0, null ) );
+		Assert.AreEqual( null, m.WaitUntilEqAndSet( null, 0, null ) );
+	}
+	
+	/** @ */
+        [Test]
+        [ExpectedException(typeof(ThreadInterruptedException))]
+	public void waitUntilEqAndSet2() 
+	{
+		Monitor<int?> m = new Monitor<int?>( "a", null );
+		try
+		{
+			m.WaitUntilEqAndSet( 1, 1, 2 );
+		}
+		finally
+		{
+			Assert.AreEqual( null, m.Get() );
+		}
+	}
+	
+	/** @ */
+        [Test]
+        [ExpectedException(typeof(ThreadInterruptedException))]
+	public void waitUntilEqAndSet3() 
+	{
+		Monitor<int?> m = new Monitor<int?>( "a", 1 );
+		try
+		{
+			m.WaitUntilEqAndSet( null, 1, 2 );
+		}
+		finally
+		{
+			Assert.AreEqual( 1, m.Get() );
+		}
+	}
+	
+	/** @ */
+	[Test]
+	public void waitUntilNotEqAndSet1() 
+	{
+		Monitor<int?> m = new Monitor<int?>( "a", null );
+		Assert.AreEqual( null, m.WaitUntilNotEqAndSet( 2, 1 ) );
+		Assert.AreEqual( 1, m.WaitUntilNotEqAndSet( 3, 2 ) );
+		Assert.AreEqual( 2, m.WaitUntilNotEqAndSet( 4, null ) );
+		Assert.AreEqual( null, m.WaitUntilNotEqAndSet( 5, null ) );
+
+		Assert.AreEqual( null, m.WaitUntilNotEqAndSet( 2, 0, 1 ) );
+		Assert.AreEqual( 1, m.WaitUntilNotEqAndSet( 3, 0, 2 ) );
+		Assert.AreEqual( 2, m.WaitUntilNotEqAndSet( 4, 0, null ) );
+		Assert.AreEqual( null, m.WaitUntilNotEqAndSet( 5, 0, null ) );
+	}
+	
+	/** @ */
+        [Test]
+        [ExpectedException(typeof(ThreadInterruptedException))]
+	public void waitUntilNotEqAndSet2() 
+	{
+		Monitor<int?> m = new Monitor<int?>( "a", null );
+		try
+		{
+			m.WaitUntilNotEqAndSet( null, 1, 1 );
+		}
+		finally
+		{
+			Assert.AreEqual( null, m.Get() );
+		}
+	}
+	
+	/** @ */
+        [Test]
+        [ExpectedException(typeof(ThreadInterruptedException))]
+	public void waitUntilNotEqAndSet3() 
+	{
+		Monitor<int?> m = new Monitor<int?>( "a", 1 );
+		try
+		{
+			m.WaitUntilNotEqAndSet( 1, 1, null );
+		}
+		finally
+		{
+			Assert.AreEqual( 1, m.Get() );
+		}
+	}
+	
+	/** @ */
+	[Test]
+	public void waitUntilEq5() 
+	{
+	    Monitor<int?> m = new Monitor<int?>( "a", null );
+		
+		Thread t = TestHelp.delayAndStart( 200, new Thread(new ThreadStart(delegate()
+		                                                                       {
+		                                                                          m.Set( 1 ); 
+		                                                                       })));
+
+
+	    long t0 = HPTimer.Now();
+		m.WaitUntilEq( 1 );
+		double t1 = (HPTimer.Now() - t0) / 1000000.0;
+		TestHelp.AssertRelError( 200, t1, REL_ERROR );
+		
+		t.Join();
+	}
+	
+	/** @ */
+	[Test]
+	public void waitUntilNotEq4() 
+	{
+		   Monitor<int?> m = new Monitor<int?>( "a", null );
+		
+		Thread t = TestHelp.delayAndStart( 200, new Thread(new ThreadStart(delegate()
+		                                                                       {
+		                                                                          m.Set( 1 ); 
+		                                                                       })));
+
+
+		long t0 = HPTimer.Now();
+		m.WaitUntilNotEq( null );
+		double t1 = (HPTimer.Now() - t0) / 1000000.0;
+		TestHelp.AssertRelError( 200, t1, REL_ERROR );
+		
+		t.Join();
+	}
+	
+	/** @ */
+	[Test]
+	public void waitUntilEqAndSet4() 
+	{
+		Monitor<int?> m = new Monitor<int?>( "a", null );
+		
+		Thread t = TestHelp.delayAndStart( 200, new Thread(new ThreadStart(delegate()
+		                                                                       {
+		                                                                          m.Set( 1 ); 
+		                                                                       })));
+
+	    long t0 = HPTimer.Now();
+		m.WaitUntilEqAndSet( 1, 2 );
+		double t1 = (HPTimer.Now() - t0) / 1000000.0;
+		// TODO is there a better way for choosing relative error?
+		TestHelp.AssertRelError( 200, t1, REL_ERROR );
+		
+		t.Join();
+	}
+	
+	/** @ */
+	[Test]
+	public void waitUntilNotEqAndSet4() 
+	{
+        Monitor<int?> m = new Monitor<int?>("a", null);
+
+        Thread t = TestHelp.delayAndStart(200, new Thread(new ThreadStart(delegate()
+                                                                               {
+                                                                                   m.Set(1);
+                                                                               })));
+
+	    long t0 = HPTimer.Now();
+		m.WaitUntilNotEqAndSet( null, 2 );
+        double t1 = (HPTimer.Now() - t0) / 1000000.0;
+		TestHelp.AssertRelError( 200, t1, REL_ERROR );
+		
+		t.Join();
+	}
+
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Util/TestPacketizer.cs b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestPacketizer.cs
new file mode 100644
index 0000000..ada4065
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestPacketizer.cs
@@ -0,0 +1,701 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{
+    [TestFixture]
+    public class TestPacketizer
+    {
+        private static MyPacketHandler mph ;
+        private static Packetizer p ;
+        private static MyDataHandler dh;
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestPacketizer" );
+        }
+
+        public void SetUp()
+        {
+            dh = new MyDataHandler();
+            p = new Packetizer(dh,"tcp:",null);
+            mph = new MyPacketHandler( p);
+           
+          
+        }
+
+        public class DummyWho : Who 
+        {
+            public DummyWho()
+            {
+                // do nothing
+            }
+        }
+        private Who whoDummy = new DummyWho();
+
+        [Test]
+        public void SendPacket()
+        {
+            SetUp();
+            FlexBuffer buf = new FlexBuffer( new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 } );
+            
+            byte[][] result = ( FlexBuffer.littleEndian )? new byte[][] { new byte[] { 239, 190, 173, 222, 0, 0, 0, 0 }, } :
+                new byte[][] { new byte[] { 222, 173, 190, 239, 0, 0, 0, 0 }, };
+
+        //    p.Packet( whoDummy, buf );
+            p.TransportPacket(whoDummy,buf);
+            Assert.AreEqual( dh.what, What.DATA );
+            Assert.IsTrue( dh.Check( result ) );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+        }
+
+        [Test]
+        public void SendPacket1()
+        {
+            SetUp();
+            // Create Packet to send
+            FlexBuffer buf = new FlexBuffer( new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 1 } );
+            
+            byte[][] result = ( FlexBuffer.littleEndian ) ? new byte[][] { new byte[] { 239, 190, 173, 222, 1, 0, 0, 0, 1 },  } : 
+                new byte[][] { new byte[] { 222, 173, 190, 239, 0, 0, 0, 1, 1 },  };
+
+        //    p.Packet( null, buf );
+            p.TransportPacket(null,buf);
+            Assert.AreEqual( dh.what, What.DATA );
+            Assert.IsTrue( dh.Check( result ) );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+        }
+        
+        [Test]
+        public void SendPacket2() 
+	    {
+            SetUp();
+		    // Create Packet to send
+		    FlexBuffer buf = new FlexBuffer (new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 2, 3 });
+            byte[][] result = ( FlexBuffer.littleEndian ) ? new byte[][] { new byte[] { 239, 190, 173, 222, 2, 0, 0, 0, 2, 3 }, } : 
+                new byte[][] { new byte[] { 222, 173, 190, 239, 0, 0, 0, 2, 2, 3 }, };
+    		
+		    p.TransportPacket(null, buf);
+		    Assert.AreEqual( dh.what, What.DATA );
+		    Assert.IsTrue(dh.Check(result));
+		    Assert.IsNull(dh.xsender);
+		    Assert.IsNull(dh.xbuf);
+	    }
+        
+        ////////////////////////////////////////////////////////////
+        // these tests are for a single Packet in a single buffer //
+        ////////////////////////////////////////////////////////////
+
+        [Test]
+        public void SendSingleSingleData0()
+        {
+            SetUp();
+            // Create Data to send
+            FlexBuffer buf = ( FlexBuffer.littleEndian ) ? new FlexBuffer( new byte[] { 239, 190, 173, 222, 0, 0, 0, 0 } ) :
+                new FlexBuffer( new byte[] { 222, 173, 190, 239, 0, 0, 0, 0 } );
+		    
+            byte[][] result = new byte[][] { };
+    		
+		    p.SessionData(null, buf);
+		    Assert.IsTrue(mph.Check(result));
+    		
+		    Assert.IsNull(mph.what);
+		    Assert.IsNull(mph.xsender);
+		    Assert.IsNull(mph.xbuf);
+        }
+        
+        [Test]
+	    public void SendSingleSingleData1() 
+	    {
+            SetUp();
+		    // length = 1
+            FlexBuffer buf = ( FlexBuffer.littleEndian ) ? new FlexBuffer( new byte[] { 239, 190, 173, 222, 1, 0, 0, 0, 1 } ) :
+                new FlexBuffer( new byte[] { 222, 173, 190, 239, 0, 0, 0, 1, 1 } );
+
+		    byte[][] result = new byte[][] { new byte[] { 1 },  };
+    		
+		    p.SessionData(null, buf);
+		    Assert.IsTrue(mph.Check(result));
+    		
+		    Assert.AreEqual(mph.what, What.PACKET);
+		    Assert.IsNull(mph.xsender);
+		    Assert.IsNull(mph.xbuf);
+	    }
+    	
+	    [Test]
+	    public void SendSingleSingleData2()  
+	    {
+            SetUp();
+		    // length = 2
+            FlexBuffer buf = ( FlexBuffer.littleEndian ) ? new FlexBuffer( new byte[] { 239, 190, 173, 222, 2, 0, 0, 0, 3, 4 } ) :
+                new FlexBuffer( new byte[] { 222, 173, 190, 239, 0, 0, 0, 2, 3, 4 } );
+
+		    byte[][] result = new byte[][] { new byte[] { 3, 4 }, };
+    		
+		    p.SessionData(null, buf);
+		    Assert.IsTrue(mph.Check(result));
+    		
+		    Assert.AreEqual(mph.what, What.PACKET);
+		    Assert.IsNull(mph.xsender);
+		    Assert.IsNull(mph.xbuf);
+	    }
+    	
+	    ////////////////////////////////////////////////////////
+	    // these tests are for two Packets in a single buffer //
+	    ////////////////////////////////////////////////////////
+    	
+	    [Test]
+	    public void SendDoubleSingleData0()  
+	    {
+            SetUp();
+		    // length = 0
+            FlexBuffer buf = ( FlexBuffer.littleEndian ) ? new FlexBuffer( new byte[] { 239, 190, 173, 222, 0, 0, 0, 0, 239, 190, 173, 222, 0, 0, 0, 0 } ) : 
+                new FlexBuffer( new byte[] { 222, 173, 190, 239, 0, 0, 0, 0, 222, 173, 190, 239, 0, 0, 0, 0 } );
+
+		    byte[][] result = new byte[][] {};
+    		
+		    p.SessionData(null, buf);
+    		
+		    Assert.IsTrue(mph.Check(result));
+		    Assert.IsNull(mph.what);
+		    Assert.IsNull(mph.xbuf);
+		    Assert.IsNull(mph.xsender);
+	    }
+    	
+	    [Test]
+	    public void SendDoubleSingleData1()  
+	    {
+            SetUp();
+		    // length = 1
+            FlexBuffer buf = ( FlexBuffer.littleEndian )? new FlexBuffer( new byte[] { 239, 190, 173, 222, 1, 0, 0, 0, 1, 239, 190, 173, 222, 1, 0, 0, 0, 2 } ) : 
+                new FlexBuffer( new byte[] { 222, 173, 190, 239, 0, 0, 0, 1, 1, 222, 173, 190, 239, 0, 0, 0, 1, 2 } );
+
+		    byte[][] result = new byte[][] { new byte[] { 1 }, new byte[] { 2 } };
+    		
+		    p.SessionData(null, buf);
+    		
+		    Assert.IsTrue(mph.Check(result));
+		    Assert.AreEqual(mph.what, What.PACKET);
+		    Assert.IsNull(mph.xsender);
+		    Assert.IsNull(mph.xbuf);
+	    }
+    	
+	    [Test]
+	    public void SendDoubleSingleData2()  
+	    {
+            SetUp();
+		    // length = 2
+            FlexBuffer buf = ( FlexBuffer.littleEndian ) ? new FlexBuffer( new byte[] { 239, 190, 173, 222, 2, 0, 0, 0, 3, 4, 239, 190, 173, 222, 2, 0, 0, 0, 5, 6 } ) : 
+                new FlexBuffer( new byte[] { 222, 173, 190, 239, 0, 0, 0, 2, 3, 4, 222, 173, 190, 239, 0, 0, 0, 2, 5, 6 } );
+
+		    byte[][] result = new byte[][] { new byte[] { 3, 4 }, new byte[] { 5, 6 } } ;
+    		
+		    p.SessionData(null, buf);
+    		
+		    Assert.IsTrue(mph.Check(result));
+		    Assert.AreEqual(mph.what, What.PACKET);
+		    Assert.IsNull(mph.xbuf);
+		    Assert.IsNull(mph.xsender);
+	    }
+    	
+	    //////////////////////////////////////////////////////////////////////
+	    // these tests are for two Packets in two buffers with header split //
+	    //////////////////////////////////////////////////////////////////////
+    	
+	    [Test]
+	    public void SendDoubleSingle_HeaderSplit_Data0()  
+	    {
+            SetUp();
+		    // length = 0
+            FlexBuffer buf = ( FlexBuffer.littleEndian ) ? new FlexBuffer( new byte[] { 239, 190, 173, 222, 0, 0 } ) : 
+                new FlexBuffer( new byte[] { 222, 173, 190, 239, 0, 0 } );
+		    byte[][] result = new byte[][] { } ;
+    		
+		    p.SessionData(null, buf);
+    		
+		    Assert.IsTrue(mph.Check(result));
+		    Assert.IsNull(mph.what);
+		    Assert.IsNull(mph.xsender);
+		    Assert.IsNull(mph.xbuf);
+
+            FlexBuffer buf2 = ( FlexBuffer.littleEndian ) ? new FlexBuffer( new byte[] { 0, 0, 239, 190, 173, 222, 0, 0, 0, 0 } ) :
+                new FlexBuffer( new byte[] { 0, 0, 222, 173, 190, 239, 0, 0, 0, 0 } );
+		    byte[][] result2 = new byte[][] {};
+    		
+		    p.SessionData(null, buf2);
+    		
+		    Assert.IsTrue(mph.Check(result2));
+		    Assert.IsNull(mph.what);
+		    Assert.IsNull(mph.xsender);
+		    Assert.IsNull(mph.xbuf);
+	    }
+    	
+	    [Test]
+	    public void SendDoubleSingle_HeaderSplit_Data1()  
+	    {
+            SetUp();
+		    // length = 1
+            FlexBuffer buf = ( FlexBuffer.littleEndian ) ? new FlexBuffer( new byte[] { 239, 190, 173, 222, 1, 0 } ) : 
+                new FlexBuffer( new byte[] { 222, 173, 190, 239, 0, 0 } );
+		    byte[][] result = new byte[][] { } ;
+    		
+		    p.SessionData(null, buf);
+    		
+		    Assert.IsTrue(mph.Check(result));
+		    Assert.IsNull(mph.what);
+		    Assert.IsNull(mph.xsender);
+		    Assert.IsNull(mph.xbuf);
+
+            FlexBuffer buf2 = ( FlexBuffer.littleEndian ) ? new FlexBuffer( new byte[] { 0, 0, 1, 239, 190, 173, 222, 1, 0, 0, 0, 2 } ) : 
+                new FlexBuffer( new byte[] { 0, 1, 1, 222, 173, 190, 239, 0, 0, 0, 1, 2 } );
+		    byte[][] result2 = new byte[][] {new byte[] { 1 }, new byte[] { 2 }};
+    		
+		    p.SessionData(null, buf2);
+    		
+		    Assert.IsTrue(mph.Check(result2));
+		    Assert.AreEqual(mph.what, What.PACKET);
+		    Assert.IsNull(mph.xsender);
+		    Assert.IsNull(mph.xbuf);
+	    }
+    	
+	    [Test]
+	    public void sendDoubleSingle_HeaderSplit_Data2()  
+	    {
+            SetUp();
+		    // length = 2
+            FlexBuffer buf = ( FlexBuffer.littleEndian ) ? new FlexBuffer( new byte[] { 239, 190, 173, 222, 2, 0 } ) : 
+                new FlexBuffer( new byte[] { 222, 173, 190, 239, 0, 0 } );
+		    byte[][] result = new byte[][] { } ;
+    		
+		    p.SessionData(null, buf);
+    		
+		    Assert.IsTrue(mph.Check(result));
+		    Assert.IsNull(mph.what);
+		    Assert.IsNull(mph.xsender);
+		    Assert.IsNull(mph.xbuf);
+
+            FlexBuffer buf2 = ( FlexBuffer.littleEndian ) ? new FlexBuffer( new byte[] { 0, 0, 3, 4, 239, 190, 173, 222, 2, 0, 0, 0, 5, 6 } ) :
+                new FlexBuffer( new byte[] { 0, 2, 3, 4, 222, 173, 190, 239, 0, 0, 0, 2, 5, 6 } );
+
+		    byte[][] result2 = new byte[][] { new byte[] { 3, 4 }, new byte[] { 5, 6 } };
+    		
+		    p.SessionData(null, buf2);
+    		
+		    Assert.IsTrue(mph.Check(result2));
+		    Assert.AreEqual(mph.what, What.PACKET);
+		    Assert.IsNull(mph.xsender);
+		    Assert.IsNull(mph.xbuf);
+	    }
+    	
+	    ////////////////////////////////////////////////////////////////////
+	    // these tests are for two Packets in two buffers with body split //
+	    ////////////////////////////////////////////////////////////////////
+    	
+	    [Test]
+	    public void SendDoubleSingle_BodySplit_Data2()  
+	    {
+            SetUp();
+		    // length = 2
+            FlexBuffer buf = ( FlexBuffer.littleEndian ) ? new FlexBuffer( new byte[] { 239, 190, 173, 222, 2, 0, 0, 0, 1 } ) : 
+                new FlexBuffer( new byte[] { 222, 173, 190, 239, 0, 0, 0, 2, 1 } );
+		    
+            byte[][] result = new byte[][] { } ;
+    		
+		    p.SessionData(null, buf);
+    		
+		    Assert.IsTrue(mph.Check(result));
+		    Assert.IsNull(mph.what);
+		    Assert.IsNull(mph.xsender);
+		    Assert.IsNull(mph.xbuf);
+
+            FlexBuffer buf2 = ( FlexBuffer.littleEndian ) ? new FlexBuffer( new byte[] { 2, 239, 190, 173, 222, 2, 0, 0, 0, 3, 4 } ) :
+                new FlexBuffer( new byte[] { 2, 222, 173, 190, 239, 0, 0, 0, 2, 3, 4 } );
+
+		    byte[][] result2 = new byte[][] { new byte[] { 1, 2 }, new byte[] { 3, 4 } };
+    		
+		    p.SessionData(null, buf2);
+    		
+		    Assert.IsTrue(mph.Check(result2));
+		    Assert.AreEqual(mph.what, What.PACKET);
+		    Assert.IsNull(mph.xsender);
+		    Assert.IsNull(mph.xbuf);
+	    }
+    	
+	    [Test]
+	    public void SendDoubleSingle_BodySplit_Data3()  
+	    {
+            SetUp();
+		    // length = 3
+            FlexBuffer buf = ( FlexBuffer.littleEndian ) ? new FlexBuffer( new byte[] { 239, 190, 173, 222, 3, 0, 0, 0, 5, 6 } ) : 
+                new FlexBuffer( new byte[] { 222, 173, 190, 239, 0, 0, 0, 3, 5, 6 } );
+
+		    byte[][] result = new byte[][] { } ;
+    		
+		    p.SessionData(null, buf);
+    		
+		    Assert.IsTrue(mph.Check(result));
+		    Assert.IsNull(mph.what);
+		    Assert.IsNull(mph.xsender);
+		    Assert.IsNull(mph.xbuf);
+
+            FlexBuffer buf2 = ( FlexBuffer.littleEndian ) ? new FlexBuffer( new byte[] { 7, 239, 190, 173, 222, 3, 0, 0, 0, 8, 9, 10 } ) :
+                new FlexBuffer( new byte[] { 7, 222, 173, 190, 239, 0, 0, 0, 3, 8, 9, 10 } );
+
+		    byte[][] result2 = new byte[][] { new byte[] { 5, 6, 7 }, new byte[] { 8, 9, 10 } };
+    		
+		    p.SessionData(null, buf2);
+    		
+		    Assert.IsTrue(mph.Check(result2));
+		    Assert.AreEqual(mph.what, What.PACKET);
+		    Assert.IsNull(mph.xsender);
+		    Assert.IsNull(mph.xbuf);
+	    }
+    	
+	    [Test]
+	    public void Up()  
+	    {
+            SetUp();
+            p.SessionNotify( SessionConsts.UP );
+    		
+		    Assert.AreEqual(mph.what, What.UP);
+		    Assert.IsNull(mph.xbuf);
+		    Assert.IsNull(mph.xsender);
+	    }
+    	
+	    [Test]
+	    public void Down()   
+	    {
+            SetUp();
+            p.SessionNotify( SessionConsts.DOWN );
+    		
+		    Assert.AreEqual(mph.what, What.DOWN);
+		    Assert.IsNull(mph.xbuf);
+		    Assert.IsNull(mph.xsender);
+	    }
+    	
+	    [Test]
+	    public void LocalAddress()   
+	    {
+            SetUp();
+		    p.TransportQuery( Connection<SessionData>.LOCAL_ADDRESS );
+    		
+		    Assert.AreEqual(dh.what, What.LOCALADDRESS);
+		    Assert.IsNull(dh.xsender);
+		    Assert.IsNull(dh.xbuf);
+	    }
+    	
+	    [Test] 
+	    public void RemoteAddress()   
+	    {
+            SetUp();
+            p.TransportQuery( Connection<SessionData>.REMOTE_ADDRESS );
+    		
+		    Assert.AreEqual(dh.what, What.REMOTEADDRESS);
+		    Assert.IsNull(dh.xsender);
+		    Assert.IsNull(dh.xbuf);
+	    }
+    	
+	    [Test] 
+	    public void Stop()   
+	    {
+            SetUp();
+            p.TransportControl( TransportConsts.STOP, null );
+    		
+		    Assert.AreEqual(dh.what, What.STOP);
+		    Assert.IsNull(dh.xsender);
+		    Assert.IsNull(dh.xbuf);
+	    }
+        
+        public enum What { DATA, PACKET, UP, DOWN, RESET, LOCALADDRESS, REMOTEADDRESS, 
+            STOP, STARTED, STOPPED, EXCEPTION };
+
+
+        // This is like messagizer handling packets
+        public class MyPacketHandler : SessionPacket
+        {
+            public Enum what;
+            public Who xsender;
+            public FlexBuffer xbuf;
+            public Who xrecipient;
+            public TransportPacket _tp;
+
+            public MyPacketHandler()
+            {
+                // nothing to do.
+            }
+
+            public MyPacketHandler( TransportPacket tp )
+            {
+                _tp = tp;
+                _tp.SetSession(this);
+            }
+
+            private List<byte[]> list = new List<byte[]>();
+
+            // Auxiliary methods
+
+            public void Clear()
+            {
+                list.Clear();
+            }
+
+            public bool Check( byte[][] result )
+            {
+                bool flag = Check( list.Count == result.Length );
+                if ( flag == false )
+                    return flag;
+
+                for ( int i = 0; i < list.Count; i++ )
+                {
+                    flag = Check( list[i], result[i] );
+                    if ( flag == false )
+                        return flag;
+                }
+                return true;
+            }
+
+            private bool Check( byte[] a, byte[] b )
+            {
+                bool flag = Check( a.Length == b.Length );
+                if ( flag == false )
+                    return flag;
+
+                for ( int i = 0; i < a.Length; i++ )
+                {
+                    flag = Check( a[ i ] == b[ i ] );
+                    if ( flag == false )
+                        return flag;
+                }
+                return true;
+            }
+
+            private bool Check( bool ok )
+            {
+                return ok;
+            }
+
+            public void tp_print()
+            {
+                foreach ( byte b in list[0] )
+                Console.WriteLine(b);
+            }
+
+            // PacketHandler methods
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <param name="src"></param>
+            /// <param name="sender"></param>
+            /// <param name="buf"></param>
+            /// Exception:
+            ///      
+            public void Packet( Who sender, FlexBuffer buf )
+            {
+                what = What.PACKET;
+                xsender = sender;
+                list.Add(buf.GetAvailBytes());
+            }
+    		
+            // DataSource methods
+		
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <param name="recipient"></param>
+            /// <param name="buf"></param>
+            /// Exception:
+            ///      
+		    public void Data( Who recipient, FlexBuffer buf )
+		    {
+    			
+			    what = What.DATA;
+                this.xrecipient = recipient;
+			    list.Add( buf.GetAvailBytes() );
+		    }
+
+            
+
+            #region Session Members
+
+            public object SessionQuery( object query )
+            {
+                throw new Exception( "unsupported query " + query );
+            }
+
+            public void SessionControl( object control, object value )
+            {
+                throw new Exception( " unsupported control " + control );
+            }
+
+            public void SessionNotify( object eventObj )
+            {
+                if ( eventObj.Equals( SessionConsts.UP ) )
+                {
+                    what = What.UP;
+                    return;
+                }
+                if ( eventObj.Equals( SessionConsts.DOWN ) )
+                {
+                    what = What.DOWN;
+                    return;
+                }
+            }
+
+            #endregion
+
+           
+
+            #region SessionPacket Members
+
+            public void SessionPacket(Who sender, FlexBuffer buf)
+            {
+                what = What.PACKET;
+                xsender = sender;
+                list.Add(buf.GetAvailBytes());
+            }
+
+            #endregion
+
+           
+        }
+
+        public class MyDataHandler : TransportData
+        {
+            public Enum what;
+            public Who xsender;
+            public FlexBuffer xbuf;
+            public Who xrecipient;
+            private List<byte[]> list = new List<byte[]>();
+
+            private SessionData session;
+            public MyDataHandler()
+            {
+                
+            }
+
+            #region TransportData Members
+
+            public void TransportData(Who recipient, FlexBuffer buf)
+            {
+                what = What.DATA;
+                this.xrecipient = recipient;
+                list.Add(buf.GetAvailBytes());
+            }
+
+            #endregion
+
+            #region Transport<SessionData> Members
+
+            public object TransportQuery(object query)
+            {
+                if (query.Equals(Connection<SessionData>.LOCAL_ADDRESS))
+                {
+                    what = What.LOCALADDRESS;
+                    return null;
+                }
+                if (query.Equals(Connection<SessionData>.REMOTE_ADDRESS))
+                {
+                    what = What.REMOTEADDRESS;
+                    return null;
+                }
+                throw new Exception(" unsupported query " + query);
+            }
+
+            public void TransportControl(object control, object value)
+            {
+                if (control.Equals(TransportConsts.STOP))
+                {
+                    what = What.STOP;
+                    return;
+                }
+                throw new Exception(" unsupported control " + control);
+            }
+
+            public void TransportNotify(object eventObj)
+            {
+                
+            }
+
+            public void SetSession(SessionData session)
+            {
+                this.session = session;
+            }
+
+            public SessionData GetSession()
+            {
+                return session;
+            }
+
+            #endregion
+
+            // Auxiliary methods
+
+            public void Clear()
+            {
+                list.Clear();
+            }
+
+            public bool Check(byte[][] result)
+            {
+                bool flag = Check(list.Count == result.Length);
+                if (flag == false)
+                    return flag;
+
+                for (int i = 0; i < list.Count; i++)
+                {
+                    flag = Check(list[i], result[i]);
+                    if (flag == false)
+                        return flag;
+                }
+                return true;
+            }
+
+            private bool Check(byte[] a, byte[] b)
+            {
+                bool flag = Check(a.Length == b.Length);
+                if (flag == false)
+                    return flag;
+
+                for (int i = 0; i < a.Length; i++)
+                {
+                    flag = Check(a[i] == b[i]);
+                    if (flag == false)
+                        return flag;
+                }
+                return true;
+            }
+
+            private bool Check(bool ok)
+            {
+                return ok;
+            }
+        }
+
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Util/TestStrIntHashMapSerializer.cs b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestStrIntHashMapSerializer.cs
new file mode 100644
index 0000000..6231465
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestStrIntHashMapSerializer.cs
@@ -0,0 +1,104 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    [TestFixture]
+    public class TestStrIntHashMapSerializer
+    {
+        private readonly ValueFactory vf = new DummyValueFactory();
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestStrIntHashMapSerializer" );
+        }
+
+
+        [Test]
+        public void TestImport0() 
+	    {
+		    StrIntHashMap map = new StrIntHashMap();
+		    TestMap( map );
+	    }
+
+        [Test]
+	    public void TestImport1() 
+	    {
+		    StrIntHashMap map = new StrIntHashMap();
+		    map.Add( "a", 1 );
+		    TestMap( map );
+	    }
+
+        [Test]
+	    public void TestImport2() 
+	    {
+		    StrIntHashMap map = new StrIntHashMap();
+		    map.Add( "a", 1 );
+		    map.Add( "b", 2 );
+		    TestMap( map );
+	    }
+
+        [Test]
+	    public void TestImport3() 
+	    {
+		    StrIntHashMap map = new StrIntHashMap();
+		    map.Add( "a", 1 );
+		    map.Add( "b", 2 );
+		    map.Add( "c", 3 );
+		    TestMap( map );
+	    }
+    	
+        [Test]
+	    public void TestImportNull1() 
+	    {
+		    StrIntHashMap map = new StrIntHashMap();
+            map.Add( "a", 1 );
+		    map.Add( "b", null );
+            map.Add( "c", 2 );
+		    TestMap( map );
+	    }
+    	
+	    // no tests for null keys as string? isn't allowed
+
+        public void TestMap( StrIntHashMap map )
+        {
+            XType type = new XType( "map" );
+		  
+            Class2TypeMap class2type = new Class2TypeMap();
+		    StrIntHashMapSerializer.Init( type, class2type );
+		    ImportExportHelper helper = type.GetImportExportHelper();
+    		
+		    StructValue sv = helper.ExportValue( vf, map );
+    		
+		    Assert.AreEqual( sv.GetXType, type );
+    		
+		    StrIntHashMap map2 = (StrIntHashMap) helper.ImportValue( sv );
+    		
+		    Assert.AreEqual( map, map2 );
+        }
+
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Util/TestStrStrHashMapSerializer.cs b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestStrStrHashMapSerializer.cs
new file mode 100644
index 0000000..3d476b5
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestStrStrHashMapSerializer.cs
@@ -0,0 +1,95 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    [TestFixture]
+    public class TestStrStrHashMapSerializer
+    {
+        private readonly ValueFactory vf = new DummyValueFactory();
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestStrStrHashMapSerializer" );
+        }
+
+
+        [Test]
+        public void TestImport0()
+        {
+            StrStrHashMap map = new StrStrHashMap();
+            TestMap( map );
+        }
+
+        [Test]
+        public void TestImport1()
+        {
+            StrStrHashMap map = new StrStrHashMap();
+            map.Add( "a", "1" );
+            TestMap( map );
+        }
+
+        [Test]
+        public void TestImport2()
+        {
+            StrStrHashMap map = new StrStrHashMap();
+            map.Add( "a", "1" );
+            map.Add( "b", "2" );
+            TestMap( map );
+        }
+
+        [Test]
+        public void TestImport3()
+        {
+            StrStrHashMap map = new StrStrHashMap();
+            map.Add( "a", "1" );
+            map.Add( "b", "2" );
+            map.Add( "c", "3" );
+            TestMap( map );
+        }
+
+        // no tests for null keys as string? isn't allowed
+
+        public void TestMap( StrStrHashMap map )
+        {
+            XType type = new XType( "map" );
+		   
+            Class2TypeMap class2type = new Class2TypeMap();
+		    StrStrHashMapSerializer.Init( type, class2type );
+		    ImportExportHelper helper = type.GetImportExportHelper();
+    		
+		    StructValue sv = helper.ExportValue( vf, map );
+    		
+		    Assert.AreEqual( sv.GetXType, type );
+    		
+		    StrStrHashMap map2 = (StrStrHashMap) helper.ImportValue( sv );
+    		
+            Assert.AreEqual( map, map2 );
+        }
+
+
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Util/TestStringUtil.cs b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestStringUtil.cs
new file mode 100644
index 0000000..8b95f4d
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestStringUtil.cs
@@ -0,0 +1,161 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    
+    [TestFixture]
+    public class TestStringUtil
+    {
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestStringUtil" );
+        }
+
+
+        #region LEFT SPLIT TESTS
+
+        [Test]
+        public void TestSimpleLeftSplit()
+        {
+            String test = "Hello: World";
+            String[] s = StringUtil.LeftSplit( test, ':' );
+            Assert.AreEqual( "Hello", s[ 0 ] );
+            Assert.AreEqual( " World", s[ 1 ] );
+        }
+
+        [Test]
+        public void TestMultipleLeftSplit()
+        {
+            String test = "Hello: World: Second";
+            String[] s = StringUtil.LeftSplit( test, ':' );
+            Assert.AreEqual( "Hello", s[ 0 ] );
+            Assert.AreEqual( " World: Second", s[ 1 ] );
+        }
+
+        [Test]
+        public void TestNoDelimsLeftSplit()
+        {
+            String test = "Hello World";
+            String[] s = StringUtil.LeftSplit( test, ':' );
+            Assert.IsNull( s );
+        }
+
+        #endregion
+
+        #region RIGHT SPLIT TESTS
+
+        [Test]
+        public void TestSimpleRightSplit()
+        {
+            String test = "Hello: World";
+            String[] s = StringUtil.RightSplit( test, ':' );
+            Assert.AreEqual( "Hello", s[ 0 ] );
+            Assert.AreEqual( " World", s[ 1 ] );
+        }
+
+        [Test]
+        public void TestMultipleRightSplit()
+        {
+            String test = "Hello: World: Second";
+            String[] s = StringUtil.RightSplit( test, ':' );
+            Assert.AreEqual( "Hello: World", s[ 0 ] );
+            Assert.AreEqual( " Second", s[ 1 ] );
+        }
+
+        [Test]
+        public void TestNoDelimsRightSplit()
+        {
+            String test = "Hello World";
+            String[] s = StringUtil.RightSplit( test, ':' );
+            Assert.IsNull( s );
+        }
+
+        #endregion
+
+        #region TOHEX TESTS
+
+        [Test]
+        public void TestToHex_validArgs()
+        {
+            Assert.AreEqual( '0', StringUtil.ToHex( 0 ) );
+            Assert.AreEqual( '1', StringUtil.ToHex( 1 ) );
+            Assert.AreEqual( '2', StringUtil.ToHex( 2 ) );
+            Assert.AreEqual( '3', StringUtil.ToHex( 3 ) );
+            Assert.AreEqual( '4', StringUtil.ToHex( 4 ) );
+            Assert.AreEqual( '5', StringUtil.ToHex( 5 ) );
+            Assert.AreEqual( '6', StringUtil.ToHex( 6 ) );
+            Assert.AreEqual( '7', StringUtil.ToHex( 7 ) );
+            Assert.AreEqual( '8', StringUtil.ToHex( 8 ) );
+            Assert.AreEqual( '9', StringUtil.ToHex( 9 ) );
+            Assert.AreEqual( 'a', StringUtil.ToHex( 10 ) );
+            Assert.AreEqual( 'b', StringUtil.ToHex( 11 ) );
+            Assert.AreEqual( 'c', StringUtil.ToHex( 12 ) );
+            Assert.AreEqual( 'd', StringUtil.ToHex( 13 ) );
+            Assert.AreEqual( 'e', StringUtil.ToHex( 14 ) );
+            Assert.AreEqual( 'f', StringUtil.ToHex( 15 ) );
+        }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentException))]
+        public void TestToHex_invalidArg()
+        {
+            StringUtil.ToHex( 16 );
+        }
+
+        #endregion
+
+        #region FROMHEX TESTS
+
+        public void TestFromHex()
+        {
+            Assert.AreEqual( 0, StringUtil.FromHex( '0' ) );
+            Assert.AreEqual( 1, StringUtil.FromHex( '1' ) );
+            Assert.AreEqual( 2, StringUtil.FromHex( '2' ) );
+            Assert.AreEqual( 3, StringUtil.FromHex( '3' ) );
+            Assert.AreEqual( 4, StringUtil.FromHex( '4' ) );
+            Assert.AreEqual( 5, StringUtil.FromHex( '5' ) );
+            Assert.AreEqual( 6, StringUtil.FromHex( '6' ) );
+            Assert.AreEqual( 7, StringUtil.FromHex( '7' ) );
+            Assert.AreEqual( 8, StringUtil.FromHex( '8' ) );
+            Assert.AreEqual( 9, StringUtil.FromHex( '9' ) );
+            Assert.AreEqual( 10, StringUtil.FromHex( 'a' ) );
+            Assert.AreEqual( 11, StringUtil.FromHex( 'b' ) );
+            Assert.AreEqual( 12, StringUtil.FromHex( 'c' ) );
+            Assert.AreEqual( 13, StringUtil.FromHex( 'd' ) );
+            Assert.AreEqual( 14, StringUtil.FromHex( 'e' ) );
+            Assert.AreEqual( 15, StringUtil.FromHex( 'f' ) );
+        }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentException))]
+        public void TestFromHex_invalid()
+        {
+            StringUtil.FromHex( 'g' );
+        }
+
+        #endregion
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Util/TestTcpConnection.cs b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestTcpConnection.cs
new file mode 100644
index 0000000..6b98fc8
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestTcpConnection.cs
@@ -0,0 +1,847 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+using TcpListener=Org.Apache.Etch.Bindings.Csharp.Util.TcpListener;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Transport
+{       
+    [TestFixture]
+    public class TestTcpConnection
+    {
+        public static MyListener lh = new MyListener();
+        public static Connection<SessionListener<Socket>> l;
+        public TcpConnection c;
+        private const int TIMEOUT = 4000;
+        private static int port;
+
+        [TestFixtureSetUp]
+        public void StartListener()
+        {
+            Console.WriteLine();
+            Console.Write( "TestTCPConnection" );
+
+            l = new TcpListener( "tcp:", null );
+            l.SetSession(lh);
+            l.Start();
+            l.WaitUp( TIMEOUT );
+            port = ( ( IPEndPoint ) l.LocalAddress() ).Port;
+            //Console.WriteLine( " port = " + port );
+        }
+
+        [TestFixtureTearDown]
+        public void StopListener()
+        {
+            l.Stop();
+            l.WaitDown( TIMEOUT );
+        }
+
+        #region Constructor tests
+
+        [Test]
+        [ExpectedException(typeof(ArgumentNullException))]
+        public void Constructor1()
+        {
+            new TcpConnection( null, "tcp:", null );
+        }
+
+        [TearDown]
+        public void SleepAWhile()
+        {
+            Thread.Sleep( 1000 );
+        }
+
+        [Test]
+        public void Constructor2()
+        {
+            IPEndPoint ipe = new IPEndPoint( IPAddress.Parse( "127.0.0.1" ), port );
+            Socket s = new Socket( ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp );
+            s.Connect( ipe );
+
+            Socket t = lh.accepted.WaitUntilNotEqAndSet( null, TIMEOUT, null );
+
+            TcpConnection c = new TcpConnection( s, "tcp:",null );
+            Assert.IsNull( c.GetSession() );
+
+            s.Close();
+            t.Close();
+        }
+
+        [Test]
+        public void Constructor3()
+        {
+            IPEndPoint ipe = new IPEndPoint( IPAddress.Parse( "127.0.0.1" ), port );
+            Socket s = new Socket( ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp );
+            s.Connect( ipe );
+
+            Socket t = lh.accepted.WaitUntilNotEqAndSet( null, TIMEOUT, null );
+
+            TcpConnection c = new TcpConnection(s, "tcp:", null);
+            SessionData dh = new MyDataHandler(c);
+            Assert.AreEqual( dh, c.GetSession() );
+
+            s.Close();
+            t.Close();
+        }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentNullException))]
+        public void Constructor4()
+        {
+            new TcpConnection( null, (string) null, null );
+        }
+
+        [Test]
+        [ExpectedException(typeof(ArgumentNullException))]
+        public void Constructor5()
+        {
+            new TcpConnection( null, (string) null,null );
+        }
+
+        [Test]
+        public void Constructor8()
+        {
+            TcpConnection c = new TcpConnection( null,"tcp://localhost:"+port, null );
+            Assert.IsNull( c.GetSession() );
+        }
+
+        [Test]
+        public void Constructor9()
+        {
+
+            TcpConnection c = new TcpConnection(null, "tcp://localhost:" + port, null);
+            SessionData dh = new MyDataHandler(c);
+            Assert.AreEqual( dh, c.GetSession() );
+        }
+
+        #endregion
+
+        #region Start variations
+
+        [Test]
+        public void Start1()
+        {
+            IPEndPoint ipe = new IPEndPoint( IPAddress.Parse( "127.0.0.1" ), port );
+            Socket s = new Socket( ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp );
+            s.Connect( ipe );
+
+            Socket t = lh.accepted.WaitUntilNotEqAndSet( null, TIMEOUT, null );
+
+           
+            TcpConnection c = new TcpConnection( s,"tcp:",null );
+            MyDataHandler dh = new MyDataHandler(c);
+
+            Assert.IsFalse( c.IsStarted() );
+            c.Start();
+            Assert.IsTrue( c.IsStarted() );
+
+            c.WaitUp( TIMEOUT );
+
+            AssertWhat( What.UP, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+
+            c.Flush();
+            Assert.IsNotNull( c.RemoteAddress() );
+            Assert.IsNotNull( c.LocalAddress() );
+            Assert.AreEqual( c.RemoteAddress(), t.LocalEndPoint );
+            Assert.AreEqual( c.LocalAddress(), t.RemoteEndPoint );
+            
+            t.Close();
+
+            AssertWhat( What.DOWN, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+        }
+
+        [Test]
+        public void Start2()
+        {
+            IPEndPoint ipe = new IPEndPoint( IPAddress.Parse( "127.0.0.1" ), port );
+            Socket s = new Socket( ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp );
+            s.Connect( ipe );
+
+            Socket t = lh.accepted.WaitUntilNotEqAndSet( null, TIMEOUT, null );
+
+            
+            TcpConnection c = new TcpConnection(s, "tcp:", null );
+            MyDataHandler dh = new MyDataHandler(c);
+
+            Assert.IsFalse( c.IsStarted() );
+            c.Start();
+            Assert.IsTrue( c.IsStarted() );
+            c.WaitUp( TIMEOUT );
+
+            AssertWhat( What.UP, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+
+            Assert.IsTrue( c.IsStarted() );
+            c.Stop();
+
+            Assert.IsFalse( c.IsStarted() );
+
+            c.WaitDown( TIMEOUT );
+
+            
+            AssertWhat( What.DOWN, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+
+            t.Close();
+        }
+
+        [Test]
+        public void Start3()
+        {
+
+            IPEndPoint ipe = new IPEndPoint( IPAddress.Parse( "127.0.0.1" ), port );
+            Socket s = new Socket( ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp );
+            s.Connect( ipe );
+
+            Socket t = lh.accepted.WaitUntilNotEqAndSet( null, TIMEOUT, null );
+
+           
+            TcpConnection c = new TcpConnection( s, "tcp:", null );
+            MyDataHandler dh = new MyDataHandler(c);
+
+            Assert.IsFalse( c.IsStarted() );
+            c.Start();
+            Assert.IsTrue( c.IsStarted() );
+
+            c.WaitUp( TIMEOUT );
+
+            AssertWhat( What.UP, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+
+            Assert.IsTrue( c.IsStarted() );
+            c.Close();
+
+            c.WaitDown( TIMEOUT );
+
+            AssertWhat( What.DOWN, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+
+            t.Close();
+        }
+
+        [Test]
+        public void Start4()
+        {
+
+            IPEndPoint ipe = new IPEndPoint( IPAddress.Parse( "127.0.0.1" ), port );
+            Socket s = new Socket( ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp );
+
+            s.Connect( ipe );
+            
+            Socket t = lh.accepted.WaitUntilNotEqAndSet( null, TIMEOUT, null );
+
+          
+            TcpConnection c = new TcpConnection( s, "tcp:", null );
+            MyDataHandler dh = new MyDataHandler(c);
+
+            Assert.IsFalse( c.IsStarted() );
+            c.Start();
+            Assert.IsTrue( c.IsStarted() );
+
+            c.WaitUp( TIMEOUT );
+
+            AssertWhat( What.UP, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+
+            Assert.IsTrue( c.IsStarted() );
+            c.Close( false );
+
+            c.WaitDown( TIMEOUT );
+
+            AssertWhat( What.DOWN, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+
+            t.Close();
+        }
+
+        [Test]
+        public void Start5()
+        {
+            IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port);
+            Socket s = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+            s.Connect(ipe);
+
+            Socket t = lh.accepted.WaitUntilNotEqAndSet(null, TIMEOUT, null);
+
+            TcpConnection c = new TcpConnection(s, "tcp:", null);
+            MyDataHandler dh = new MyDataHandler(c);
+
+            Assert.IsFalse(c.IsStarted());
+            c.Start();
+            Assert.IsTrue(c.IsStarted());
+
+            c.WaitUp(TIMEOUT);
+
+            AssertWhat(What.UP, dh.what);
+            Assert.IsNull(dh.xsender);
+            Assert.IsNull(dh.xbuf);
+
+            Assert.IsTrue(c.IsStarted());
+            c.Close(true);
+
+            c.WaitDown(TIMEOUT);
+
+            AssertWhat(What.DOWN, dh.what);
+            Assert.IsNull(dh.xsender);
+            Assert.IsNull(dh.xbuf);
+
+            t.Close();
+        }
+
+        [Test]
+        public void Start6()
+        {
+
+            TcpConnection c = new TcpConnection(null, "tcp://127.0.0.1:" + port, null);
+            MyDataHandler dh = new MyDataHandler(c);
+
+            Assert.IsFalse( c.IsStarted() );
+            c.Start();
+            Assert.IsTrue( c.IsStarted() );
+            c.WaitUp( TIMEOUT );
+
+            Socket t = lh.accepted.WaitUntilNotEqAndSet( null, TIMEOUT, null );
+
+            AssertWhat( What.UP, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+
+            Assert.IsTrue( c.IsStarted() );
+            c.Stop();
+            Assert.IsFalse( c.IsStarted() );
+
+            AssertWhat( What.DOWN, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+
+            t.Close();
+        
+        }
+        
+        #endregion
+        
+        // Cause BuildServer to hang, hence ignored
+       [Ignore]
+	    [Test]
+	    public void restart1() 
+	    {
+
+
+
+            TcpConnection c = new TcpConnection(null, "tcp://127.0.0.1:" + port + "?TcpTransport.reconnectDelay=200", null);
+            MyDataHandler dh = new MyDataHandler(c);
+		
+		    c.Start();
+		    c.WaitUp( TIMEOUT );
+		
+		    int n = 10;
+		    int i = 0;
+		    while (++i <= n)
+		    {
+			    Socket t = lh.accepted.WaitUntilNotEqAndSet( null, TIMEOUT, null );
+
+			    Console.WriteLine(String.Format( "accepted i {0} t.local {1} t.remote {2}",  i,
+				     t.LocalEndPoint, t.RemoteEndPoint ));
+			
+			AssertWhat( What.UP, dh.what );
+			
+			Assert.AreEqual( t.LocalEndPoint, c.RemoteAddress() );
+			Assert.AreEqual( t.RemoteEndPoint, c.LocalAddress() );
+            byte[] data = new byte[] {Convert.ToByte(i)};
+		        
+		       t.Send(data);
+	//		t.getOutputStream().write( i );
+			AssertWhat( What.DATA, dh.what );
+			Assert.IsNull( dh.xsender );
+			Assert.IsNotNull( dh.xbuf );
+			Assert.AreEqual( 1, dh.xbuf.Length );
+			Assert.AreEqual( (byte) i, dh.xbuf[0] );
+
+		//	t.shutdownOutput();
+                t.Shutdown(SocketShutdown.Send);
+			t.Close();
+			t = null;
+			
+			AssertWhat( What.DOWN, dh.what );
+		}
+
+        Thread t1 = new Thread(new ThreadStart(RunMonitorSocketThread));
+
+        Thread t2 = new Thread(new ThreadStart(delegate()
+                                                   {
+
+                                                       try
+                                                       {
+                                                           Object t;
+                                                           Monitor<What> mon = dh.what;
+                                                           while ((t = mon.WaitUntilNotEqAndSet(default(What), TIMEOUT, default(What))) != null) { }
+                                                           //	Log.report( "harvested", "mon", mon, "t", t );
+                                                       }
+                                                       catch (Exception)
+                                                       {
+                                                           // ignore
+                                                       }    
+            
+
+
+                                                   }));
+		
+	//	Thread t1 = new MonitorHarvester<Socket>( lh.accepted );
+		t1.Start();
+	//	Thread t2 = new MonitorHarvester<What>( dh.what );
+		t2.Start();
+
+		Console.WriteLine( "stopping" );
+		c.Stop();
+		c.WaitDown( TIMEOUT );
+		Console.WriteLine( "stoppped" );
+		
+		t1.Join();
+		t2.Join();
+	}
+
+        private void RunMonitorSocketThread()
+        {
+            try
+            {
+                Object t;
+                Monitor<Socket> mon = lh.accepted;
+                while ((t = mon.WaitUntilNotEqAndSet(null, TIMEOUT, null)) != null)
+                {
+                    //	Log.report( "harvested", "mon", mon, "t", t );   
+                }
+
+            }
+            catch (Exception)
+            {
+                // ignore
+            }    
+        }
+
+       
+	/**
+	 * @param <T>
+	 */
+	    public class MonitorHarvester<T> 
+	{
+		/**
+		 * @param mon
+		 */
+		public MonitorHarvester( Monitor<T> mon )
+		{
+			this.mon = mon;
+           
+		}
+		
+		private readonly Monitor<T> mon;
+
+	
+	}
+    // Cause BuildServer to hang, hence ignored
+    [Ignore]
+	[Test]
+	public void restart2() 
+	{
+
+
+
+        TcpConnection c = new TcpConnection(null, "tcp://127.0.0.1:" + port + "?TcpTransport.reconnectDelay=200", null);
+        MyDataHandler dh = new MyDataHandler(c);
+		
+		c.Start();
+		c.WaitUp( TIMEOUT );
+		
+		int n = 10;
+		int i = 0;
+		while (++i <= n)
+		{
+//			Log.report( "--- waitAccepted" );
+			Socket t = lh.accepted.WaitUntilNotEqAndSet( null, TIMEOUT, null );
+
+            Console.WriteLine(String.Format("accepted i {0} t.local {1} t.remote {2}", i,
+                        t.LocalEndPoint, t.RemoteEndPoint));
+			
+			AssertWhat( What.UP, dh.what );
+//			Log.report( "up", "c.local", c.localAddress(), "c.remote", c.remoteAddress() );
+			
+			Assert.AreEqual( t.LocalEndPoint, c.RemoteAddress() );
+			Assert.AreEqual( t.RemoteEndPoint, c.LocalAddress() );
+
+            byte[] data = new byte[] { Convert.ToByte(i) };
+
+            t.Send(data);
+			AssertWhat( What.DATA, dh.what );
+			Assert.IsNull( dh.xsender );
+			Assert.IsNotNull( dh.xbuf );
+			Assert.AreEqual( 1, dh.xbuf.Length );
+			Assert.AreEqual( (byte) i, dh.xbuf[0] );
+
+//			Log.report( "c.shutingDownOutput" );
+			c.ShutdownOutput();
+//			Log.report( "c.shutdownOutput" );
+			
+//			Log.report( "t.reading" );
+			Assert.AreEqual( 0, t.Receive(data) );
+//			Log.report( "t.eof" );
+			
+			t.Shutdown(SocketShutdown.Send);
+			t.Close();
+			t = null;
+			
+			AssertWhat( What.DOWN, dh.what );
+//			Log.report( "down" );
+		}
+
+        Thread t1 = new Thread(new ThreadStart(RunMonitorSocketThread));
+		t1.Start();
+        Thread t2 = new Thread(new ThreadStart(delegate()
+                                                  {
+
+                                                      try
+                                                      {
+                                                          Object t;
+                                                          Monitor<What> mon = dh.what;
+                                                          while ((t = mon.WaitUntilNotEqAndSet(default(What), TIMEOUT, default(What))) != null) { }
+                                                          //	Log.report( "harvested", "mon", mon, "t", t );
+                                                      }
+                                                      catch (Exception)
+                                                      {
+                                                          // ignore
+                                                      }
+
+
+
+                                                  }));
+		t2.Start();
+		
+		Console.WriteLine( "stopping" );
+		c.Stop();
+		c.WaitDown( TIMEOUT );
+		Console.WriteLine( "stopped" );
+		
+		t1.Join();
+		t2.Join();
+	} 
+
+        #region Data tests
+
+        [Test]
+        public void Data1()
+        {
+
+            TcpConnection c = new TcpConnection(null, "tcp://127.0.0.1:" + port, null);
+            MyDataHandler dh = new MyDataHandler(c);
+
+            Assert.IsFalse( c.IsStarted() );
+            c.Start();
+            Assert.IsTrue( c.IsStarted() );
+
+            c.WaitUp( TIMEOUT );
+
+            Socket t = lh.accepted.WaitUntilNotEqAndSet( null, TIMEOUT, null );
+
+            AssertWhat( What.UP, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+        
+            byte[] buf = new byte[] { 23 };
+            t.Send( buf );
+
+            AssertWhat( What.DATA, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNotNull( dh.xbuf );
+            Assert.AreEqual( 1, dh.xbuf.Length );
+            Assert.AreEqual( ( byte ) 23, dh.xbuf[ 0 ] );
+
+            Assert.IsTrue( c.IsStarted() );
+            c.Stop();
+            Assert.IsFalse( c.IsStarted() );
+
+            AssertWhat( What.DOWN, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+
+            t.Close();
+
+        }
+
+        [Test]
+        public void Data2()
+        {
+
+            TcpConnection c = new TcpConnection(null, "tcp://127.0.0.1:" + port, null);
+            MyDataHandler dh = new MyDataHandler(c);
+
+            Assert.IsFalse( c.IsStarted() );
+            c.Start();
+            Assert.IsTrue( c.IsStarted() );
+
+            c.WaitUp( TIMEOUT );
+
+            Socket t = lh.accepted.WaitUntilNotEqAndSet( null,TIMEOUT, null );
+
+            AssertWhat( What.UP, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+
+            byte[] buf = { 21, 22, 23 };
+
+            t.Send( buf );
+            // t.getOutputStream().flush();
+
+            AssertWhat( What.DATA, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNotNull( dh.xbuf );
+            Assert.AreEqual( 3, dh.xbuf.Length );
+            Assert.AreEqual( ( byte ) 21, dh.xbuf[ 0 ] );
+            Assert.AreEqual( ( byte ) 22, dh.xbuf[ 1 ] );
+            Assert.AreEqual( ( byte ) 23, dh.xbuf[ 2 ] );
+
+            Assert.IsTrue( c.IsStarted() );
+            c.Stop();
+            Assert.IsFalse( c.IsStarted() );
+
+            AssertWhat( What.DOWN, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+
+            t.Close();
+        }
+
+        [Test]
+        public void Data3()
+        {
+
+            TcpConnection c = new TcpConnection(null, "tcp://127.0.0.1:" + port, null);
+            MyDataHandler dh = new MyDataHandler(c);
+
+            Assert.IsFalse( c.IsStarted() );
+            c.Start();
+            Assert.IsTrue( c.IsStarted() );
+
+            c.WaitUp( TIMEOUT );
+
+            Socket t = lh.accepted.WaitUntilNotEqAndSet( null, TIMEOUT, null );
+
+            AssertWhat( What.UP, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+
+            t.Shutdown( SocketShutdown.Send );
+
+            AssertWhat( What.DOWN, dh.what );
+            Assert.IsNull( dh.xsender );
+            Assert.IsNull( dh.xbuf );
+
+            t.Close();
+            c.Close();
+        }
+
+        [Test]
+        public void Data4()
+        {
+
+            TcpConnection c = new TcpConnection(null, "tcp://127.0.0.1:" + port, null);
+            MyDataHandler dh = new MyDataHandler(c);
+
+		    c.Start();
+
+            c.WaitUp( TIMEOUT );
+
+		    Socket t = lh.accepted.WaitUntilNotEqAndSet( null,TIMEOUT, null );
+    		
+		    AssertWhat( What.UP, dh.what );
+		    Assert.IsNull( dh.xsender );
+		    Assert.IsNull( dh.xbuf );
+    		
+            byte[] sendBuf = new byte[] { 21, 22, 23 };
+
+	//	    c.Data( null, new FlexBuffer( sendBuf ) );
+            c.TransportData(null, new FlexBuffer(sendBuf));
+		    // c.flush();
+    		
+            byte[] receiveBuf = new byte[ 3 ];
+            t.Receive( receiveBuf );
+
+            Assert.AreEqual( sendBuf, receiveBuf );
+
+            c.ShutdownOutput();
+        		
+		    // Assert.AreEqual( -1, is.read() );
+    		
+		    c.Close();
+    		
+		    AssertWhat( What.DOWN, dh.what );
+		    Assert.IsNull( dh.xsender );
+		    Assert.IsNull( dh.xbuf );
+    		
+		    t.Close();
+        }
+
+        #endregion
+
+
+        private void AssertWhat( What what, Monitor<What> mon )
+        {
+            mon.WaitUntilEqAndSet( what, TIMEOUT, default( What) );
+        }
+
+        public enum What { 
+            // connection is up
+            UP, 
+            // connection is down
+            DOWN, 
+            // connection read some data
+            DATA 
+        };
+
+        #region Filler classes
+
+        public class MyListener : SessionListener<Socket>
+        {
+            public Monitor<Socket> accepted = new Monitor<Socket>( "accepted" );
+
+            public void Accepted( Socket s )
+            {
+              //  accepted.Set( s );
+                accepted.WaitUntilEqAndSet(null, TIMEOUT, s);
+            }
+
+           
+            #endregion
+
+            #region Session Members
+
+            public object SessionQuery( object query )
+            {
+                // ignore
+               throw new NotSupportedException("unknown query: " + query);
+            }
+
+            public void SessionControl( object control, object value )
+            {
+                // ignore
+                throw new NotSupportedException("unknown control:  " + control);
+            }
+
+            public void SessionNotify( object eventObj )
+            {
+                // ignore
+                if (eventObj is Exception)
+                    Console.WriteLine("MyListener.SessionNotify: " + eventObj);
+            }
+
+            #endregion
+
+            #region SessionListener Members
+
+            public void SessionAccepted(Socket socket)
+            {
+                  accepted.WaitUntilEqAndSet(null, TIMEOUT, socket);
+            }
+
+            #endregion
+        }
+
+        public class MyDataHandler : SessionData
+        {
+            // holds event type
+            public Monitor<What> what = new Monitor<What>( "what" );
+
+		    // sender of the event if DATA 
+		    public Who xsender;
+
+		    // data of the event if DATA 
+		    public byte[] xbuf;
+    		
+            //public void Data( Who sender, FlexBuffer buf ) 
+            //{
+            //    xsender = sender;
+            //    xbuf = buf.GetAvailBytes();
+           
+            //    what.WaitUntilEqAndSet(default(What), TIMEOUT, What.DATA);
+            //}
+            public MyDataHandler(TcpConnection conn)
+            {
+                conn.SetSession(this);
+            }
+           
+
+            #region Session Members
+
+            public object SessionQuery( object query )
+            {
+                throw new NotSupportedException( " Unsupported query " + query );
+            }
+
+            public void SessionControl( object control, object value )
+            {
+                throw new NotSupportedException( " Unsupported control " + control );
+            }
+
+            public void SessionNotify( object eventObj )
+            {
+                if ( eventObj.Equals( SessionConsts.UP ) )
+                {
+                    xbuf = null;
+                //    what.Set( What.UP );
+                    what.WaitUntilEqAndSet(default(What), TIMEOUT, What.UP);
+                    return;
+                }
+
+                if ( eventObj.Equals( SessionConsts.DOWN ) )
+                {
+                    xbuf = null;
+                    what.WaitUntilEqAndSet(default(What), TIMEOUT, What.DOWN);
+                    return;
+                }
+            }
+
+            #endregion
+
+            #region SessionData Members
+
+            public void SessionData(Who sender, FlexBuffer buf)
+            {
+                xsender = sender;
+                xbuf = buf.GetAvailBytes();
+
+                what.WaitUntilEqAndSet(default(What), TIMEOUT, What.DATA);
+            }
+
+            #endregion
+        }
+       
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Util/TestURL.cs b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestURL.cs
new file mode 100644
index 0000000..7464adb
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestURL.cs
@@ -0,0 +1,351 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using NUnit.Framework;
+
+// s is scheme:[//[user[:password]@]host[:port]/]uri[;params][?terms][#fragment]
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    [TestFixture]
+    public class TestURL
+    {
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestURL" );
+        }
+
+        [ExpectedException( typeof( ArgumentNullException ) )]
+        public void TestNullURL()
+        {
+            string testUrl = "";
+            URL url1 = new URL( testUrl );
+
+        }
+        
+        /// <summary>
+        /// Parse a simple URL
+        /// </summary>
+        [Test]
+        public void TestParse1()
+        {
+            string testUrl = "tcp://user:password@127.0.0.1:4001";
+            URL url1 = new URL( testUrl );
+            Assert.AreEqual( "tcp", url1.Scheme );
+            Assert.AreEqual( "user", url1.User );
+            Assert.AreEqual( "password", url1.Password );
+            Assert.AreEqual( "127.0.0.1", url1.Host );
+            Assert.AreEqual( 4001, url1.Port );
+
+            //scheme tests
+            
+            Assert.IsFalse( url1.HasTerms() );
+            Assert.IsFalse( url1.HasParams() );
+
+            Assert.AreEqual( "tcp://user:password@127.0.0.1:4001/", url1.ToString() );
+        }
+
+        [Test]
+        public void TestSchemeFunctions()
+        {
+            string testUrl = "tcp://user:password@127.0.0.1:4001";
+            URL url1 = new URL( testUrl );
+
+            Assert.AreEqual( "tcp", url1.Scheme );
+            Assert.IsTrue( url1.IsScheme( "tcp" ) );
+            Assert.IsFalse( url1.IsScheme( "" ) );
+            Assert.IsFalse( url1.IsScheme( "tcp-" ) );
+
+            url1.Scheme = "udp";
+            Assert.AreEqual( "udp", url1.Scheme );
+            Assert.IsTrue( url1.IsScheme( "udp" ) );
+
+            Assert.AreEqual( "udp://user:password@127.0.0.1:4001/", url1.ToString() );
+        }
+
+        [Test]
+        public void TestUser()
+        {
+            string testUrl = "tcp://user:password@127.0.0.1:4001";
+            URL url1 = new URL( testUrl );
+
+            Assert.AreEqual( "user", url1.User );
+            
+            url1.User = "user2";
+            Assert.AreEqual( "user2", url1.User );
+
+            try
+            {
+                url1.User = "";
+                Assert.Fail();
+            }
+            catch ( Exception )
+            {
+                Assert.IsTrue( true );
+            }
+
+            Assert.AreEqual( "tcp://user2:password@127.0.0.1:4001/", url1.ToString() );
+        }
+
+        [Test]
+        public void TestPassword()
+        {
+            string testUrl = "tcp://user:password@127.0.0.1:4001";
+            URL url1 = new URL( testUrl );
+
+            Assert.AreEqual( "password", url1.Password );
+
+            url1.Password = "password2";
+            Assert.AreEqual( "password2", url1.Password );
+
+            Assert.AreEqual( "tcp://user:password2@127.0.0.1:4001/", url1.ToString() );
+        }
+
+        [Test]
+        public void TestHost()
+        {
+            string testUrl = "tcp://user:password@127.0.0.1:4001";
+            URL url1 = new URL( testUrl );
+
+            Assert.AreEqual( "127.0.0.1", url1.Host );
+
+            url1.Host = "localhost";
+            Assert.AreEqual( "localhost", url1.Host );
+
+            Assert.AreEqual( "tcp://user:password@localhost:4001/", url1.ToString() );
+        }
+
+        [Test]
+        public void TestPort()
+        {
+            string testUrl = "tcp://user:password@127.0.0.1:4001";
+            URL url1 = new URL( testUrl );
+
+            Assert.AreEqual( 4001, url1.Port );
+
+            url1.Port = 8000;
+            Assert.AreEqual( 8000, url1.Port );
+
+            try
+            {
+                url1.Port = -1;
+                Assert.Fail();
+            }
+            catch ( ArgumentException )
+            {
+                Assert.IsTrue( true );
+                try
+                {
+                    url1.Port = 65536;
+                    Assert.Fail();
+                }
+                catch ( ArgumentException )
+                {
+                    Assert.IsTrue( true );
+                }
+            }
+
+            Assert.AreEqual( "tcp://user:password@127.0.0.1:8000/", url1.ToString() );
+        }
+
+        [Test]
+        public void TestUri()
+        {
+            string testUrl = "tcp://user:password@127.0.0.1:4001/myUri";
+            URL url1 = new URL( testUrl );
+
+            Assert.AreEqual( "myUri", url1.Uri );
+
+            url1.Uri = "";
+            Assert.AreEqual( "", url1.Uri );
+
+            Assert.AreEqual( "tcp://user:password@127.0.0.1:4001/", url1.ToString() );
+        }
+
+        [Test]
+        public void TestParams()
+        {
+            string testUrl = "tcp://user:password@127.0.0.1:4001/myUri";
+            URL url = new URL( testUrl );
+            Assert.IsFalse( url.HasParams() );
+            Assert.AreEqual(0, url.GetParams().Length);
+            Assert.IsNull(url.GetParam("PARAM1="));
+
+            testUrl = "tcp://user:password@127.0.0.1:4001/cuae;PARAM1=1;PARAM2=2";
+            url = new URL( testUrl );
+            Assert.IsTrue( url.HasParams() );
+            Assert.AreEqual( "PARAM1=1", url.GetParam( "PARAM1" ) );
+            Assert.AreEqual( "PARAM2=2", url.GetParam( "PARAM2" ) );
+            
+            // get iterator over params
+            string[] p = url.GetParams();
+            Assert.AreEqual(2, p.Length);
+            Assert.IsTrue(Find("PARAM1=1", p));
+            Assert.IsTrue(Find("PARAM2=2", p));
+
+            // add a new param
+            url.AddParam( "0123456789" );
+            Assert.AreEqual( "0123456789", url.GetParam( "0123" ) );
+            p = url.GetParams();
+            Assert.AreEqual(3, p.Length);
+            Assert.IsTrue(Find("PARAM1=1", p));
+            Assert.IsTrue(Find("PARAM2=2", p));
+            Assert.IsTrue(Find("0123456789", p));
+
+            // remove a param
+            Assert.AreEqual( "PARAM1=1", url.RemoveParam( "PARAM1" ) );
+            Assert.IsNull(url.GetParam("PARAM1="));
+            p = url.GetParams();
+            Assert.AreEqual(2, p.Length);
+            Assert.IsTrue(Find("PARAM2=2", p));
+            Assert.IsTrue(Find("0123456789", p));
+
+            // clear all params
+            url.ClearParams();
+            Assert.IsFalse( url.HasParams() );
+        }
+
+        private bool Find(string s, string[] a)
+        {
+            foreach (string x in a)
+                if (x.Equals(s))
+                    return true;
+            return false;
+        }
+
+        [Test]
+        public void TestQueryTerms()
+        {
+            String testUrl = "tcp://user:password@127.0.0.1:4001/cuae";
+            URL url = new URL( testUrl );
+            Assert.IsFalse( url.HasTerms() );
+
+            testUrl = "tcp://user:password@127.0.0.1:4001/cuae?term1=500";
+            url = new URL( testUrl );
+
+            Assert.IsTrue( url.HasTerms() );
+            Assert.IsTrue( url.HasTerm( "term1" ) );
+            Assert.IsTrue( url.HasTerm( "term1", "500" ) );
+            Assert.IsTrue(url.HasTerm("term1", 500));
+            Assert.IsFalse(url.HasTerm("term1", "1000"));
+            Assert.IsFalse(url.HasTerm("term1", 1000));
+            Assert.IsFalse(url.HasMultipleValues("term1"));
+            Assert.AreEqual("500", url.GetTerm("term1"));
+            Assert.AreEqual(500, url.GetIntegerTerm("term1"));
+            Assert.AreEqual("500", url.GetTerm("term1", "x"));
+            Assert.AreEqual(500, url.GetIntegerTerm("term1", 2));
+
+            Assert.IsFalse(url.HasTerm("term2"));
+            Assert.IsFalse(url.HasTerm("term2", "500"));
+            Assert.IsFalse(url.HasTerm("term2", 500));
+            Assert.IsNull(url.GetTerm("term2"));
+            Assert.IsNull(url.GetIntegerTerm("term2"));
+            Assert.AreEqual("x", url.GetTerm("term2", "x"));
+            Assert.AreEqual(2, url.GetIntegerTerm("term2", 2));
+
+            // multiple values of the same term
+            url.AddTerm( "term1", 500.5 );
+            Assert.IsTrue(url.HasMultipleValues("term1"));
+            Assert.IsTrue(url.HasTerm("term1"));
+            Assert.IsTrue(url.HasTerm("term1", "500"));
+            Assert.IsTrue(url.HasTerm("term1", 500));
+            Assert.IsTrue(url.HasTerm("term1", "500.5"));
+            Assert.IsTrue(url.HasTerm("term1", 500.5));
+            try
+            {
+                url.GetTerm( "term1" );
+                Assert.Fail( "Exception wasn't thrown..." );
+            }
+            catch ( Exception )
+            {
+                // ignore exception
+            }
+            string[] t = url.GetTerms( "term1" );
+            Assert.AreEqual(2, t.Length);
+            Assert.AreEqual( "500", t[0] );
+            Assert.AreEqual( "500.5", t[1] );
+
+            // add another term => multiple terms
+            url.AddTerm( "term2", "value" );
+            Assert.IsFalse( url.HasMultipleValues( "term2" ) );
+            Assert.IsTrue( url.HasTerm( "term2" ) );
+            Assert.IsTrue( url.HasTerm( "term2", "value" ) );
+            Assert.AreEqual( "value", url.GetTerm( "term2" ) );
+
+            t = url.GetTermNames();
+            Assert.AreEqual(2, t.Length);
+            Assert.AreEqual( "term1", t[0] );
+            Assert.AreEqual( "term2", t[1] );
+
+            // Console.WriteLine( url.ToString() );
+            // remove term
+            Assert.IsFalse( url.RemoveTerm( "term3" ) );
+            Assert.IsTrue( url.RemoveTerm( "term2" ) );
+            Assert.IsFalse( url.HasTerm( "term2" ) );
+            t = url.GetTermNames();
+            Assert.AreEqual(1, t.Length);
+            Assert.AreEqual("term1", t[0]);
+
+            // remove one value from a list of values for a term
+            Assert.IsTrue( url.RemoveTerm( "term1", "500.5" ) );
+            Assert.IsFalse( url.HasMultipleValues( "term1" ) );
+            Assert.AreEqual( "500", url.GetTerm( "term1" ) );
+
+            // clear terms
+            url.ClearTerms();
+            Assert.IsFalse( url.HasTerms() );
+            Assert.AreEqual(0, url.GetTermNames().Length);
+            Assert.AreEqual( "tcp://user:password@127.0.0.1:4001/cuae", url.ToString() );
+        }
+
+        [Test]
+        public void TestFragment()
+        {
+            string testUrl = "tcp://user:password@127.0.0.1:4001/cuae;p1;p2?t1=1?t2=2";
+            URL url = new URL( testUrl );
+            Assert.IsNull( url.Fragment );
+
+            url.Fragment = "fragments";
+            Assert.AreEqual( "fragments", url.Fragment );
+            
+        }
+
+        public void TestConstructor()
+        {
+            string testUrl2 = "tcp://user:password@127.0.0.1:4001/cuae;p1;p2?t1=1?t2=2#fragment";
+            URL url2 = new URL( testUrl2 );
+            URL url3 = new URL( url2 );
+
+            Assert.AreEqual( url2.Scheme, url3.Scheme );
+            Assert.AreEqual( url2.User, url3.User );
+            Assert.AreEqual( url2.Password, url3.Password );
+            Assert.AreEqual( url2.Host, url3.Host);
+            Assert.AreEqual( url2.Port, url3.Port );
+            Assert.AreEqual( url2.Uri, url3.Uri );
+            //Assert.AreEqual( url2.GetParams(), url3.GetParams() );
+            //Assert.AreEqual( url2., url3.GetTerms() );
+            Assert.AreEqual( url2.Fragment, url3.Fragment );
+
+        }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/Etch/Util/TestUrlSerializer.cs b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestUrlSerializer.cs
new file mode 100644
index 0000000..ea136e1
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Etch/Util/TestUrlSerializer.cs
@@ -0,0 +1,64 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using NUnit.Framework;
+
+namespace Org.Apache.Etch.Bindings.Csharp.Util
+{
+    [TestFixture]
+    public class TestUrlSerializer
+    {
+        private readonly ValueFactory vf = new DummyValueFactory();
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestUrlSerializer" );
+        }
+
+
+        [Test]
+	    public void TestImport()
+	    {
+		    URL url = new URL( "scheme://user:pw@host:23/resource;s=1;t=2?p=3&q=4#frag" );
+		    Test( url );
+	    }
+    	
+	    private void Test( URL url )
+	    {
+    		
+		    XType type = new XType( "url" );
+            Class2TypeMap class2type = new Class2TypeMap();
+		    URLSerializer.Init( type, class2type );
+		    ImportExportHelper helper = type.GetImportExportHelper();
+    		
+		    StructValue sv = helper.ExportValue( vf, url );
+    		
+		    Assert.AreEqual( sv.GetXType, type );
+    		
+		    URL url2 = (URL) helper.ImportValue( sv );
+    		
+		    Assert.AreEqual( url.ToString(), url2.ToString() );
+	    }
+    }
+}
diff --git a/binding-csharp/runtime/src/test/csharp/EtchTestProj.csproj b/binding-csharp/runtime/src/test/csharp/EtchTestProj.csproj
new file mode 100644
index 0000000..3cb1390
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/EtchTestProj.csproj
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{3D44C33C-0E5F-443B-A0B4-ABDF16B64AC5}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Etch</RootNamespace>
+    <AssemblyName>EtchTest</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="nunit.framework, Version=2.4.7.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>$(NUNIT_HOME)\bin\nunit.framework.dll</HintPath>
+      <SpecificVersion>False</SpecificVersion>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Etch\Msg\TestComboValidator.cs" />
+    <Compile Include="Etch\Msg\TestField.cs" />
+    <Compile Include="Etch\Msg\TestFieldMap.cs" />
+    <Compile Include="Etch\Msg\TestIdName.cs" />
+    <Compile Include="Etch\Msg\TestIdNameMap.cs" />
+    <Compile Include="Etch\Msg\TestMessage.cs" />
+    <Compile Include="Etch\Msg\TestStructValue.cs" />
+    <Compile Include="Etch\Msg\TestTypeMap.cs" />
+    <Compile Include="Etch\Msg\TestXType.cs" />
+    <Compile Include="Etch\Support\TestDefaultValueFactory.cs" />
+    <Compile Include="Etch\Support\TestFreePool.cs" />
+    <Compile Include="Etch\Support\TestRemoteBase.cs" />
+    <Compile Include="Etch\Support\TestStubBase.cs" />
+    <Compile Include="Etch\Support\TestTodoManager.cs" />
+    <Compile Include="Etch\Support\TestTypeValidator.cs" />
+    <Compile Include="Etch\Support\TestValidators.cs" />
+    <Compile Include="Etch\Support\TestValidator_boolean.cs" />
+    <Compile Include="Etch\Support\TestValidator_byte.cs" />
+    <Compile Include="Etch\Support\TestValidator_double.cs" />
+    <Compile Include="Etch\Support\TestValidator_float.cs" />
+    <Compile Include="Etch\Support\TestValidator_int.cs" />
+    <Compile Include="Etch\Support\TestValidator_long.cs" />
+    <Compile Include="Etch\Support\TestValidator_object.cs" />
+    <Compile Include="Etch\Support\TestValidator_short.cs" />
+    <Compile Include="Etch\Support\TestValidator_string.cs" />
+    <Compile Include="Etch\Support\TestValidator_StructValue.cs" />
+    <Compile Include="Etch\Support\TestValidator_void.cs" />
+    <Compile Include="Etch\Transport\Filter\TestKeepAlive.cs" />
+    <Compile Include="Etch\Transport\Filter\TestLogger.cs" />
+    <Compile Include="Etch\Transport\Filter\TestPwAuth.cs" />
+    <Compile Include="Etch\Transport\Fmt\Binary\TestBinaryTaggedDataInOut.cs" />
+    <Compile Include="Etch\Transport\TestArrayValue.cs" />
+    <Compile Include="Etch\Transport\TestDefaultDeliveryService.cs" />
+    <Compile Include="Etch\Transport\TestMessagizer.cs" />
+    <Compile Include="Etch\Transport\TestPlainMailbox.cs" />
+    <Compile Include="Etch\Transport\TestPlainMailboxManager.cs" />
+    <Compile Include="Etch\Util\TestAlarmManager.cs" />
+    <Compile Include="Etch\Util\TestCharIterator.cs" />
+    <Compile Include="Etch\Util\TestCircularQueue.cs" />
+    <Compile Include="Etch\Util\TestDateSerializer.cs" />
+    <Compile Include="Etch\Util\TestFlexBuffer.cs" />
+    <Compile Include="Etch\Util\TestHelp.cs" />
+    <Compile Include="Etch\Util\TestHPTimer.cs" />
+    <Compile Include="Etch\Util\TestMonitor.cs" />
+    <Compile Include="Etch\Util\TestPacketizer.cs" />
+    <Compile Include="Etch\Util\TestStringUtil.cs" />
+    <Compile Include="Etch\Util\TestStrIntHashMapSerializer.cs" />
+    <Compile Include="Etch\Util\TestStrStrHashMapSerializer.cs" />
+    <Compile Include="Etch\Util\TestTcpConnection.cs" />
+    <Compile Include="Etch\Util\TestURL.cs" />
+    <Compile Include="Etch\Util\TestUrlSerializer.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/binding-csharp/runtime/src/test/csharp/Properties/AssemblyInfo.cs b/binding-csharp/runtime/src/test/csharp/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..87ee0fd
--- /dev/null
+++ b/binding-csharp/runtime/src/test/csharp/Properties/AssemblyInfo.cs
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("EtchTest")]
+[assembly: AssemblyDescription("Etch C# Unit Tests DLL")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Cisco Systems")]
+[assembly: AssemblyProduct("Etch")]
+[assembly: AssemblyCopyright("Copyright © Cisco Systems 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("44712a15-22c2-4a72-9c1a-e9b88bbd1219")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.0.0.1")]
+[assembly: AssemblyFileVersion("0.0.0.1")]
diff --git a/binding-java/build.xml b/binding-java/build.xml
new file mode 100644
index 0000000..ec67f5b
--- /dev/null
+++ b/binding-java/build.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-java-binding" basedir="." default="help">
+    <description>Etch-to-Java Binding</description>
+    <property name="Etch.basedir" location="${basedir}/.." />
+    <import file="${Etch.basedir}/build-support/etch.common.xml" />
+
+    <!-- standard, supported targets -->
+    <target name="Debug"         depends="debug" />
+    <target name="Release"       depends="release" />
+    <target name="Clean"         depends="clean" />
+    <target name="debug"         depends="init-debug,component-all,post-debug"   />
+    <target name="release"       depends="init-release,component-all,post-release" />
+    <target name="clean"         depends="init-clean,component-all,post-clean" />
+    <target name="maven-install" depends="init-maven,release" />
+
+    <target name="init-maven" >
+        <property name="DO.maven.install" value="true" />
+    </target>
+
+    <target name="validate-dependencies" >
+        <mkdir dir="${Etch.logDirectory}" />
+    </target>
+
+    <target name="init-debug" depends="validate-dependencies" >
+        <property name="Etch.build.target" value="Debug" />
+        <property name="Etch.javac.debug" value="on" />
+        <property name="Etch.javac.optimize" value="off" />
+    </target>
+
+    <target name="post-debug" >
+    </target>
+
+    <target name="init-release" depends="validate-dependencies">
+        <!-- For now, keep debug-symbols and no-optimize, even for release builds -->
+        <property name="Etch.build.target" value="Release" />
+        <property name="Etch.javac.debug"  value="on" />
+        <property name="Etch.javac.optimize" value="off" />
+        <!--
+        <property name="Etch.javac.debug"  value="off" />
+        <property name="Etch.javac.optimize" value="on" />
+        -->
+    </target>
+    
+    <target name="post-release" >
+    </target>
+
+    <target name="init-clean" depends="validate-dependencies">
+        <property name="Etch.build.target" value="Clean" />
+    </target>
+
+    <target name="post-clean" >
+        <echo message="Executing clean" />
+    </target>
+
+    <target name="component-all" >
+        <build_component dir="compiler" />
+        <build_component dir="runtime" />
+    </target>
+
+</project>
diff --git a/binding-java/compiler/build.xml b/binding-java/compiler/build.xml
new file mode 100644
index 0000000..fe91898
--- /dev/null
+++ b/binding-java/compiler/build.xml
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-java-compiler" basedir="." default="help">
+    <description>Etch-to-Java compiler implementation</description>
+    <property name="Etch.basedir" location="${basedir}/../.." />
+    <import file="${Etch.basedir}/build-support/etch.includes.xml" />
+
+    <!-- Static properties of the sub-project -->
+    <property name="proj"                 location="${Etch.basedir}/binding-java/compiler" />
+    <property name="target"               location="${proj}/target" />
+    <property name="src"                  location="${proj}/src" />        
+    <property name="generatedSrc"         location="${target}/generated-sources" />
+    <property name="classesDirectory"     location="${target}/classes" />
+    <property name="resourcesDirectory"   location="${target}/resources" />
+    <property name="testResultsDirectory" location="${target}/test-results" />
+
+    <!-- MACRO: init-target -->
+    <macrodef name="init-target" >
+        <sequential>
+            <delete dir="${classesDirectory}"   failonerror="false" quiet="true" />
+            <delete dir="${resourcesDirectory}" failonerror="false" quiet="true" />
+            <mkdir dir="${classesDirectory}" />
+            <mkdir dir="${classesDirectory}/main" />
+            <mkdir dir="${classesDirectory}/test" />
+            <mkdir dir="${resourcesDirectory}" />
+        </sequential>
+    </macrodef>
+
+    <!-- MACRO: compile-sources -->
+    <macrodef name="compile-sources" >
+        <sequential>            
+            <!-- compile compiler plugin -->
+            <javac  debug="${Etch.javac.debug}"
+                    target="1.5"
+                    optimize="${Etch.javac.optimize}"
+                    destdir="${classesDirectory}/main" >
+                <src path="${src}/main/java" />
+                <exclude name="**/.svn/**" />
+                <classpath refid="Etch.dependencies.jar.paths" />
+                <classpath>
+                    <pathelement location="${Etch.HOME}/lib/${etch-compiler.jar}" />
+                </classpath>
+            </javac>
+
+            <!-- compiler plugin resources -->
+            <copy todir="${classesDirectory}/main" >
+                <fileset dir="${src}/main/resources">
+                    <include name="**/*.kwd" />
+                    <include name="**/*.vm" />
+                </fileset>
+            </copy>
+
+            <!--
+            <javac  debug="${Etch.javac.debug}"
+                    target="1.5"
+                    optimize="${Etch.javac.optimize}"
+                    destdir="${classesDirectory}/test" >
+                <src path="${src}/test/java" />
+                <exclude name="**/.svn/**" />
+                <classpath refid="Etch.dependencies.jar.paths" />
+                <classpath>
+                    <pathelement location="${classesDirectory}/main" />
+                    <pathelement location="${Etch.HOME}/lib/${etch-compiler.jar}" />
+                </classpath>
+            </javac>
+            -->
+
+        </sequential>
+    </macrodef>
+    
+    <!-- MACRO: bundle-jars -->
+    <macrodef name="bundle-jars" >
+        <attribute name="dist" default="${Etch.dist}" />
+        <sequential>
+            <mkdir dir="@{dist}/lib" />
+            
+            <!-- CREATE jars -->
+
+            <!-- Package up etch-java-compiler jar -->
+            <jar jarfile="@{dist}/lib/${etch-java-compiler.jar}" >
+                <manifest>
+                    <attribute name="Copyright"    value="${Etch.copyrightNotice}" />
+                    <attribute name="Version"      value="${Etch.version}" />
+                    <attribute name="LongVersion"  value="${Etch.longversion}" />
+                    <attribute name="Build-Tag"    value="${Etch.buildTag}" />
+                    <attribute name="SVN-Revision" value="${Etch.runtime.revisionNumber}" />
+                </manifest>
+                <metainf dir="${Etch.basedir}" >
+                    <include name="NOTICE.txt" />
+                    <include name="LICENSE.txt" />
+                </metainf>
+                <fileset dir="${classesDirectory}/main">
+                    <include name="org/apache/etch/bindings/**" />
+                    <!-- <include name="resources/**" /> -->
+                </fileset>
+            </jar>
+
+            <!-- CREATE source archives -->
+            
+            <!-- package up etch-java-compiler src -->
+            <zip destfile="@{dist}/lib/${etch-java-compiler-src.zip}" >
+                <fileset dir="${src}/main/java" >
+                    <include name="org/apache/etch/bindings/**/*.java" />
+                </fileset>
+                <fileset dir="${src}/main/resources" >
+                    <include name="**/*" />
+                </fileset>
+            </zip>
+
+        </sequential>
+    </macrodef>
+    
+    <!-- INIT TARGET -->
+    <!-- Modify this target to define project specific properties that can only be set at runtime -->
+    <target name="do-init">
+        <delete dir="${target}" failonerror="false" quiet="true" />
+
+        <mkdir dir="${target}" />
+        <mkdir dir="${generatedSrc}" />
+        <mkdir dir="${classesDirectory}" />
+        <mkdir dir="${resourcesDirectory}" />
+        <mkdir dir="${testResultsDirectory}" />
+    </target>
+
+    <!-- CLEAN TARGET -->
+    <target name="do-clean">
+        <delete dir="${target}" />
+    </target>
+
+    <!-- BUILD TARGET -->
+    
+    <target name="generate-sources" >
+        <!-- Generate version info -->
+        <update-tokens filename="${src}/main/java/org/apache/etch/bindings/java/compiler/CompilerVersion.java" />  
+    </target>
+
+    <target name="compile-for-dist" >
+        <!-- Initialize target directories -->
+        <init-target />
+
+        <!-- Compile Source -->
+        <compile-sources />
+
+        <!-- Bundle Jars -->
+        <bundle-jars dist="${Etch.dist}" />
+    </target>
+    
+    <target name="compile-for-clover" if="Clover.enabled" >
+
+        <echo message="Rebuilding with clover" />
+
+        <!-- initialize-clover -->
+        <initialize-clover suffix="etchjavacompiler" >
+            <fileset dir="${src}/main/java">
+                <include name="**/*.java" />
+            </fileset>
+            <!--
+            <testsources dir="${src}/test/java">
+                <include name="**/*.java" />
+            </testsources>
+            -->
+        </initialize-clover>
+        
+        <!-- Initialize target directories -->
+        <init-target />
+        
+        <!-- Compile Source -->
+        <compile-sources />
+        
+        <!-- Bundle Jars -->
+        <bundle-jars dist="${Etch.clover-dist}" />
+
+    </target>
+    
+    <target name="do-build" depends="generate-sources,compile-for-dist,compile-for-clover" />
+
+    <!-- TEST TARGET -->
+    <target name="do-test">
+        
+        <!-- Run Unit Tests -->
+        <!--
+        <junit printsummary="yes" haltonfailure="no" dir="${classesDirectory}"
+            errorProperty="build.tests.fail" failureProperty="build.tests.fail">
+            <classpath>
+                <pathelement location="${classesDirectory}/main" />
+                <pathelement location="${classesDirectory}/test" />
+                <pathelement location="${Etch.dependency.junit.jar}" />
+                <pathelement location="${Etch.HOME}/lib/${etch-compiler.jar}" />
+                <pathelement location="${Etch.dependency.clover.jar}"/>
+            </classpath>
+            <formatter type="xml"/>
+            <batchtest fork="true" todir="${testResultsDirectory}">
+                <fileset dir="${src}/test/java">
+                    <include name="**/*.java" />
+                </fileset>
+            </batchtest>
+        </junit>
+        -->
+    </target>
+
+    <!-- POSTBUILD TARGET -->
+    <target name="do-postbuild">
+    </target>
+
+    <target name="do-publish" if="build.tests.fail">
+        <!-- Set flag file if any tests failed -->
+        <touch file="${Etch.runtime.tests.fail}"/>
+    </target>
+
+</project>
diff --git a/binding-java/compiler/src/main/java/org/apache/etch/bindings/java/compiler/Compiler.java b/binding-java/compiler/src/main/java/org/apache/etch/bindings/java/compiler/Compiler.java
new file mode 100644
index 0000000..59b837e
--- /dev/null
+++ b/binding-java/compiler/src/main/java/org/apache/etch/bindings/java/compiler/Compiler.java
@@ -0,0 +1,1126 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.compiler;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.CmdLineOptions;
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.LogHandler;
+import org.apache.etch.compiler.Output;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.Token;
+import org.apache.etch.compiler.Version;
+import org.apache.etch.compiler.ast.Builtin;
+import org.apache.etch.compiler.ast.Except;
+import org.apache.etch.compiler.ast.Item;
+import org.apache.etch.compiler.ast.Message;
+import org.apache.etch.compiler.ast.MessageDirection;
+import org.apache.etch.compiler.ast.Module;
+import org.apache.etch.compiler.ast.MsgDirHelper;
+import org.apache.etch.compiler.ast.Name;
+import org.apache.etch.compiler.ast.Named;
+import org.apache.etch.compiler.ast.ParamList;
+import org.apache.etch.compiler.ast.Parameter;
+import org.apache.etch.compiler.ast.ReservedWordChecker;
+import org.apache.etch.compiler.ast.Service;
+import org.apache.etch.compiler.ast.Struct;
+import org.apache.etch.compiler.ast.Thrown;
+import org.apache.etch.compiler.ast.TypeRef;
+import org.apache.etch.compiler.opt.ToString;
+import org.apache.etch.compiler.opt.ToString.FieldItem;
+import org.apache.etch.compiler.opt.ToString.FmtItem;
+import org.apache.etch.compiler.opt.ToString.StringItem;
+import org.apache.etch.util.Assertion;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.exception.ResourceNotFoundException;
+import org.apache.velocity.runtime.RuntimeServices;
+import org.apache.velocity.runtime.log.LogChute;
+
+
+/**
+ * Compiler is a helper class not only for Backend, but also for the templates.
+ * They call methods here to perform "hard" tasks.
+ */
+public class Compiler extends Backend
+{
+
+	private final static String tmplPath1 = "org/apache/etch/bindings/java/compiler/";
+
+	private final static String tmplPath2 = "resources/org/apache/etch/bindings/java/compiler/";
+
+	private final static String fnSuffix = ".java";
+
+	private final static String VERSION = Version.VERSION + " / "
+		+ CompilerVersion.VERSION;
+
+	/**
+	 * Constructs the Compiler. This is a helper class not only for Backend, but
+	 * also for the templates. They call methods here to perform "hard" tasks.
+	 *
+	 * @throws Exception
+	 */
+	public Compiler() throws Exception
+	{
+		initVelocity();
+		
+		String[] path = { tmplPath1, tmplPath2 };
+		vf_vm = getTemplate( path, "vf.vm" );
+		intf_vm = getTemplate( path, "intf.vm" );
+		remote_vm = getTemplate( path, "remote.vm" );
+		stub_vm = getTemplate( path, "stub.vm" );
+		helper_vm = getTemplate( path, "helper.vm" );
+		readme_vm = getTemplate( path, "readme.vm" );
+		main_vm = getTemplate( path, "main.vm" );
+		base_vm = getTemplate( path, "base.vm" );
+		impl_vm = getTemplate( path, "impl.vm" );
+
+		local_kwd = getPath( path, "javaKeywords.kwd" );
+	}
+
+	private final Template vf_vm;
+
+	private final Template intf_vm;
+
+	private final Template remote_vm;
+
+	private final Template stub_vm;
+
+	private final Template helper_vm;
+
+	private final Template readme_vm;
+
+	private final Template main_vm;
+
+	private final Template base_vm;
+
+	private final Template impl_vm;
+
+	private final String local_kwd;
+
+	private LogHandler lh;
+	
+	/**
+	 * Initializes use of velocity engine and sets up
+	 * resource loaders.
+	 * @throws Exception
+	 */
+	private void initVelocity()
+		throws Exception
+	{
+		Velocity.setProperty( Velocity.RUNTIME_LOG_LOGSYSTEM, new MyLogger() );
+		
+		Velocity.setProperty( Velocity.RESOURCE_LOADER, "file, class" );
+
+		Velocity.setProperty( "file.resource.loader.description", "Velocity File Resource Loader" );
+		Velocity.setProperty( "file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.FileResourceLoader" );
+		Velocity.setProperty( "file.resource.loader.path", "." );
+
+		Velocity.setProperty( "class.resource.loader.description", "Velocity Classpath Resource Loader" );
+		Velocity.setProperty( "class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader" );
+		
+		Velocity.init();
+	}
+	
+	private static class MyLogger implements LogChute
+	{
+		private final LogHandler lh = null;
+		
+		public void init( RuntimeServices rts ) throws Exception
+		{
+			// ignore.
+		}
+
+		public boolean isLevelEnabled( int level )
+		{
+			return level >= 2;
+		}
+
+		public void log( int level, String msg )
+		{
+			if (level < 2)
+				return;
+			
+			if (lh != null)
+				lh.report( level == 2 ? LogHandler.LEVEL_WARNING : LogHandler.LEVEL_ERROR, null, msg );
+			else
+				System.out.printf( "Velocity msg (%d): %s\n", level, msg );
+		}
+
+		public void log( int level, String msg, Throwable e )
+		{
+			if (level < 2)
+				return;
+			
+			if (lh != null)
+				lh.report( level == 2 ? LogHandler.LEVEL_WARNING : LogHandler.LEVEL_ERROR, null, msg );
+			else
+				System.out.printf( "Velocity msg (%d): %s: %s\n", level, msg, e );
+		}
+	}
+
+	/**
+	 * @param path
+	 * @param fn
+	 * @return the velocity template
+	 * @throws Exception
+	 */
+	private Template getTemplate( String[] path, String fn )
+		throws Exception
+	{
+		ResourceNotFoundException rnfe = null;
+		
+		for (String p: path)
+		{
+			if (p == null)
+				continue;
+			
+//			System.out.println( "trying to load template "+(p+fn) );
+			try
+			{
+				if (Velocity.resourceExists( p+fn ))
+					return Velocity.getTemplate( p+fn );
+			}
+			catch ( ResourceNotFoundException e )
+			{
+				rnfe = e;
+			}
+			catch ( Exception e )
+			{
+				System.out.println( "ignoring "+e);
+			}
+		}
+		
+		if (rnfe != null)
+			throw rnfe;
+		
+		throw new ResourceNotFoundException("could not find resource: "+fn);
+	}
+
+	@Override
+	public void generate( Module module, CmdLineOptions options )
+		throws Exception
+	{
+		// java always wants to not flatten packages:
+		options.noFlattenPackages = true;
+		
+		lh = options.lh;
+
+		boolean ignoreGlobal = options.ignoreGlobalWordsList;
+		boolean ignoreLocal = options.ignoreLocalWordsList;
+		String userWords = options.userWordsList != null ? options.userWordsList.getPath() : null;
+		Set<String> what = options.what;
+
+		// Load the reserved words lists if any have been provided.
+		Map<String, String> words = new HashMap<String, String>();
+		if (!ignoreGlobal)
+			mapWords( global_kwd, words );
+		if (!ignoreLocal)
+			mapWords( local_kwd, words );
+		if (userWords != null)
+			mapWords( userWords, words );
+
+		// check for collisions with the reserved word list.
+		ReservedWordChecker checker = new ReservedWordChecker( words, false, lh );
+		module.treewalk( checker );
+		if (!checker.ok())
+		{
+			lh.report( LogHandler.LEVEL_ERROR, null, "Encountered errors during java generation." );
+			return;
+		}
+
+		// ok, we're ready to generate code. make sure the
+		// output directories exist.
+
+		Output dir = options.output;
+		Output templateDir = options.templateOutput;
+		
+		String m = module.name().name;
+		if (m.length() > 0)
+		{
+			dir = dir.newPackage( m );
+			templateDir = templateDir.newPackage( m );
+		}
+		
+		// generate code for each service.
+
+		for (Service intf : module)
+		{
+			generate( intf, what, dir, templateDir );
+		}
+	}
+
+	private void generate( final Service intf, Set<String> what, Output dir,
+		Output templateDir ) throws Exception
+	{
+		what = populateWhat( what );
+
+		if (what.isEmpty())
+		{
+			// lh.logMessage( lh.LEVEL_ERROR, null, "User has selected NONE\n" );
+			return;
+		}
+
+		final MessageDirection msgDir = getMessageDirection( what );
+
+		if (what.contains( WHAT_INTF ))
+		{
+			// Generate the value factory file.
+			
+			generateVf( intf, dir );
+	
+			// Generate the interface, remote, and stub files.
+	
+			generateIntfRemoteStub( intf, dir, msgDir, MessageDirection.BOTH, false );
+	
+			generateIntfRemoteStub( intf, dir, msgDir, MessageDirection.SERVER, true );
+	
+			generateIntfRemoteStub( intf, dir, msgDir, MessageDirection.CLIENT, true );
+	
+			// Generate helper file.
+	
+			generateHelper( intf, dir, msgDir );
+			
+			// Generate base file.
+			
+			generateBase( intf, dir, msgDir );
+	
+			// Generate readme file.
+			
+			generateReadme( intf, dir, msgDir );
+		}
+
+		// Generate main template file.
+
+		if (what.contains( WHAT_MAIN ))
+			generateMain( intf, templateDir, msgDir );
+
+		// Generate impl template file.
+
+		if (what.contains( WHAT_IMPL ))
+			generateImpl( intf, templateDir, msgDir );
+	}
+
+	private void generateReadme( final Service intf, Output dir,
+		final MessageDirection msgDir ) throws Exception
+	{
+		doFile( dir, "readme-etch-java-files.txt", lh, new Gen()
+		{
+			public void run( PrintWriter pw ) throws Exception
+			{
+				generateReadme( pw, intf, msgDir );
+			}
+		} );
+	}
+
+	private void generateVf( final Service intf, Output dir )
+		throws Exception
+	{
+		doFile( dir, getVfName( intf ) + fnSuffix, lh, new Gen()
+		{
+			public void run( PrintWriter pw ) throws Exception
+			{
+				generateVf( pw, intf );
+			}
+		} );
+	}
+
+	private void generateHelper( final Service intf, Output dir,
+		final MessageDirection msgDir ) throws Exception
+	{
+		doFile( dir, getHelperName( intf ) + fnSuffix, lh, new Gen()
+		{
+			public void run( PrintWriter pw ) throws Exception
+			{
+				generateHelper( pw, intf, msgDir );
+			}
+		} );
+	}
+
+	private void generateMain( final Service intf, Output dir,
+		MessageDirection msgDir ) throws Exception
+	{
+		if (msgDir == MessageDirection.BOTH
+				|| msgDir == MessageDirection.CLIENT)
+			doFile( dir, getMainName( intf, MessageDirection.CLIENT ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateMain( pw, intf, MessageDirection.CLIENT, false );
+				}
+			} );
+
+		if (msgDir == MessageDirection.BOTH
+				|| msgDir == MessageDirection.SERVER)
+			doFile( dir, getMainName( intf, MessageDirection.SERVER ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateMain( pw, intf, MessageDirection.SERVER, false );
+				}
+			} );
+	}
+
+	private void generateBase( final Service intf, Output dir,
+		MessageDirection msgDir ) throws Exception
+	{
+		if (msgDir == MessageDirection.BOTH || msgDir == MessageDirection.CLIENT)
+			doFile( dir, getBaseName( intf, MessageDirection.CLIENT ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateBase (pw, intf, MessageDirection.CLIENT, false );
+				}
+			} );
+
+		if (msgDir == MessageDirection.BOTH || msgDir == MessageDirection.SERVER)
+			doFile( dir, getBaseName( intf, MessageDirection.SERVER ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateBase (pw, intf, MessageDirection.SERVER, false );
+				}
+			} );
+	}
+
+	private void generateImpl( final Service intf, Output dir,
+		MessageDirection msgDir ) throws Exception
+	{
+		if (msgDir == MessageDirection.BOTH
+				|| msgDir == MessageDirection.CLIENT)
+			doFile( dir, getImplName( intf, MessageDirection.CLIENT ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateImpl( pw, intf, MessageDirection.CLIENT, false );
+				}
+			} );
+
+		if (msgDir == MessageDirection.BOTH
+				|| msgDir == MessageDirection.SERVER)
+			doFile( dir, getImplName( intf, MessageDirection.SERVER ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateImpl( pw, intf, MessageDirection.SERVER, false );
+				}
+			} );
+	}
+
+	private void generateIntfRemoteStub( final Service intf, Output dir,
+		final MessageDirection what, final MessageDirection mc,
+		final boolean hasBaseClass ) throws Exception
+	{
+		// Generate interface file
+
+		doFile( dir, getIntfName( intf, mc ) + fnSuffix, lh, new Gen()
+		{
+			public void run( PrintWriter pw ) throws Exception
+			{
+				generateIntf( pw, intf, mc, hasBaseClass );
+			}
+		} );
+
+		// Generate remote file
+
+		if (mc == MessageDirection.BOTH || what == MessageDirection.BOTH
+				|| mc != what)
+			doFile( dir, getRemoteName( intf, mc ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateRemote( pw, intf, mc, hasBaseClass );
+				}
+			} );
+
+		// Generate stub file
+
+		if (mc == MessageDirection.BOTH || what == MessageDirection.BOTH
+				|| mc == what)
+			doFile( dir, getStubName( intf, mc ) + fnSuffix, lh, new Gen()
+			{
+				public void run( PrintWriter pw ) throws Exception
+				{
+					generateStub( pw, intf, mc, hasBaseClass );
+				}
+			} );
+	}
+
+	/**
+	 * Generate the value factory for the service.
+	 *
+	 * @param pw
+	 * @param intf
+	 * @throws Exception
+	 */
+	void generateVf( PrintWriter pw, Service intf ) throws Exception
+	{
+		// params keeps track of the total set of parameters
+		// named (for enums, structs, exceptions, and messages).
+		Set<String> params = new HashSet<String>();
+
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "params", params );
+		vf_vm.merge( context, pw );
+	}
+
+	/**
+	 * Generate the interface for the service.
+	 *
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @param hasBaseClass
+	 * @throws Exception
+	 */
+	void generateIntf( PrintWriter pw, Service intf, MessageDirection mc,
+		boolean hasBaseClass ) throws Exception
+	{
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "mc", mc );
+		context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
+		context.put( "hasBaseClass", hasBaseClass );
+		intf_vm.merge( context, pw );
+	}
+
+	/**
+	 * Generate the call to message implementation of the interface. This class
+	 * turns calls on its methods into messages which are sent to the remote
+	 * stub. For two-way calls, it then waits for a response message, returning
+	 * the result therein to the caller.
+	 *
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @param hasBaseClass
+	 * @throws Exception
+	 */
+	void generateRemote( PrintWriter pw, Service intf, MessageDirection mc,
+		boolean hasBaseClass ) throws Exception
+	{
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "mc", mc );
+		context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
+		context.put( "hasBaseClass", hasBaseClass );
+		context.put( "methodList", new ArrayList<String>());
+		remote_vm.merge( context, pw );
+	}
+
+	/**
+	 * Generate the message to call implementation. This class accepts a message
+	 * and turns it back into a call on the user's implementation. For two-way
+	 * messages, the return value from the user's implementation method is turned
+	 * into the appropriate response message and sent.
+	 *
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @param hasBaseClass
+	 * @throws Exception
+	 */
+	void generateStub( PrintWriter pw, Service intf, MessageDirection mc,
+		boolean hasBaseClass ) throws Exception
+	{
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "mc", mc );
+		context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
+		context.put( "hasBaseClass", hasBaseClass );
+		stub_vm.merge( context, pw );
+	}
+
+	/**
+	 * Generate the transport plumbing helper.
+	 *
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @throws Exception
+	 */
+	void generateHelper( PrintWriter pw, Service intf, MessageDirection mc )
+		throws Exception
+	{
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "mc", mc );
+
+		helper_vm.merge( context, pw );
+	}
+
+	/**
+	 * Generate the readme.txt.
+	 *
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @throws Exception
+	 */
+	void generateReadme( PrintWriter pw, Service intf, MessageDirection mc ) throws Exception
+	{
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "mc", mc );
+
+		readme_vm.merge( context, pw );
+	}
+
+	/**
+	 * Generate the template main program.
+	 *
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @param hasBaseClass
+	 * @throws Exception
+	 */
+	void generateMain( PrintWriter pw, Service intf, MessageDirection mc,
+		boolean hasBaseClass ) throws Exception
+	{
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "mc", mc );
+		context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
+		context.put( "hasBaseClass", hasBaseClass );
+		main_vm.merge( context, pw );
+	}
+
+	/**
+	 * Generates the base implementation of the interfaces, with each
+	 * method throwing an exception to the tune that it isn't implemented.
+	 * User's impl will extend this base implementation.
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @param hasBaseClass
+	 * @throws Exception
+	 */
+	void generateBase( PrintWriter pw, Service intf, MessageDirection mc,
+		boolean hasBaseClass ) throws Exception
+		{
+			VelocityContext context = new VelocityContext();
+			context.put( "now", new Date() );
+			context.put( "version", VERSION );
+			context.put( "helper", this );
+			context.put( "intf", intf );
+			context.put( "mc", mc );
+			context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
+			context.put( "hasBaseClass", hasBaseClass );
+			context.put( "methodList", new ArrayList<String>());
+			base_vm.merge( context, pw );
+		}
+
+	/**
+	 * Generate the template user implemention class which extends the base
+	 * implementation generated above. This class will only have the appropriate
+	 * constructor and reference to the appropriate remote, and a comment inviting
+	 * the user to override methods.
+	 * @param pw
+	 * @param intf
+	 * @param mc
+	 * @param hasBaseClass
+	 * @throws Exception
+	 */
+	void generateImpl( PrintWriter pw, Service intf, MessageDirection mc,
+		boolean hasBaseClass ) throws Exception
+	{
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "mc", mc );
+		context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
+		context.put( "hasBaseClass", hasBaseClass );
+		impl_vm.merge( context, pw );
+	}
+
+	private String getVfName( Service intf )
+	{
+		return "ValueFactory" + getIntfName( intf, MessageDirection.BOTH );
+	}
+
+	private String getIntfName( Service intf, MessageDirection mc )
+	{
+		String suffix = MsgDirHelper.getSuffix( mc );
+		return intf.name() + suffix;
+	}
+
+	private String getMainName( Service intf, MessageDirection mc )
+	{
+		if (mc == MessageDirection.SERVER)
+			return "Main" + intf.name() + "Listener";
+		return "Main" + getIntfName( intf, mc );
+	}
+
+	private String getImplName( Service intf, MessageDirection mc )
+	{
+		return "Impl" + getIntfName( intf, mc );
+	}
+
+	private String getRemoteName( Service intf, MessageDirection mc )
+	{
+		return "Remote" + getIntfName( intf, mc );
+	}
+
+	private String getStubName( Service intf, MessageDirection mc )
+	{
+		return "Stub" + getIntfName( intf, mc );
+	}
+
+	private String getHelperName( Service intf )
+	{
+		return intf.name() + "Helper";
+	}
+	
+	private String getBaseName( Service intf, MessageDirection mc )
+	{
+		return "Base" + getIntfName( intf, mc );
+	}
+
+	@Override
+	public String asyncReceiverPoolName( Message msg )
+	{
+		return msg.getAsyncReceiver().toString().toLowerCase();
+	}
+
+	@Override
+	public String getTypeValue( TypeRef type, Token value )
+	{
+		// System.out.println( "getTypeValue called with: "+type+": "+value );
+		Token t = type.type();
+		switch (t.kind)
+		{
+			case EtchGrammarConstants.LONG:
+				return value.image + "l";
+			case EtchGrammarConstants.FLOAT:
+				return value.image + "f";
+			case EtchGrammarConstants.DOUBLE:
+				return value.image + "d";
+			case EtchGrammarConstants.STRING:
+				return protectString( value.image );
+			default:
+				return value.image;
+		}
+	}
+
+	private String protectString( String s )
+	{
+		// System.out.println( "protectString called with: "+s );
+
+		StringBuffer sb = new StringBuffer();
+		sb.append( "\"" );
+		for (char c : s.toCharArray())
+		{
+			if (c == '\t')
+			{
+				sb.append( "\\t" );
+				continue;
+			}
+			if (c == '\r')
+			{
+				sb.append( "\\r" );
+				continue;
+			}
+			if (c == '\n')
+			{
+				sb.append( "\\n" );
+				continue;
+			}
+			if (c == '\"')
+			{
+				sb.append( "\\\"" );
+				continue;
+			}
+			if (c == '\\')
+			{
+				sb.append( "\\\\" );
+				continue;
+			}
+			if (c >= 32 && c < 127)
+			{
+				sb.append( c );
+				continue;
+			}
+			sb.append( String.format( "\\u%04x", (int) c ) );
+		}
+		sb.append( "\"" );
+		return sb.toString();
+	}
+
+	/**
+	 * @param type
+	 * @return type name appropriate for use as a structure element or exception
+	 * parameter or function parameter or result.
+	 */
+	@Override
+	public String getTypeName( TypeRef type )
+	{
+		if (type.dim() > 0)
+			return getNativeTypeName( type ) + dim2spec( type.dim() );
+		return getRefTypeName( type );
+	}
+
+	/**
+	 * @param type the etch type
+	 * @return the fundamental native type for java. so etch int -> java int,
+	 * while etch string -> java String.
+	 */
+	@Override
+	public String getNativeTypeName( TypeRef type )
+	{
+		Token t = type.type();
+		switch (t.kind)
+		{
+			case EtchGrammarConstants.VOID:
+				return "void";
+			case EtchGrammarConstants.BOOLEAN:
+				return "boolean";
+			case EtchGrammarConstants.BYTE:
+				return "byte";
+			case EtchGrammarConstants.SHORT:
+				return "short";
+			case EtchGrammarConstants.INT:
+				return "int";
+			case EtchGrammarConstants.LONG:
+				return "long";
+			case EtchGrammarConstants.FLOAT:
+				return "float";
+			case EtchGrammarConstants.DOUBLE:
+				return "double";
+			case EtchGrammarConstants.STRING:
+				return "String";
+			case EtchGrammarConstants.OBJECT:
+				return "Object";
+			default:
+			{
+				// we have to use a fully qualified name here.
+				// find the actual type...
+				Named<?> n = type.intf().get( t.image );
+				if (n == null)
+					throw new IllegalArgumentException( String.format(
+						"undefined or ambiguous name at line %d: %s",
+						t.beginLine, t.image ) );
+				return n.efqname( this );
+			}
+		}
+	}
+
+	/**
+	 * @param type the etch type
+	 * @return the fundamental native reference type for java. so etch int ->
+	 * java Integer, while etch string -> java String.
+	 */
+	private String getRefTypeName( TypeRef type )
+	{
+		Token t = type.type();
+		switch (t.kind)
+		{
+			case EtchGrammarConstants.VOID:
+				return "void";
+			case EtchGrammarConstants.BOOLEAN:
+				return "Boolean";
+			case EtchGrammarConstants.BYTE:
+				return "Byte";
+			case EtchGrammarConstants.SHORT:
+				return "Short";
+			case EtchGrammarConstants.INT:
+				return "Integer";
+			case EtchGrammarConstants.LONG:
+				return "Long";
+			case EtchGrammarConstants.FLOAT:
+				return "Float";
+			case EtchGrammarConstants.DOUBLE:
+				return "Double";
+			case EtchGrammarConstants.STRING:
+				return "String";
+			case EtchGrammarConstants.OBJECT:
+				return "Object";
+			default:
+			{
+				// we have to use a fully qualified name here.
+				// find the actual type...
+				Named<?> n = type.intf().get( t.image );
+				if (n == null)
+					throw new IllegalArgumentException( String.format(
+						"undefined or ambiguous name at line %d: %s",
+						t.beginLine, t.image ) );
+				return n.efqname( this );
+			}
+		}
+	}
+
+	private String dim2spec( int i )
+	{
+		String s = "";
+		while (i-- > 0)
+			s += "[]";
+		return s;
+	}
+
+	@Override
+	public String formatString( ParamList<Service> n, boolean isExcept )
+		throws ParseException, IOException
+	{
+		ToString ts = (ToString) n.getOpt( "ToString" );
+		List<FmtItem> list;
+		if (ts != null)
+		{
+			list = ts.getFormat();
+			n.checkFormatList( ts.lineno(), list );
+		}
+		else if (isExcept)
+			list = n.mkFormatList( true, ((Except)n).hasExtends() );
+		else
+			list = n.mkFormatList( false, ((Struct)n).hasExtends() );
+
+		if (list.size() == 1)
+		{
+			return list.get( 0 ).value();
+		}
+
+		StringBuffer sb = new StringBuffer();
+		sb.append( "String.format( " );
+		sb.append( "\"" );
+		for (FmtItem i : list)
+		{
+			if (i instanceof FieldItem)
+			{
+				sb.append( "%s" );
+			}
+			else
+			{
+				escape( sb, ((StringItem) i).value() );
+			}
+		}
+		sb.append( "\"" );
+		for (FmtItem i : list)
+		{
+			if (i instanceof FieldItem)
+			{
+				sb.append( ", " );
+				sb.append( ((FieldItem) i).value() );
+			}
+		}
+		sb.append( " )" );
+		return sb.toString();
+	}
+
+	private void escape( StringBuffer sb, String s ) throws IOException
+	{
+		StringReader rdr = new StringReader( s );
+		int c;
+		while ((c = rdr.read()) >= 0)
+		{
+			if (c == '"')
+				sb.append( "\\\"" );
+			else if (c == '\\')
+				sb.append( "\\\\" );
+			else if (c == '\t')
+				sb.append( "\\t" );
+			else if (c == '\r')
+				sb.append( "\\r" );
+			else if (c == '\n')
+				sb.append( "\\n" );
+			else
+				sb.append( (char) c );
+		}
+	}
+
+	@Override
+	public String mfvname( String vname )
+	{
+		return "_mf_" + vname;
+	}
+
+	@Override
+	public String mtvname( String vname )
+	{
+		return "_mt_" + vname;
+	}
+
+	@Override
+	public String getLang()
+	{
+		return "java";
+	}
+
+	@Override
+	public String enum_efqname( String fqname, String moduleName,
+		String serviceName, String enumName )
+	{
+		return fqname;
+	}
+
+	@Override
+	public String except_efqname( String fqname, String moduleName,
+		String serviceName, String exceptName )
+	{
+
+		return fqname;
+	}
+
+	@Override
+	public String struct_efqname( String fqname, String moduleName,
+		String serviceName, String enumName )
+	{
+
+		return fqname;
+	}
+
+	@Override
+	public String qualifyParameterName( Token name )
+	{
+		return name.image;
+	}
+
+	@Override
+	public String qualifyConstantName( Service intf, Token name )
+	{
+		return intf.fqname() + '.' + name.image;
+	}
+
+	@Override
+	public String qualifyEnumName( Service intf, Token name )
+	{
+		return intf.fqname() + '.' + name.image;
+	}
+
+	@Override
+	public String getValidator( Named<?> named )
+	{
+		if (named instanceof Parameter)
+		{
+			Parameter param = (Parameter) named;
+			TypeRef type = param.type();
+
+			if (type.isBuiltin())
+				return String.format( "Validator_%s.get( %d )",
+					type.type(), type.dim() );
+
+			Named<?> n = type.getNamed( type.intf() );
+
+			if (n.isBuiltin())
+			{
+				Builtin b = (Builtin) n;
+				String cn = b.className();
+				
+				int i = cn.indexOf( '<' );
+				if (i >= 0)
+					cn = cn.substring( 0, i );
+				
+				return String.format( "Validator_custom.get( %s.class, %d, %s )",
+					cn, type.dim(), b.allowSubclass() );
+			}
+
+			// Allow subclassing for etch defined structs and externs.
+
+			if (n.isStruct() || n.isExcept())
+				return String.format( "Validator_custom.get( %s.class, %d, true )",
+					n.efqname( this ), type.dim() );
+
+			// Don't allow subclassing for externs or etch defined enums.
+
+			if (!(n.isExtern() || n.isEnumx()))
+				Assertion.check( n.isExtern() || n.isEnumx(),
+					"n.isExtern() || n.isEnumx(): "+n );
+
+			return String.format( "Validator_custom.get( %s.class, %d, false )",
+				n.efqname( this ), type.dim() );
+		}
+
+		if (named instanceof Thrown)
+		{
+			Thrown thrown = (Thrown) named;
+			Except e = (Except) thrown.getNamed();
+			return String.format( "Validator_custom.get( %s.class, 0, true )", e.efqname( this ) );
+		}
+
+		if (named instanceof Item)
+			return "Validator_boolean.get( 0 )";
+
+		return "null";
+	}
+
+	/**
+	 * @param name
+	 * @return the appropriate name for a getter method.
+	 */
+	public String getGetterName( Name name )
+	{
+		String s = name.name;
+		return "get"+s.substring( 0, 1 ).toUpperCase()+s.substring( 1 );
+	}
+
+	/**
+	 * @param name
+	 * @return the appropriate name for a setter method.
+	 */
+	public String getSetterName( Name name )
+	{
+		String s = name.name;
+		return "set"+s.substring( 0, 1 ).toUpperCase()+s.substring( 1 );
+	}
+
+	@Override
+	public void addDefaults( Service service ) throws ParseException
+	{
+		addBuiltin( service, newName( "List" ), "java.util.List<?>", true );
+		addBuiltin( service, newName( "Map" ), "java.util.Map<?, ?>", true );
+		addBuiltin( service, newName( "Set" ), "java.util.Set<?>", true );
+		addBuiltin( service, newName( "Datetime" ), "java.util.Date", false );
+	}
+}
diff --git a/binding-java/compiler/src/main/java/org/apache/etch/bindings/java/compiler/CompilerVersion.java b/binding-java/compiler/src/main/java/org/apache/etch/bindings/java/compiler/CompilerVersion.java
new file mode 100644
index 0000000..3f0a55d
--- /dev/null
+++ b/binding-java/compiler/src/main/java/org/apache/etch/bindings/java/compiler/CompilerVersion.java
@@ -0,0 +1,33 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.compiler;
+
+/**
+ * The version info of this Etch backend (compiler).
+ */
+public interface CompilerVersion
+{
+	// This file is edited by the production build system to replace the value
+	// of VERSION below with whatever it wants the version string to actually be.
+	
+	/** The version of this Etch backend (compiler) */
+	public String VERSION = "java 1.1.0-incubating (LOCAL-0)";
+}
diff --git a/binding-java/compiler/src/main/java/org/apache/etch/bindings/java/compiler/CompilerVersion.java.tmpl b/binding-java/compiler/src/main/java/org/apache/etch/bindings/java/compiler/CompilerVersion.java.tmpl
new file mode 100644
index 0000000..84c0dcb
--- /dev/null
+++ b/binding-java/compiler/src/main/java/org/apache/etch/bindings/java/compiler/CompilerVersion.java.tmpl
@@ -0,0 +1,30 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.compiler;
+
+/**
+ * The version info of this Etch backend (compiler).
+ */
+public interface CompilerVersion
+{
+	// This file is edited by the production build system to replace the value
+	// of VERSION below with whatever it wants the version string to actually be.
+	
+	/** The version of this Etch backend (compiler) */
+	public String VERSION = "java @EtchLongVersion@ (@EtchBuildTag@)";
+}
diff --git a/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/base.vm b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/base.vm
new file mode 100644
index 0000000..2b3e696
--- /dev/null
+++ b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/base.vm
@@ -0,0 +1,143 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created and should not be edited!
+// Re-implement these methods by overriding them in Impl$intf.name()$suffix.
+#set($i = $intf.name())
+#set($intfname = "$i$suffix")
+#set($clname = "Base$intfname")
+#if ($helper.isServer($mc))
+#set($peer = "client")
+#else
+#set($peer = "server")
+#end
+
+package $intf.parent().name();
+
+import org.apache.etch.bindings.java.support.ObjSession;
+
+#foreach( $n in $intf.iterator() )
+#if ($n.isExtern())
+#if ($n.hasImport( $helper ))
+import $n.getImport( $helper );
+#end
+#end
+#end
+
+/**
+ * Base implementation of $intfname, with default method implementations
+ * which throw UnsupportedOperationException. Extend this class to provide
+ * implementations of messages from the $peer.
+ *
+ * @see Impl$intfname
+ */
+public class $clname implements $intfname, ObjSession
+{
+	public Object _sessionQuery( Object query ) throws Exception
+	{
+		throw new UnsupportedOperationException( "unknown query: "+query );
+	}
+
+	public void _sessionControl( Object control, Object value ) throws Exception
+	{
+		throw new UnsupportedOperationException( "unknown control: "+control );
+	}
+
+	public void _sessionNotify( Object event ) throws Exception
+	{
+		if (event instanceof Throwable)
+			((Throwable) event).printStackTrace();
+	}
+#foreach ($mthd in $intf.iterator())
+#if ($mthd.isMsgDir($mc) || $mthd.isMsgDirBoth())
+#if (!$mthd.isHidden())
+#if(!$methodList.contains($mthd.name().name()))
+#set ( $addMethodListStatus = $methodList.add($mthd.name().name()) )
+
+	public $helper.getTypeName( $mthd.type() ) $mthd.name()
+	(
+#set( $sep = "" )
+#foreach( $param in $mthd.iterator() )
+		$sep$helper.getTypeName( $param.type() ) $param.name()
+#set( $sep = ", " )
+#end
+	)
+#if($mthd.hasThrown())
+	throws
+#set( $sep = "" )
+#foreach($t in $mthd.thrown().iterator())
+		$sep$t.getNamed().fqname()
+#set( $sep = ", " )
+#end
+#end
+	{
+		throw new UnsupportedOperationException( "$mthd.name()" );
+	}
+#end
+#end
+#end
+#end
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+#foreach( $n in $z.messages( true ) )
+#if($n.isMsgDir($mc) || $n.isMsgDirBoth() )
+#if(!$n.isHidden())
+#if(!$methodList.contains($n.name().name()))
+#set ( $addMethodListStatus = $methodList.add($n.name().name()) )
+#if($n.isOneway())
+
+	public $helper.getTypeName( $n.type() ) $n.name()
+	(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+		$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+	)
+	{
+		throw new UnsupportedOperationException( "$n.name()" );
+	}
+#else
+
+	public $helper.getTypeName( $n.type() ) $n.name()
+	(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+		$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+	)
+#if($n.hasThrown())
+	throws
+#set( $sep = "" )
+#foreach($t in $n.thrown().iterator())
+		$sep$t.getNamed().fqname()
+#set( $sep = ", " )
+#end
+#end
+	{
+		throw new UnsupportedOperationException( "$n.name()" );
+	}
+#end
+#end
+#end
+#end
+#end
+#end
+#end
+}
diff --git a/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/helper.vm b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/helper.vm
new file mode 100644
index 0000000..4d560b1
--- /dev/null
+++ b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/helper.vm
@@ -0,0 +1,189 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created and should not be edited!
+
+#set($i = $intf.name()) 
+package $intf.parent().name();
+
+import org.apache.etch.bindings.java.support.DeliveryService;
+import org.apache.etch.bindings.java.support.Pool;
+#if($helper.isServer($mc) || $helper.isBoth($mc))
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.DefaultServerFactory;
+#end
+import org.apache.etch.util.core.io.Transport;
+import org.apache.etch.bindings.java.support.TransportFactory;
+import org.apache.etch.bindings.java.support.TransportHelper;
+import org.apache.etch.bindings.java.transport.DefaultDeliveryService;
+import org.apache.etch.bindings.java.transport.MailboxManager;
+import org.apache.etch.bindings.java.transport.PlainMailboxManager;
+import org.apache.etch.bindings.java.transport.TransportMessage;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+
+/**
+ * Transport helper for ${i}. All methods are static.
+ */
+abstract public class ${i}Helper extends TransportHelper
+{
+#if($helper.isServer($mc) || $helper.isBoth($mc))
+
+	/**
+	 * Constructs a new server session listener per specifications in uri and
+	 * resources. This listener will accept requests from clients for new server
+	 * sessions.
+	 *
+	 * @param uri contains specifications for the server session listener and
+	 * for the server session transport stack.
+	 *
+	 * @param resources additional resources to aid in constructing new server
+	 * sessions.
+	 *
+	 * @param implFactory factory used to construct a new instance implementing
+	 * ${i}Server. The new instance will receive and process messages from
+	 * the client session.
+	 *
+	 * @return a server session listener.
+	 *
+	 * @throws Exception
+	 */
+	public static ServerFactory newListener( final String uri,
+		final Resources resources, final ${i}ServerFactory implFactory )
+		throws Exception
+	{
+		final Resources res = initResources( resources );
+		
+		final Transport<ServerFactory> listener = TransportFactory.getListener( uri, res );
+		
+		return new DefaultServerFactory( listener, implFactory )
+		{
+			public void newServer( TransportMessage t, String uri, Resources r )
+				throws Exception
+			{
+				ValueFactory vf = (ValueFactory) r.get( Transport.VALUE_FACTORY );
+				MailboxManager x = new PlainMailboxManager( t, uri, r );
+				DeliveryService d = new DefaultDeliveryService( x, uri, r );
+				Remote${i}Client client = new Remote${i}Client( d, vf );
+				${i}Server server = implFactory.new${i}Server( client );
+				Pool qp = (Pool) r.get( QUEUED_POOL );
+				Pool fp = (Pool) r.get( FREE_POOL );
+				new Stub${i}Server( d, server, qp, fp );
+				client._start();
+			}
+
+			public ValueFactory newValueFactory( String uri )
+			{
+				return new ValueFactory${i}( uri );
+			}
+			
+			@Override
+			public String toString()
+			{
+				return "${i}Helper.ServerFactory/" + listener;
+			}
+		};
+	}
+
+	/**
+	 * Factory used by
+	 * {@link ${i}Helper#newListener(String, Resources, ${i}ServerFactory)}
+	 * to construct a new instance implementing {@link ${i}Server}. The new
+	 * instance will receive and process messages from the client session.
+	 */
+	public interface ${i}ServerFactory
+	{
+		/**
+		 * Constructs a new instance implementing ${i}Server. The new
+		 * instance will receive and process messages from the client session.
+		 *
+		 * @param client an instance of Remote${i}Client which may be used to
+		 * send messages to the client session.
+		 * @return a new instance implementing ${i}Server (typically
+		 * Impl${i}Server).
+		 * @throws Exception
+		 */
+		public ${i}Server new${i}Server( Remote${i}Client client )
+			throws Exception;
+	}
+#end
+#if($helper.isClient($mc) || $helper.isBoth($mc))
+
+	/**
+	 * Constructs a new client session per specifications in uri and resources.
+	 * 
+	 * @param uri contains specifications for the client session transport
+	 * stack.
+	 * 
+	 * @param resources additional resources to aid in constructing new client
+	 * sessions.
+	 * 
+	 * @param implFactory factory used to construct a new instance implementing
+	 * ${i}Client. The new instance will receive and process messages from
+	 * the server session.
+	 * 
+	 * @return an instance of Remote${i}Server initialized by uri and
+	 * resources which may be used to send messages to the server session.
+	 * 
+	 * @throws Exception
+	 */
+	public static Remote${i}Server newServer( String uri,
+		Resources resources, ${i}ClientFactory implFactory )
+		throws Exception
+	{
+		final Resources res = initResources( resources );
+		
+		final ValueFactory${i} vf = new ValueFactory${i}( uri );
+		res.put( Transport.VALUE_FACTORY, vf );
+		
+		URL u = new URL( uri );
+		
+		TransportMessage m = TransportFactory.getTransport( uri, res );
+		MailboxManager r = new PlainMailboxManager( m, u, resources );
+		DeliveryService d = new DefaultDeliveryService( r, u, resources );
+		Remote${i}Server server = new Remote${i}Server( d, vf );
+		${i}Client client = implFactory.new${i}Client( server );
+		Pool qp = (Pool) res.get( QUEUED_POOL );
+		Pool fp = (Pool) res.get( FREE_POOL );
+		new Stub${i}Client( d, client, qp, fp );
+
+		return server;
+	}
+
+	/**
+	 * Factory used by
+	 * {@link ${i}Helper#newServer(String, Resources, ${i}ClientFactory)}
+	 * to construct a new instance implementing {@link ${i}Client}. The new
+	 * instance will receive and process messages from the server session.
+	 */
+	public interface ${i}ClientFactory
+	{
+		/**
+		 * Constructs a new instance implementing ${i}Client. The new
+		 * instance will receive and process messages from the server session.
+		 * 
+		 * @param server an instance of Remote${i}Server which may be used to
+		 * send messages to the server session.
+		 * @return a new instance implementing ${i}Client (typically
+		 * Impl${i}Client).
+		 * @throws Exception
+		 */
+		public ${i}Client new${i}Client( Remote${i}Server server )
+			throws Exception;
+	}
+#end
+}
diff --git a/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/impl.vm b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/impl.vm
new file mode 100644
index 0000000..0b687f4
--- /dev/null
+++ b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/impl.vm
@@ -0,0 +1,60 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created for your convenience and will not be
+// overwritten once it exists! Please edit this file as necessary to implement
+// your service logic.
+#set($i = $intf.name())
+#set($intfname = "$i$suffix")
+#set($baseclname = "Base$intfname")
+#set($clname = "Impl$intfname")
+#if ($helper.isServer($mc))
+#set($peer = "client")
+#set($peerclass = "Remote${i}Client")
+#else
+#set($peer = "server")
+#set($peerclass = "Remote${i}Server")
+#end
+
+package $intf.parent().name();
+
+/**
+ * Your custom implementation of $baseclname. Add methods here to provide
+ * implementations of messages from the $peer.
+ */
+public class $clname extends $baseclname
+{
+	/**
+	 * Constructs the $clname.
+	 *
+	 * @param $peer a connection to the $peer session. Use this to send a
+	 * message to the $peer.
+	 */
+	public $clname( $peerclass $peer )
+	{
+		this.$peer = $peer;
+	}
+	
+	/**
+	 * A connection to the $peer session. Use this to send a
+	 * message to the $peer.
+	 */
+	@SuppressWarnings( "unused" )
+	private final $peerclass $peer;
+
+	// TODO insert methods here to provide implementations of $intfname
+	// messages from the $peer.
+}
\ No newline at end of file
diff --git a/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/intf.vm b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/intf.vm
new file mode 100644
index 0000000..3e38584
--- /dev/null
+++ b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/intf.vm
@@ -0,0 +1,289 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created and should not be edited!
+
+package $intf.parent().name();
+
+#if( !$hasBaseClass )
+import java.io.Serializable;
+#end
+
+#foreach( $n in $intf.iterator() )
+#if ($n.isExtern())
+#if ($n.hasImport( $helper ))
+import $n.getImport( $helper );
+#end
+#end
+#end
+
+#if ($intf.hasDescr())
+/**
+#foreach( $s in $intf.descr() )
+ * $s
+#end
+ */
+#end
+@SuppressWarnings("unused")
+#set ($sep = "extends")
+#if ($hasBaseClass)
+public interface $intf.name()$suffix $sep $intf.name()
+#set ($sep = ",")
+#else
+public interface $intf.name()$suffix
+#end
+#foreach( $n in $intf.iterator() )
+#if ($n.isMixin())
+	$sep $n.fqname()$suffix
+#set ($sep = ",")
+#end
+#end
+{
+#if (!$intf.hasMessageDirection($mc))
+	// no $mc direction items defined.
+#end
+#foreach( $n in $intf.iterator() )
+#if ($n.isMessage())
+#if ($n.isMsgDir($mc))
+#if (!$n.isHidden())
+	/**
+#foreach( $s in $n.descr() )
+	 * $s
+#end
+#foreach( $p in $n.iterator() )
+#set($first = true)
+#foreach( $s in $p.descr() )
+#if ($first)
+#set($first = false)
+	 * @param $p.name() $s
+#else
+	 * $s
+#end
+#end
+#end
+#if ($n.hasReturn())
+#set($first = true)
+#foreach( $s in $n.returnDescr() )
+#if ($first)
+#set($first = false)
+	 * @return $s
+#else
+	 * $s
+#end
+#end
+#end
+#foreach($t in $n.thrown().iterator())
+#set($first = true)
+#foreach( $s in $t.descr() )
+#if ($first)
+#set($first = false)
+	 * @throws $t.name() $s
+#else
+	 * $s
+#end
+#end
+#end
+	 */
+	public $helper.getTypeName( $n.type() ) $n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+		$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+	)
+#if ($n.hasThrown())
+	throws
+#set( $sep = "" )
+#foreach($t in $n.thrown().iterator())
+		$sep$t.getNamed().fqname()
+#set( $sep = ", " )
+#end
+#end
+	;
+#end
+#end
+#elseif ($n.isConstant())
+#if (!$hasBaseClass)
+#if ($n.hasDescr())
+	/**
+#foreach( $s in $n.descr() )
+	 * $s
+#end
+	 */
+#end
+	public $helper.getNativeTypeName( $n.type() ) $n.name() = $helper.getTypeValue( $n.type(), $n.value() );
+
+#end
+#elseif ($n.isEnumx())
+#if (!$hasBaseClass)
+#if ($n.hasDescr())
+	/**
+#foreach( $s in $n.descr() )
+	 * $s
+#end
+	 */
+#end
+	public enum $n.name()
+	{
+#set( $sep = "" )
+#foreach( $i in $n.iterator() )
+		/**
+#foreach( $s in $i.descr() )
+		 * $s
+#end
+		 */
+		$sep$i.name()
+#set( $sep = ", " )
+#end
+	}
+
+#end
+#elseif ($n.isExtern())
+## ignore extern
+#elseif ($n.isMixin())
+## ignore mixin
+#elseif ($n.isStruct() || $n.isExcept())
+#if (!$hasBaseClass)
+#if ($n.hasDescr())
+	/**
+#foreach( $s in $n.descr() )
+	 * $s
+#end
+	 */
+#end
+	@SuppressWarnings("serial")
+	public class $n.name()
+#if( $n.hasExtends() )
+		extends $n.getExtends().name()
+#else
+#if( $n.isExcept() )
+#if( $n.isUnchecked() )
+		extends RuntimeException
+#else
+		extends Exception
+#end
+#else
+		implements Serializable
+#end
+#end
+	{
+		/**
+		 * Constructs the $n.name(). Don't init any fields.
+		 */
+		public $n.name()()
+		{
+			// don't init any fields.
+		}
+#if ($n.hasAnyParameters())
+
+		/**
+		 * Constructs the $n.name().
+#foreach( $i in $n.getAllParameters() )
+#set( $sep = "@param " )
+#foreach( $s in $i.descr() )
+		 * $sep$i.name() $s
+#set( $sep = "" )
+#end
+#end
+		 */
+		public $n.name()
+		(
+#set( $sep = "" )
+#foreach( $i in $n.getAllParameters() )
+			$sep$helper.getTypeName( $i.type() ) $i.name()
+#set( $sep = ", " )
+#end
+		)
+		{
+#if( $n.hasExtends() )
+			super
+			(
+#set( $sep = "" )
+#foreach( $i in $n.getExtends().getAllParameters() )
+				$sep$i.name()
+#set( $sep = ", " )
+#end
+			);
+#end
+#foreach( $i in $n.getParameters() )
+			this.$i.name() = $i.name();
+#end
+		}
+#end
+#if( $n.isExcept() )
+
+		@Override
+		public String getMessage()
+		{
+			return $helper.formatString( $n, true );
+		}
+#else
+
+		@Override
+		public String toString()
+		{
+			return $helper.formatString( $n, false );
+		}
+#end
+#foreach( $i in $n.iterator() )
+
+#if( $i.hasDescr())
+		/**
+#foreach( $s in $i.descr() )
+		 * $s
+#end
+		 */
+#end
+		public $helper.getTypeName( $i.type() ) $i.name();
+
+		/**
+		 * Gets the value.
+		 *
+#foreach( $s in $i.descr() )
+		 * $s
+#end
+		 *
+		 * @return the value.
+		 */
+		public $helper.getTypeName( $i.type() ) $helper.getGetterName( $i.name() )()
+		{
+			return $i.name();
+		}
+
+		/**
+		 * Sets the value.
+		 *
+#foreach( $s in $i.descr() )
+		 * $s
+#end
+		 *
+		 * @param value the value.
+		 */
+		public void $helper.getSetterName( $i.name() )( $helper.getTypeName( $i.type() ) value )
+		{
+			this.$i.name() = value;
+		}
+#end
+	}
+
+#end
+#elseif ($n.isBuiltin())
+## nothing to do.
+#else
+	*** intf.vm: don't know what to do with $n ***
+#end
+#end
+}
diff --git a/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/javaKeywords.kwd b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/javaKeywords.kwd
new file mode 100644
index 0000000..ee91f90
--- /dev/null
+++ b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/javaKeywords.kwd
@@ -0,0 +1,76 @@
+# $Id$

+# 

+# Copyright 2007-2008 Cisco Systems Inc.

+# 

+# Licensed under the Apache License, Version 2.0 (the "License"); you may not

+# use this file except in compliance with the License. You may obtain a copy

+# of the License at

+#  

+#     http://www.apache.org/licenses/LICENSE-2.0

+# 

+# Unless required by applicable law or agreed to in writing, software

+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+# License for the specific language governing permissions and limitations

+# under the License.

+

+

+

+# *  	   	not used

+# ** 	  	added in 1.2

+# *** 	  	added in 1.4

+# **** 	  	added in 5.0

+

+true

+false

+null

+abstract

+continue

+for

+new

+switch

+assert			# ***

+default

+goto			# *

+package

+synchronized

+boolean

+do

+if

+private

+this

+break

+double

+implements

+protected

+throw

+byte

+else

+import

+public

+throws

+case

+enum			# ****

+instanceof

+return

+transient

+catch

+extends

+int

+short

+try

+char

+final

+interface

+static

+void

+class

+finally

+long

+strictfp		# **

+volatile

+const			# *

+float

+native

+super

+while

diff --git a/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/main.vm b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/main.vm
new file mode 100644
index 0000000..40d3197
--- /dev/null
+++ b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/main.vm
@@ -0,0 +1,103 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created for your convenience and will not be
+// overwritten once it exists! Please edit this file as necessary to implement
+// your service logic.
+#set($i = $intf.name())
+#set($intfname = "$i$suffix")
+#set($baseclname = "Base$intfname")
+#set($clname = "Impl$intfname")
+#if ($helper.isServer($mc))
+#set($peer = "client")
+#set($peerclass = "Remote${i}Client")
+#else
+#set($peer = "server")
+#set($peerclass = "Remote${i}Server")
+#end
+
+package $intf.parent().name();
+
+#if ($helper.isServer($mc))
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.util.core.io.Transport;
+
+/**
+ * Main program for ${i}Server. This program makes a listener to accept
+ * connections from Main${i}Client.
+ */
+public class Main${i}Listener implements ${i}Helper.${i}ServerFactory
+{
+	/**
+	 * Main program for ${i}Server.
+	 * 
+	 * @param args command line arguments.
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		// TODO Change to correct URI
+		String uri = "tcp://0.0.0.0:4001";
+		
+		ServerFactory listener = ${i}Helper.newListener( uri, null,
+			new Main${i}Listener() );
+
+		// Start the Listener
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+	}
+
+	public ${i}Server new${i}Server( Remote${i}Client client )
+	{
+		return new Impl${i}Server( client );
+	}
+}
+#else
+/**
+ * Main program for ${i}Client. This program makes a connection to the
+ * listener created by Main${i}Listener.
+ */
+public class Main${i}Client implements ${i}Helper.${i}ClientFactory
+{
+	/**
+	 * Main program for ${i}Client.
+	 * 
+	 * @param args command line arguments.
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		// TODO Change to correct URI
+		String uri = "tcp://localhost:4001";
+		
+		Remote${i}Server server = ${i}Helper.newServer( uri, null,
+			new Main${i}Client() );
+
+		// Connect to the service
+		server._startAndWaitUp( 4000 );
+
+		// TODO Insert Your Code Here
+
+		// Disconnect from the service
+		server._stopAndWaitDown( 4000 );
+	}
+
+	public ${i}Client new${i}Client( Remote${i}Server server )
+		throws Exception
+	{
+		return new Impl${i}Client( server );
+	}
+}
+#end
diff --git a/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/readme.vm b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/readme.vm
new file mode 100644
index 0000000..590cadd
--- /dev/null
+++ b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/readme.vm
@@ -0,0 +1,135 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created and should not be edited!
+
+This is a description of the etch-generated files for your service.
+
+----------------
+- How To Build -
+----------------
+
+In the directory where the etch file is located, execute the following command:
+
+etch -q -d . -I . -b java -w all Blah.etch
+
+This would compile the service description Blah.etch, generating all java files,
+into java packages rooted in the current directory (-d .), resolving includes
+and mixins from the current directory (-I .) and being quiet about it (-q).
+
+Assuming the Blah.etch specified a module of "demo" and a service of Blah,
+the java files would be generated into a sub-directory demo of the current
+directory. you may now change to that directory and compile the resulting files:
+
+cd demo
+javac -cp %ETCH_HOME%\lib\etch-java-runtime.jar *.java
+
+(Assuming windows; for unix, you only need to change the slash direction and
+change %ETCH_HOME% into \$ETCH_HOME.)
+
+To run the service (which initially won't do anything but make a connection and
+then close it, use the following two commands in separate shells (again, from
+the demo directory):
+
+java -cp %ETCH_HOME%\lib\etch-java-runtime.jar;.. demo.MainBlahListener
+
+java -cp %ETCH_HOME%\lib\etch-java-runtime.jar;.. demo.MainBlahClient
+
+(Again, assuming windows; for unix, make the changes detailed above and also
+change the semi-colon in the -cp spec to a colon.)
+
+The first command (java ... demo.MainBlahListener) starts the service listener
+which accepts connections. The second command runs a sample client, which makes
+a connection to the running listener and then closes it again.
+
+Once you've compiled the service and tested the result, you may implement your
+service by adding content to the etch file, adding implementation details to the
+Impl*.java and Main*.java files, and recompiling using the above steps. You may
+also load these files into an IDE such as eclipse or intellij, or use a build
+management system such as maven or ant. Remember, whenever you change the etch
+file, you must re-etch the service description and then re-javac all the java
+files.
+
+-------------------
+- Generated Files -
+-------------------
+
+Here is a description of the generated files for a service named Blah.
+
+Blah.java
+BlahClient.java
+BlahServer.java
+
+These three files are the generated interface classes. Service defined constants
+and types are in Blah.java, as well as direction "both" messages, which are
+messages which are shared between client and server. BlahClient.java and
+BlahServer.java are respectively the messages for just the direction client or
+server. You should not edit these files.
+
+RemoteBlah.java
+RemoteBlahClient.java
+RemoteBlahServer.java
+
+RemoteBlah*.java are the generated classes which implement the interfaces,
+with message implementations which encode the message type and arguments for
+transport to the connection peer and then receive and decode any response. You
+should not edit these files.
+
+StubBlah.java
+StubBlahClient.java
+StubBlahServer.java
+
+StubBlah*.java are the generated classes which receive messages encoded by
+RemoteBlah*.java and decode them, calling the appropriate message implementation
+and then encoding and sending any result. You should not edit these files.
+
+ValueFactoryBlah.java
+
+ValueFactoryBlah.java is a generated class which contains helper code to
+serialize service defined types and also the meta data which describes the
+messages and fields, field types, timeouts, etc. You should not edit this file.
+
+BaseBlah.java
+BaseBlahClient.java
+BaseBlahServer.java
+
+BaseBlah*.java are generated classes which implement the interfaces, with
+message implementations which do nothing but throw UnsupportedOperationException.
+They can be used to supply an implementation when you don't want to immediately
+implement all the messages. You should not edit these files.
+
+ImplBlahClient.java
+ImplBlahServer.java
+
+ImplBlah*.java are the generated sample client and server implementation
+classes. They extend the generated base classes. These are used by the sample
+main programs to provide implementations of the client or server messages. Edit
+these files as you wish to implement your service (overriding the default
+implementations from the generated base classes).
+
+BlahHelper.java
+
+BlahHelper.java is a generated class which includes static methods to help
+construct transports for client and listener. You should not edit this file.
+
+MainBlahClient.java
+MainBlahListener.java
+
+MainBlah*.java are the generated sample client and server main programs.
+They show how to setup a transport and start it and how to create a session.
+Edit these files as you wish to implement your service, or just copy the code
+into your own application.
+
diff --git a/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/remote.vm b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/remote.vm
new file mode 100644
index 0000000..ba836ba
--- /dev/null
+++ b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/remote.vm
@@ -0,0 +1,422 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created and should not be edited!
+#set($i = $intf.name())
+#set($vfname = "ValueFactory$i")
+#set($intfname = "$i$suffix")
+#set($clname = "Remote$intfname")
+
+package $intf.parent().name();
+
+#foreach( $n in $intf.iterator() )
+#if($n.isExtern())
+#if($n.hasImport( $helper ))
+import $n.getImport( $helper );
+#end
+#end
+#end
+
+/**
+ * Call to message translator for $intfname.
+ */
+@SuppressWarnings("unused")
+#if($hasBaseClass)
+public final class $clname extends Remote$i implements $intfname
+#else
+public class $clname extends org.apache.etch.bindings.java.support.RemoteBase implements $intfname
+#end
+{
+	/**
+	 * Constructs the $clname.
+	 *
+	 * @param svc
+	 * @param vf
+	 */
+	public $clname( org.apache.etch.bindings.java.support.DeliveryService svc, org.apache.etch.bindings.java.msg.ValueFactory vf )
+	{
+		super( svc, vf );
+#set( $k = 0 )
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+#set( $k = $k + 1 )
+#set( $v = "_mixin$k" )
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+		$v = new ${m.name()}.Remote$z.name()${suffix}( svc, vf );
+#end
+#end
+	}
+
+	/**
+	 * {@link _Async} class instance used to hide asynchronous message
+	 * implementation. Use this to invoke the asynchronous message
+	 * implementations.
+	 */
+	public final _Async _async = new _Async();
+
+	/**
+	 * {@link _Async} class instance used to hide asynchronous message
+	 * implementation. This is here for backwards compatibility only, use
+	 * {@link #_async} instead.
+	 * @deprecated
+	 */
+	@Deprecated
+	public final _Async _inner = _async;
+#foreach($n in $intf.iterator())
+#if($n.isMsgDir($mc))
+#if(!$n.isHidden())
+#if(!$methodList.contains($n.name().name()))
+#set ( $addMethodListStatus = $methodList.add($n.name().name()))
+#if($n.isOneway())
+
+	public final $helper.getTypeName( $n.type() ) $n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+		$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+	)
+	{
+		org.apache.etch.bindings.java.msg.Message _msg = _newMessage( $vfname.$n.vname( $helper ) );
+#foreach( $p in $n.iterator() )
+		_msg.put( $vfname.$p.vname( $helper ), $p.name() );
+#end
+		try
+		{
+			_send( _msg );
+		}
+		catch ( Exception _e )
+		{
+			if (_e instanceof RuntimeException) throw (RuntimeException) _e;
+			throw new RuntimeException( "unexpected exception from peer: "+_e, _e );
+		}
+	}
+#else
+
+	public final $helper.getTypeName( $n.type() ) $n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+		$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+	)
+#if($n.thrown().iterator().hasNext())
+	throws
+#set( $sep = "" )
+#foreach($t in $n.thrown().iterator())
+		$sep$t.getNamed().fqname()
+#set( $sep = ", " )
+#end
+#end
+	{
+#if($n.hasReturn())
+		return
+#end
+		_async._end_${n.name()}( _async._begin_${n.name()}(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+			$sep$p.name()
+#set( $sep = ", " )
+#end
+		) );
+	}
+#end
+#end
+#end
+#end
+#end
+#set( $k = 0 )
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+
+	// ----- mixin $x.name() ----- //
+#set( $k = $k + 1 )
+#set( $v = "_mixin$k" )
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+
+	private final ${m.name()}.Remote$z.name()$suffix $v;
+#foreach( $n in $z.messages( true ) )
+#if($n.isMsgDir($mc))
+#if(!$n.isHidden())
+#if(!$methodList.contains($n.name().name()))
+#set ( $addMethodListStatus = $methodList.add($n.name().name()) )
+	// --- generated methods for $n.name() --- //
+
+#if($n.isOneway())
+	public final $helper.getTypeName( $n.type() ) $n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+		$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+	)
+	{
+		${v}.$n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+			$sep$p.name()
+#set( $sep = ", " )
+#end
+		);
+	}
+#else
+	public final $helper.getTypeName( $n.type() ) $n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+		$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+	)
+#if($n.thrown().iterator().hasNext())
+	throws
+#set( $sep = "" )
+#foreach($t in $n.thrown().iterator())
+		$sep$t.getNamed().fqname()
+#set( $sep = ", " )
+#end
+#end
+	{
+#if($n.hasReturn())
+		return
+#end
+		${v}.$n.name()(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+			$sep$p.name()
+#set( $sep = ", " )
+#end
+		);
+	}
+#end
+#end
+#end
+#end
+#end
+#end
+#end
+
+	/**
+	 * Asynchronous implementation of service methods.
+	 */
+#if($hasBaseClass)
+	public final class _Async extends Remote${i}._Async
+#else
+	public class _Async
+#end
+	{
+#foreach($n in $intf.iterator())
+#if($n.isMsgDir($mc))
+#if(!$n.isHidden())
+#if(!$methodList.contains("_begin_end_$n.name().name()"))
+#set ( $addMethodListStatus = $methodList.add("_begin_end_$n.name().name()") )
+#if(!$n.isOneway())
+
+		/**
+		 * Begins a call to ${n.name()}.
+		 *
+#foreach( $s in $n.descr() )
+		 * $s
+#end
+#foreach( $p in $n.iterator() )
+#set($sep = "@param $p.name() ")
+#foreach( $s in $p.descr() )
+		 * $sep$s
+#set($sep = "")
+#end
+#end
+		 * @return mailbox used to retrieve the result using _end_${n.name()}.
+		 * @see $clname#${n.name()}
+		 * @see #_end_${n.name()}
+		 */
+		public final org.apache.etch.bindings.java.support.Mailbox _begin_${n.name()}(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+			$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+		)
+		{
+			org.apache.etch.bindings.java.msg.Message _msg = _newMessage( $vfname.$n.vname( $helper ) );
+#foreach( $p in $n.iterator() )
+			_msg.put( $vfname.$p.vname( $helper ), $p.name() );
+#end
+			return _begincall( _msg );
+		}
+		
+		/**
+		 * Ends a call to ${n.name()}.
+		 *
+#foreach( $s in $n.descr() )
+		 * $s
+#end
+		 * @param mb mailbox returned by _begin_${n.name()}.
+#if($n.hasReturn())
+#set($sep = "@return ")
+#foreach( $s in $n.returnDescr() )
+		 * $sep$s
+#set($sep = "")
+#end
+#end
+#foreach($t in $n.thrown().iterator())
+#set($sep = "@throws $t.name() ")
+#foreach( $s in $t.descr() )
+		 * $sep$s
+#set($sep = "")
+#end
+#end
+		 *
+		 * @see $clname#${n.name()}
+		 * @see #_begin_${n.name()}
+		 */
+		public final $helper.getTypeName( $n.type() ) _end_${n.name()}( org.apache.etch.bindings.java.support.Mailbox mb )
+#if($n.thrown().iterator().hasNext())
+			throws
+#set( $sep = "" )
+#foreach($t in $n.thrown().iterator())
+				$sep$t.getNamed().fqname()
+#set( $sep = ", " )
+#end
+#end
+		{
+			try
+			{
+#if($n.hasReturn())
+				return
+					($helper.getTypeName( $n.type() ))
+						_endcall( mb,
+							$vfname.$n.getResultMessage().vname( $helper ) );
+#else
+				_endcall( mb,
+					$vfname.$n.getResultMessage().vname( $helper )  );
+#end
+			}
+			catch ( Exception e )
+			{
+#foreach($t in $n.thrown().iterator())
+				if (e instanceof ${t.getNamed().fqname()})
+					throw ($t.getNamed().fqname()) e;
+#end
+				if (e instanceof RuntimeException) throw (RuntimeException) e;
+				throw new RuntimeException( "unexpected exception from peer: "+e, e );
+			}
+		}
+#end
+#end
+#end
+#end 
+#end
+
+		// Mixin Methods
+#set( $k = 0 )
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+#set( $k = $k + 1 )
+#set( $v = "_mixin$k" )
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+#foreach( $n in $z.messages( true ) )
+#if($n.isMsgDir($mc))
+#if(!$n.isHidden())
+#if(!$methodList.contains("_begin_end_$n.name().name()"))
+#set ( $addMethodListStatus = $methodList.add("_begin_end_$n.name().name()") )
+		// --- generated methods for $n.name() --- //
+
+#if(!$n.isOneway())
+		/**
+		 * Begins a call to ${n.name()}.
+		 *
+#foreach( $s in $n.descr() )
+		 * $s
+#end
+#foreach( $p in $n.iterator() )
+#set( $sep = "@param $p.name() " )
+#foreach( $s in $p.descr() )
+		 * $sep$s
+#set( $sep = "" )
+#end
+#end
+		 * @return mailbox used to retrieve the result using _end_${n.name()}.
+		 * @see $clname#${n.name()}
+		 * @see #_end_${n.name()}
+		 */
+		public final org.apache.etch.bindings.java.support.Mailbox _begin_${n.name()}(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+			$sep$helper.getTypeName( $p.type() ) $p.name()
+#set( $sep = ", " )
+#end
+		)
+		{
+			return ${v}._async._begin_${n.name()}(
+#set( $sep = "" )
+#foreach( $p in $n.iterator() )
+				$sep$p.name()
+#set( $sep = ", " )
+#end
+			);
+		}
+		
+		/**
+		 * Ends a call to ${n.name()}.
+		 *
+#foreach( $s in $n.descr() )
+		 * $s
+#end
+		 * @param mb mailbox returned by _begin_${n.name()}.
+#if( $n.hasReturn() )
+#set( $sep = "@return " )
+#foreach( $s in $n.returnDescr() )
+		 * $sep$s
+#set( $sep = "" )
+#end
+#end
+#foreach( $t in $n.thrown().iterator() )
+#set( $sep = "@throws $t.name() " )
+#foreach( $s in $t.descr() )
+		 * $sep$s
+#set( $sep = "" )
+#end
+#end
+		 *
+		 * @see $clname#${n.name()}
+		 * @see #_begin_${n.name()}
+		 */
+		public final $helper.getTypeName( $n.type() ) _end_${n.name()}( org.apache.etch.bindings.java.support.Mailbox mb )
+#if($n.thrown().iterator().hasNext())
+			throws
+#set( $sep = "" )
+#foreach($t in $n.thrown().iterator())
+				$sep$t.getNamed().fqname()
+#set( $sep = ", " )
+#end
+#end
+		{
+#if($n.hasReturn())
+			return
+#end
+			${v}._async._end_${n.name()}( mb );
+		}
+#end
+#end
+#end
+#end
+#end
+#end
+#end
+	}
+}
diff --git a/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/stub.vm b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/stub.vm
new file mode 100644
index 0000000..56609ed
--- /dev/null
+++ b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/stub.vm
@@ -0,0 +1,170 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created and should not be edited!
+#set($i = $intf.name())
+
+package $intf.parent().name();
+
+import org.apache.etch.util.core.Who;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.support.DeliveryService;
+import org.apache.etch.bindings.java.support.Pool;
+import org.apache.etch.bindings.java.support.StubHelper;
+import org.apache.etch.bindings.java.support._Etch_AuthException;
+#if (!$hasBaseClass)
+import org.apache.etch.bindings.java.support.StubBase;
+#end
+import org.apache.etch.bindings.java.support.Pool.PoolRunnable;
+#foreach( $n in $intf.iterator() )
+#if ($n.isExtern())
+#if ($n.hasImport( $helper ))
+import $n.getImport( $helper );
+#end
+#end
+#end
+
+#if ($hasBaseClass)
+/**
+ * Message to call translator for $i$suffix.
+ */
+@SuppressWarnings("unused")
+public class Stub$i$suffix extends Stub$i<$i$suffix>
+#set( $T = "$i$suffix" )
+#else
+/**
+ * Message to call translator for $i$suffix.
+ * @param <T> $i$suffix or a subclass thereof.
+ */
+@SuppressWarnings("unused")
+public class Stub$i$suffix<T extends $i$suffix> extends StubBase<T>
+#set( $T = "T" )
+#end
+{
+	/**
+	 * Stub for $i$suffix.
+	 * @param svc the delivery service.
+	 * @param obj the implementation of $i$suffix responsive to requests.
+	 * @param queued thread pool used to run AsyncMode.QUEUED methods.
+	 * @param free thread pool used to run AsyncMode.FREE methods.
+	 */
+	public Stub$i$suffix( DeliveryService svc, $T obj, Pool queued, Pool free )
+	{
+		super( svc, obj, queued, free );
+	}
+	
+	static
+	{
+#foreach( $n in $intf.iterator() )
+#if( $n.isMixin() )
+#set( $m = $n.getModule() )
+#set( $z = $m.iterator().next() )
+		${m.name()}.Stub${z.name()}${suffix}.init();
+#end
+#end
+	}
+
+	/**
+	 * Method used to force static initialization.
+	 */
+	public static void init()
+	{
+		// nothing to do.
+	}
+	
+	static
+	{
+#foreach( $mthd in $intf.iterator() )
+#if ($mthd.isMsgDir($mc))
+#if (!$mthd.isHidden())
+		ValueFactory$i.${mthd.vname( $helper )}.setStubHelper( new StubHelper<$i$suffix>()
+		{
+			public final void run( DeliveryService _svc, $i$suffix _obj, Who _sender, Message _msg ) throws Exception
+			{
+#if (!$mthd.isOneway())
+				final Message _rmsg = _msg.reply();
+#end
+				try
+				{
+#if ($mthd.hasAuth())
+#foreach ($param in $mthd.iterator())
+					$helper.getTypeName( $param.type() ) $param.name() = ($helper.getTypeName( $param.type() )) _msg.get( ValueFactory$i.$param.vname( $helper ) );
+#end
+#end
+#if ($mthd.hasAuth())
+#set( $auth = $mthd.getAuth() )
+#if ($auth.isMethodFalse())
+					if (true)
+#else
+					if (!_obj.${auth.method()}(
+#set( $sep = "" )
+#foreach($arg in $auth.args())
+#if ($arg.isLiteralConstant())
+						($helper.getNativeTypeName( $arg.type() )) ${sep}$helper.getTypeValue( $arg.type(), $arg.value() )
+#elseif ($arg.isParameter( $mthd ))
+						${sep}$helper.qualifyParameterName( $arg.value() )
+#elseif ($arg.isConstant( $intf ))
+						${sep}$helper.qualifyConstantName( $intf, $arg.value() )
+#elseif ($arg.isEnum( $intf ))
+						${sep}$helper.qualifyEnumName( $intf, $arg.value() )
+#else
+						${sep}null
+#end
+#set( $sep = ", " )
+#end
+					))
+#end
+					throw new _Etch_AuthException( "stub could not authorize $mthd.name() using $auth.method()" );
+#end
+#if ($mthd.hasReturn())
+					_rmsg.put( ValueFactory$i._mf_result,
+#end
+					_obj.$mthd.name()(
+#set( $sep = "" )
+#foreach ($param in $mthd.iterator())
+#if ($mthd.hasAuth())
+						${sep}$param.name()
+#else
+						${sep}($helper.getTypeName( $param.type() )) _msg.get( ValueFactory$i.$param.vname( $helper ) )
+#end
+#set( $sep = ", " )
+#end
+#if ($mthd.hasReturn())
+					)
+#end
+					);
+				}
+				catch ( Exception e )
+				{
+					sessionNotify( _obj, e );
+#if ($mthd.isOneway())
+					Message _rmsg = _msg.reply( _msg.vf().get_mt__exception() );
+#end
+					_rmsg.put( ValueFactory$i._mf_result, e );
+#if ($mthd.isOneway())
+					_svc.transportMessage( _sender, _rmsg );
+#end
+				}
+#if (!$mthd.isOneway())
+				_svc.transportMessage( _sender, _rmsg );
+#end
+			}
+		} );
+#end
+#end
+#end
+	}
+}
diff --git a/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/vf.vm b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/vf.vm
new file mode 100644
index 0000000..a3d2117
--- /dev/null
+++ b/binding-java/compiler/src/main/resources/org/apache/etch/bindings/java/compiler/vf.vm
@@ -0,0 +1,302 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created and should not be edited!
+
+package $intf.parent().name();
+
+import org.apache.etch.bindings.java.msg.AsyncMode;
+import org.apache.etch.bindings.java.msg.Direction;
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.TypeMap;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.DefaultValueFactory;
+
+#foreach( $n in $intf.iterator() )
+#if ($n.isExtern())
+#if ($n.hasImport( $helper ))
+import $n.getImport( $helper );
+#end
+#if ($n.hasSerializerImport( $helper ))
+import $n.getSerializerImport( $helper );
+#end
+#end
+#end
+
+#set( $vf = "ValueFactory$intf.name()" )
+/**
+ * ValueFactory for $intf.name().
+ */
+@SuppressWarnings("unused")
+public final class ${vf} extends DefaultValueFactory
+{
+	/**
+	 * Constructs ${vf}.
+	 * @param uri the uri used to configure the session.
+	 */
+	public ${vf}( String uri )
+	{
+		super( uri, types, class2type );
+#foreach ( $n in $intf.iterator() )
+#if ($n.isMixin())
+#set( $m = $n.getModule() )
+#set( $s = $m.iterator().next() )
+		addMixin( new ${m.name()}.ValueFactory${s.name()}( uri ) );
+#end
+#end
+	}
+	
+	private final static TypeMap types = new TypeMap();
+	
+	private final static Class2TypeMap class2type = new Class2TypeMap();
+
+	static
+	{
+		DefaultValueFactory.init( types, class2type );
+		initTypes();
+		initResults();
+		initFields();
+		initParams();
+	}
+#foreach ( $n in $intf.iterator() )
+#if ($n.isEnumx() || $n.isStruct() || $n.isExtern() || $n.isExcept() || $n.isMessage())
+
+	/** Type for $n.fqname() */
+	public static Type ${n.vname( $helper )};
+#end
+#end
+
+	private static void initTypes()
+	{
+#foreach ( $n in $intf.iterator() )
+#if ($n.isEnumx() || $n.isStruct() || $n.isExtern() || $n.isExcept() || $n.isMessage())
+		${n.vname( $helper )} = types.get( "$n.fqname()" );
+#end
+#end
+	}
+
+	private static void initResults()
+	{
+#foreach ( $n in $intf.iterator() )
+#if ($n.isMessage())
+		${n.vname( $helper )}.setDirection( Direction.$n.msgDir() );
+#if (!$n.isHidden())
+#if ($n.isQueuedAsyncReceiver())
+		${n.vname( $helper )}.setAsyncMode( AsyncMode.QUEUED );
+#elseif ($n.isFreeAsyncReceiver())
+		${n.vname( $helper )}.setAsyncMode( AsyncMode.FREE );
+#else
+		${n.vname( $helper )}.setAsyncMode( AsyncMode.NONE );
+#end
+#if (!$n.isOneway())
+#set( $r = $n.getResultMessage() )
+		${n.vname( $helper )}.setResult( $r.vname( $helper ) );
+		${r.vname( $helper )}.setTimeout( $n.getTimeout() );
+#end
+#end
+#end
+#end
+	}
+## ----------------------------- import / export -----------------------------
+#foreach ( $n in $intf.iterator() )
+#if ($n.isStruct() || $n.isExcept())
+#set( $tname = $n.efqname( $helper ) )
+
+	static
+	{
+		class2type.put( ${tname}.class, ${n.vname( $helper )} );
+		${n.vname( $helper )}.setComponentType( ${tname}.class );
+#if ($n.hasExtends())
+		${n.vname( $helper )}.setSuperType( $n.getExtends().vname( $helper ) );
+#end
+		${n.vname( $helper )}.setImportExportHelper( new ImportExportHelper()
+		{
+			public final StructValue exportValue( ValueFactory vf, Object value )
+			{
+				StructValue struct = new StructValue( ${n.vname( $helper )}, vf );
+				$tname v = ($tname) value;
+#foreach( $p in $n.getAllParameters() )
+				struct.put( $p.vname( $helper ), v.$p.name() );
+#end
+				return struct;
+			}
+
+			public final Object importValue( StructValue struct )
+			{
+				$tname v = new ${tname}();
+#foreach ($p in $n.getAllParameters())
+				v.$p.name() = ($helper.getTypeName( $p.type() )) struct.get( $p.vname( $helper ) );
+#end
+				return v;
+			}
+		} );
+	}
+#elseif ($n.isExtern())
+#set( $tname = $n.efqname( $helper ) )
+#elseif ($n.isEnumx())
+#set( $tname = $n.efqname( $helper ) )
+
+	static
+	{
+		class2type.put( ${tname}.class, ${n.vname( $helper )} );
+		${n.vname( $helper )}.setComponentType( ${tname}.class );
+		${n.vname( $helper )}.setImportExportHelper( new ImportExportHelper()
+		{
+			public final StructValue exportValue( ValueFactory vf, Object value )
+			{
+				StructValue struct = new StructValue( ${n.vname( $helper )}, vf );
+				${tname} v = (${tname}) value;
+				switch (v)
+				{
+#foreach ($p in $n.iterator())
+					case $p.name(): struct.put( $p.vname( $helper ), true ); break;
+#end
+				}
+				return struct;
+			}
+
+			public final Object importValue( StructValue struct )
+			{
+				// if empty, it likely means that a null value was sent
+				// or an unknown key (from a different rev of the service).
+				if (struct.isEmpty())
+					return null;
+				
+				// there should only be a single key, so take the first one
+				Field key = struct.keySet().iterator().next();
+#foreach ($p in $n.iterator())
+				if (key == $p.vname( $helper )) return ${tname}.$p.name();
+#end
+
+				// a known key was sent, but it did not match any defined
+				// key for this type.
+				return null;
+			}
+		} );
+	}
+#end
+#end
+## ----------------------------- fields -----------------------------
+#set( $x = $params.clear() )
+## standard params from DefaultValueFactory
+#set( $x = $params.add( "msg" ) )
+#set( $x = $params.add( "result" ) )
+#foreach( $n in $intf.iterator() )
+#if ($n.isEnumx() || $n.isStruct() || $n.isExcept() || $n.isMessage())
+#foreach( $param in $n.iterator() )
+#if (!$params.contains($param.name().name()))
+#set( $x = $params.add($param.name().name()) )
+
+	/** Field for $param.name().name() */
+	public static Field $param.vname( $helper );
+#end
+#end
+#end
+#end
+
+	private static void initFields()
+	{
+#set( $x = $params.clear() )
+## standard params from DefaultValueFactory
+#set( $x = $params.add( "msg" ) )
+#set( $x = $params.add( "result" ) )
+#foreach( $n in $intf.iterator() )
+#if ($n.isEnumx() || $n.isStruct() || $n.isExcept() || $n.isMessage())
+#foreach( $param in $n.iterator() )
+#if (!$params.contains($param.name().name()))
+#set( $x = $params.add($param.name().name()) )
+		$param.vname( $helper ) = new Field( "$param.name().name()" );
+#end
+#end
+#end
+#end
+
+#foreach ( $n in $intf.iterator() )
+#if ($n.isMessage())
+#if (!$n.isHidden())
+#if (!$n.isOneway())
+#set( $r = $n.getResultMessage() )
+		${r.vname( $helper )}.setResponseField( _mf_result );
+#end
+#end
+#end
+#end
+	}
+	
+	static
+	{
+		// initialize the extern serializers:
+#foreach( $n in $intf.iterator() )
+#if ($n.isExtern())
+		${n.sname( $helper )}.init( ${n.vname( $helper )}, class2type );
+#end
+#end
+	}
+
+#set( $ctr = 0 )
+	private static void initParams()
+	{
+#foreach( $n in $intf.iterator() )
+#if ($n.isEnumx() || $n.isStruct() || $n.isExcept() || $n.isMessage())
+#if ($ctr > 0 && $ctr % 100 == 0)
+
+		initParams${ctr}();
+	}
+	
+	private static void initParams${ctr}()
+	{
+#end
+#set( $ctr = $ctr + 1 )
+
+		// params for $n.name()
+#if ($n.isStruct() || $n.isExcept())
+#foreach( $param in $n.getAllParameters() )
+		${n.vname( $helper )}.putValidator( $param.vname( $helper ), org.apache.etch.bindings.java.support.$helper.getValidator( $param ) );
+#end
+#else
+#foreach( $param in $n.iterator() )
+		${n.vname( $helper )}.putValidator( $param.vname( $helper ), org.apache.etch.bindings.java.support.$helper.getValidator( $param ) );
+#end
+#end
+#if ($n.isMessage())
+		${n.vname( $helper )}.putValidator( _mf__messageId, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+#if ($n.isHidden())
+#set( $param = $n.getResultParam() )
+#set( $reqMsg = $n.getRequestMessage() )
+#foreach( $t in $reqMsg.thrown().iterator() )
+		${n.vname( $helper )}.putValidator( $param.vname( $helper ), org.apache.etch.bindings.java.support.$helper.getValidator( $t ) ); // thrown $t.name()
+#end
+		${n.vname( $helper )}.putValidator( $param.vname( $helper ), org.apache.etch.bindings.java.support.Validator_RuntimeException.get() ); // thrown RuntimeException
+		${n.vname( $helper )}.putValidator( _mf__inReplyTo, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+#end
+#end
+#end
+#end
+	}
+	
+	static
+	{
+		// done updating types, and class2type: lock them.
+		types.lock();
+		for (Type t: types.values())
+			t.lock();
+		class2type.lock();
+	}
+}
diff --git a/binding-java/runtime/build.xml b/binding-java/runtime/build.xml
new file mode 100644
index 0000000..6c90e2a
--- /dev/null
+++ b/binding-java/runtime/build.xml
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-java-runtime" basedir="." default="help">
+    <description>Etch-to-Java runtime binding implementation</description>
+    <property name="Etch.basedir" location="${basedir}/../.." />
+    <import file="${Etch.basedir}/build-support/etch.includes.xml" />
+
+    <!-- Static properties of the sub-project -->
+    <property name="proj"                 location="${Etch.basedir}/binding-java/runtime" />
+    <property name="target"               location="${proj}/target" />
+    <property name="src"                  location="${proj}/src" />
+    <property name="generatedSrc"         location="${target}/generated-sources" />
+    <property name="classesDirectory"     location="${target}/classes" />
+    <property name="resourcesDirectory"   location="${target}/resources" />
+    <property name="testResultsDirectory" location="${target}/test-results" />
+
+    <!-- MACRO: init-target -->
+    <macrodef name="init-target" >
+        <sequential>
+            <delete dir="${classesDirectory}"   failonerror="false" quiet="true" />
+            <delete dir="${resourcesDirectory}" failonerror="false" quiet="true" />
+            <mkdir dir="${classesDirectory}" />
+            <mkdir dir="${classesDirectory}/main" />
+            <mkdir dir="${classesDirectory}/test" />
+            <mkdir dir="${resourcesDirectory}" />
+        </sequential>
+    </macrodef>
+
+    <!-- MACRO: compile-sources -->
+    <macrodef name="compile-sources" >
+        <attribute name="support" default="${Etch.support}" />
+        <sequential>
+
+            <javac  debug="${Etch.javac.debug}"
+                    target="1.5"
+                    optimize="${Etch.javac.optimize}"
+                    destdir="${classesDirectory}/main" >
+                <src path="${src}/main/java" />
+                <exclude name="**/.svn/**" />
+                <classpath refid="Etch.dependencies.jar.paths" />
+                <classpath>
+                    <pathelement location="@{support}/lib/${etch-util.jar}" />
+                </classpath>
+            </javac>
+
+            <javac  debug="${Etch.javac.debug}"
+                    target="1.5"
+                    optimize="${Etch.javac.optimize}"
+                    destdir="${classesDirectory}/test" >
+                <src path="${src}/test/java" />
+                <exclude name="**/.svn/**" />
+                <classpath refid="Etch.dependencies.jar.paths" />
+                <classpath>
+                    <pathelement location="${classesDirectory}/main" />
+                    <pathelement location="@{support}/lib/${etch-util.jar}" />
+                </classpath>
+            </javac>
+
+        </sequential>
+    </macrodef>
+
+    <!-- MACRO: bundle-jars -->
+    <macrodef name="bundle-jars" >
+        <attribute name="dist" default="${Etch.dist}" />
+        <sequential>
+            <mkdir dir="@{dist}/lib" />
+
+            <!-- CREATE jars -->
+
+            <!-- Package up etch-java-runtime jar -->
+            <jar jarfile="@{dist}/lib/${etch-java-runtime.jar}" >
+                <manifest>
+                    <attribute name="Copyright"    value="${Etch.copyrightNotice}" />
+                    <attribute name="Version"      value="${Etch.version}" />
+                    <attribute name="LongVersion"  value="${Etch.longversion}" />
+                    <attribute name="Build-Tag"    value="${Etch.buildTag}" />
+                    <attribute name="SVN-Revision" value="${Etch.runtime.revisionNumber}" />
+                    <!-- <attribute name="Class-Path"   value="${etch-util.jar}" /> -->
+                </manifest>
+                <metainf dir="${Etch.basedir}" >
+                    <include name="NOTICE.txt" />
+                    <include name="LICENSE.txt" />
+                </metainf>
+                <fileset dir="${classesDirectory}/main">
+                    <include name="org/apache/etch/bindings/**" />
+                </fileset>
+            </jar>
+
+            <!-- placeholder -->
+            <jar jarfile="@{dist}/lib/${etch-util.jar}" update="true" filesetmanifest="merge">
+               <manifest>
+                  <attribute name="Version" value="${Etch.version}" />
+               </manifest>   
+            </jar>
+
+            <!-- CREATE source archives -->
+
+            <!-- package up etch-java-runtime src -->
+            <zip destfile="@{dist}/lib/${etch-java-runtime-src.zip}" >
+                <fileset dir="${src}/main/java" >
+                    <include name="org/apache/etch/bindings/**/*.java" />
+                </fileset>
+            </zip>
+            
+            <mkdir dir="${target}/empty-dir" />
+            <zip destfile="@{dist}/lib/${etch-util-src.zip}" update="true" whenempty="create" basedir="${target}/empty-dir"/>
+
+        </sequential>
+    </macrodef>
+    
+    <!-- MACRO: update-jars -->
+    <macrodef name="update-jars" >
+        <attribute name="dist" default="${Etch.dist}" />
+        <attribute name="support" default="${Etch.support}" />
+        <sequential>
+            <!-- repackage .jar -->
+            <mkdir dir="@{dist}/lib" />
+            <delete dir="${target}/tmp-runtime"  quiet="true" />
+            <mkdir dir="${target}/tmp-runtime" />
+
+            <unjar src="@{support}/lib/${etch-util.jar}"     dest="${target}/tmp-runtime" />
+            <unjar src="@{support}/lib/${etch-java-runtime.jar}" dest="${target}/tmp-runtime" />
+
+            <jar jarfile="@{dist}/lib/${etch-java-runtime.jar}" update="true" filesetmanifest="merge" >
+                <fileset dir="${target}/tmp-runtime"  />
+            </jar>
+            
+            <!-- repackage .zip src -->
+            <mkdir dir="@{dist}/lib" />
+            <delete dir="${target}/tmp-runtime-src"  quiet="true" />
+            <mkdir dir="${target}/tmp-runtime-src" />
+            
+            <unzip src="@{support}/lib/${etch-util-src.zip}" dest="${target}/tmp-runtime-src" />
+            <unzip src="@{support}/lib/${etch-java-runtime-src.zip}" dest="${target}/tmp-runtime-src" />
+            
+            <zip destfile="@{dist}/lib/${etch-java-runtime-src.zip}" >
+                <fileset dir="${target}/tmp-runtime-src" />
+            </zip>
+            
+        </sequential>
+    </macrodef>
+
+    <!-- INIT TARGET -->
+    <!-- Modify this target to define project specific properties that can only be set at runtime -->
+    <target name="do-init">
+        <delete dir="${target}" failonerror="false" quiet="true" />
+
+        <mkdir dir="${target}" />
+        <mkdir dir="${generatedSrc}" />
+        <mkdir dir="${classesDirectory}" />
+        <mkdir dir="${resourcesDirectory}" />
+        <mkdir dir="${testResultsDirectory}" />
+    </target>
+
+    <!-- CLEAN TARGET -->
+    <target name="do-clean">
+        <delete dir="${target}" />
+    </target>
+
+    <!-- BUILD TARGET -->
+
+    <target name="generate-sources" >
+    </target>
+
+    <target name="compile-for-dist" >
+        <!-- Initialize target directories -->
+        <init-target />
+
+        <!-- Compile Source -->
+        <compile-sources support="${Etch.support}" />
+
+        <!-- Bundle Jars -->
+        <bundle-jars dist="${Etch.support}" />
+        
+        <!-- Update Jars -->
+        <update-jars dist="${Etch.dist}" support="${Etch.support}" />
+    </target>
+
+    <target name="compile-for-clover" if="Clover.enabled" >
+
+        <echo message="Rebuilding with clover" />
+
+        <!-- initialize-clover -->
+        <initialize-clover suffix="etchjavabinding" >
+            <fileset dir="${src}/main/java">
+                <exclude name="**/.svn/**" />                
+                <include name="**/*.java" />
+            </fileset>
+            <testsources dir="${src}/test/java">
+                <exclude name="**/.svn/**" />                
+                <include name="**/*.java" />
+            </testsources>
+        </initialize-clover>
+
+        <!-- Initialize target directories -->
+        <init-target />
+
+        <!-- Compile Source -->
+        <compile-sources support="${Etch.support}" />
+
+        <!-- Bundle Jars -->
+        <bundle-jars dist="${Etch.clover-support}" />
+        
+        <!-- Update Jars -->
+        <update-jars dist="${Etch.clover-dist}" support="${Etch.clover-support}" />
+
+    </target>
+
+    <target name="do-build" depends="generate-sources,compile-for-dist,compile-for-clover" />
+
+    <!-- TEST TARGET -->
+    <target name="do-test">
+
+        <!-- Run Unit Tests -->
+        <junit printsummary="yes" haltonfailure="no" dir="${classesDirectory}"
+            errorProperty="build.tests.fail" failureProperty="build.tests.fail">
+            <classpath>
+                <pathelement location="${classesDirectory}/main" />
+                <pathelement location="${classesDirectory}/test" />
+                <pathelement location="${Etch.dependency.junit.jar}"/>
+                <!-- TODO: remove if clover not available -->
+                <pathelement location="${Etch.SUPPORT}/lib/${etch-util.jar}" />
+                <pathelement location="${Etch.dependency.clover.jar}"/>
+            </classpath>
+            <formatter type="xml"/>
+            <batchtest fork="true" todir="${testResultsDirectory}">
+                <fileset dir="${src}/test/java">
+                    <exclude name="**/.svn/**" />                    
+                    <include name="**/*.java" />
+                </fileset>
+            </batchtest>
+        </junit>
+    </target>
+
+    <!-- POSTBUILD TARGET -->
+    <target name="do-postbuild">
+    </target>
+
+    <target name="do-publish" if="build.tests.fail">
+        <!-- Set flag file if any tests failed -->
+        <touch file="${Etch.runtime.tests.fail}"/>
+    </target>
+
+</project>
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/AsyncMode.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/AsyncMode.java
new file mode 100644
index 0000000..bfe1db7
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/AsyncMode.java
@@ -0,0 +1,34 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+/**
+ * The asynchronous receiver mode of this helper.
+ */
+public enum AsyncMode
+{
+	/** synchronous mode */
+	NONE,
+	/** the operation is queued to a thread pool for execution */
+	QUEUED,
+	/** the operation is executed by a newly allocated thread */
+	FREE
+}
\ No newline at end of file
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/ComboValidator.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/ComboValidator.java
new file mode 100644
index 0000000..de0e6ad
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/ComboValidator.java
@@ -0,0 +1,116 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+/**
+ * Validates values using one of two validators.
+ */
+public class ComboValidator implements Validator
+{
+	/**
+	 * Constructs the ComboValidator.
+	 *
+	 * @param a
+	 * @param b
+	 */
+	public ComboValidator( Validator a, Validator b )
+	{
+		this.a = a;
+		this.b = b;
+	}
+	
+	private final Validator a;
+	
+	private final Validator b;
+	
+	@Override
+	public String toString()
+	{
+		return String.format( "(%s OR %s)", a, b );
+	}
+
+	public Validator elementValidator()
+	{
+		Validator na;
+		try
+		{
+			na = a.elementValidator();
+		}
+		catch ( IllegalArgumentException e )
+		{
+			na = null;
+		}
+		
+		Validator nb;
+		try
+		{
+			nb = b.elementValidator();
+		}
+		catch ( IllegalArgumentException e )
+		{
+			nb = null;
+		}
+		
+		if (na == null && nb == null)
+			throw new IllegalArgumentException( "na == null && nb == null" );
+		
+		if (na == null)
+			return nb;
+		
+		if (nb == null)
+			return na;
+		
+		return new ComboValidator( na, nb );
+	}
+
+	public boolean validate( Object value )
+	{
+		return a.validate( value ) || b.validate( value );
+	}
+
+	public Object validateValue( Object value )
+	{
+		try
+		{
+			return a.validateValue( value );
+		}
+		catch (IllegalArgumentException e )
+		{
+			return b.validateValue( value );
+		}
+	}
+
+	/**
+	 * @return the "a" child of this validator.
+	 */
+	public Validator a()
+	{
+		return a;
+	}
+
+	/**
+	 * @return the "b" child of this validator.
+	 */
+	public Validator b()
+	{
+		return b;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/Direction.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/Direction.java
new file mode 100644
index 0000000..b26b3b0
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/Direction.java
@@ -0,0 +1,36 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+/**
+ * The direction of a message.
+ */
+public enum Direction
+{
+	/** Message is both toward client and toward server. */
+	BOTH,
+	
+	/** Message is toward server. */
+	SERVER,
+	
+	/** Message is toward client. */
+	CLIENT
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/Field.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/Field.java
new file mode 100644
index 0000000..8b29d9c
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/Field.java
@@ -0,0 +1,48 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+/**
+ * Field is an IdName which denotes a field of a struct
+ * or message (i.e., a key for a value).
+ */
+public final class Field extends IdName
+{
+	/**
+	 * Constructs the Field.
+	 * @param id the id of the field.
+	 * @param name the name of the field.
+	 */
+	public Field( int id, String name )
+	{
+		super( id, name );
+	}
+
+	/**
+	 * Constructs the Field, computing the appropriate value
+	 * for the id.
+	 * @param name the name of the field.
+	 */
+	public Field( String name )
+	{
+		super( name );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/FieldMap.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/FieldMap.java
new file mode 100644
index 0000000..7746613
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/FieldMap.java
@@ -0,0 +1,33 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+/**
+ * FieldMap is a IdNameMap for Field.
+ */
+public final class FieldMap extends IdNameMap<Field>
+{
+	@Override
+	public Field makeNew( String name )
+	{
+		return new Field( name );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/IdName.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/IdName.java
new file mode 100644
index 0000000..b23a858
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/IdName.java
@@ -0,0 +1,107 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+import org.apache.etch.util.Hash;
+
+/**
+ * An IdName is a base class for Field or Type. It is used
+ * to bind together a type or field name with the associated id. The id
+ * is used for certain operations, such as the key in a Map, comparisons,
+ * and binary encoding on the wire, while the name is used for display.
+ * 
+ * @see Field
+ * @see Type
+ */
+public class IdName extends Hash
+{
+	/**
+	 * Constructs the IdName.
+	 * @param id the id for the name (normally computed using
+	 * {@link #hash(String)})
+	 * @param name the name of the item.
+	 */
+	public IdName( Integer id, String name )
+	{
+		this.id = id;
+		this.name = name;
+	}
+	
+	/**
+	 * Constructs the IdName by computing the appropriate id given
+	 * the name.
+	 * @param name the name of the item.
+	 * @see #hash(String)
+	 */
+	public IdName( String name )
+	{
+		this( hash( name ), name );
+	}
+	
+	private final Integer id;
+	
+	private final String name;
+	
+	/**
+	 * @return the id of the item.
+	 */
+	public final Integer getId()
+	{
+		return id;
+	}
+	
+	/**
+	 * @return the name of the item.
+	 */
+	public final String getName()
+	{
+		return name;
+	}
+	
+	@Override
+	public final String toString()
+	{
+		return String.format( "%s(%d)", name, id );
+	}
+
+	@Override
+	public final boolean equals( Object obj )
+	{
+		if (obj == this)
+			return true;
+		
+		if (obj == null)
+			return false;
+		
+		if (getClass() != obj.getClass())
+			return false;
+		
+		IdName other = (IdName) obj;
+		
+		return id.equals( other.id ) && name.equals( other.name );
+	}
+
+	@Override
+	public final int hashCode()
+	{
+		return id.hashCode() ^ name.hashCode();
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/IdNameMap.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/IdNameMap.java
new file mode 100644
index 0000000..758fc7e
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/IdNameMap.java
@@ -0,0 +1,149 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * Map by id and name of IdNames (or subclasses thereof).
+ * @param <T> the specific subclass of IdName that is in the map.
+ */
+abstract public class IdNameMap<T extends IdName>
+{
+	/**
+	 * Constructs the IdNameMap.
+	 */
+	public IdNameMap()
+	{
+		// nothing to do.
+	}
+	
+	/**
+	 * Gets the IdName subclass which corresponds to the specified id.
+	 * @param id the id of an IdName.
+	 * @return the IdName subclass found.
+	 */
+	public final T get( Integer id )
+	{
+		return byId.get( id );
+	}
+	
+	/**
+	 * Gets the IdName subclass which corresponds to the specified
+	 * name, or creates it if it isn't found and if this map is not
+	 * locked.
+	 * @param name the name of an IdName.
+	 * @return the IdName subclass found or created.
+	 * @see #lock()
+	 */
+	public final T get( String name )
+	{
+		T t = byName.get( name );
+		if (t == null && !locked)
+			t = add( makeNew( name ) );
+		return t;
+	}
+	
+	/**
+	 * Adds the IdName subclass to the map.
+	 * 
+	 * @param t the IdName subclass to add.
+	 * 
+	 * @return the IdName from the map.
+	 * 
+	 * @throws IllegalStateException if locked.
+	 * @throws IllegalArgumentException if there is a collision with an
+	 * existing entry by id or name.
+	 */
+	public T add( T t )
+	{
+		if (locked)
+			throw new IllegalStateException( "locked" );
+		
+		if (byId.containsKey( t.getId() ))
+			throw new IllegalArgumentException( "id collision: "+t );
+
+		if (byName.containsKey( t.getName() ))
+			throw new IllegalArgumentException( "name collision: "+t );
+		
+		byId.put( t.getId(), t );
+		byName.put( t.getName(), t );
+		return t;
+	}
+
+	/**
+	 * Adds all the IdNames to this IdNameMap.
+	 * @param ts
+	 * @throws IllegalStateException if locked.
+	 * @throws IllegalArgumentException if there is a collision with an
+	 * existing entry by id or name.
+	 */
+	public void addAll( IdNameMap<T> ts )
+	{
+		if (locked)
+			throw new IllegalStateException( "locked" );
+		
+		for (T t: ts.byId.values())
+			add( t );
+	}
+
+	/**
+	 * @return a new set which is a snapshot of all the values.
+	 */
+	public final Set<T> values()
+	{
+		return new HashSet<T>( byId.values() );
+	}
+
+	/**
+	 * Locks the map preventing further changes.
+	 */
+	public final void lock()
+	{
+		locked = true;
+	}
+
+	/**
+	 * @return the number of values in the map.
+	 */
+	public int size()
+	{
+		return byId.size();
+	}
+	
+	/**
+	 * Makes a new subclass of IdName to put in this map.
+	 * @param name the name of the new subclass of IdName.
+	 * @return a newly constructed subclass of IdName to put in
+	 * this map.
+	 */
+	abstract public T makeNew( String name );
+	
+	private final Map<Integer, T> byId = new HashMap<Integer, T>();
+	
+	private final Map<String, T> byName = new HashMap<String, T>();
+	
+	private boolean locked;
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/ImportExportHelper.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/ImportExportHelper.java
new file mode 100644
index 0000000..6399b78
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/ImportExportHelper.java
@@ -0,0 +1,43 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+/**
+ * Interface used to implement ValueFactory based import / export code
+ * for service defined types.
+ */
+public interface ImportExportHelper
+{
+	/**
+	 * Exports a value by creating an equivalent StructValue.
+	 * @param vf the value factory for this connection.
+	 * @param value a service defined type to export.
+	 * @return a StructValue representing the exported value.
+	 */
+	public StructValue exportValue( ValueFactory vf, Object value );
+
+	/**
+	 * Imports a value from an equivalent StructValue.
+	 * @param struct a StructValue representing the exported value.
+	 * @return a service defined type.
+	 */
+	public Object importValue( StructValue struct );
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/Message.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/Message.java
new file mode 100644
index 0000000..8a18e01
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/Message.java
@@ -0,0 +1,137 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+/**
+ * A message is modeled as a command and some argments. The command is an arbitrary
+ * integer value, and the arguments are key / value pairs, where the
+ * key is an arbitrary integer value and the value is any one of the
+ * standard java objects, an ArrayValue, a StructValue, or any type
+ * which may be serialized by the ValueFactory.
+ */
+public final class Message extends StructValue
+{
+	/**
+	 * A bogus serial version uid.
+	 */
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * Constructs the Message with default length.
+	 *
+	 * @param type the type of the message (command).
+	 * @param vf the value factory.
+	 */
+	public Message( Type type, ValueFactory vf )
+	{
+		super( type, vf );
+		this.vf = vf;
+	}
+
+	/**
+	 * Constructs the Message.
+	 *
+	 * @param type the type of the message (command).
+	 * @param vf the value factory.
+	 * @param length the number of name / value pairs expected. 0 means use
+	 * default.
+	 */
+	public Message( Type type, ValueFactory vf, int length )
+	{
+		super( type, vf, length );
+		this.vf = vf;
+	}
+
+	private final ValueFactory vf;
+	
+	/**
+	 * @return the value factory.
+	 */
+	public ValueFactory vf()
+	{
+		return vf;
+	}
+
+	/**
+	 * Creates a message which is a reply to the current message.
+	 * The current message's value factory is copied to the new
+	 * message. The message-id of the current message (if any) is
+	 * copied into the in-reply-to field of the new message.
+	 * @param rType the type of the reply.
+	 * @return a reply message.
+	 */
+	public Message reply( Type rType )
+    {
+	    Message rmsg = new Message( rType, vf );
+	    rmsg.setInReplyTo( getMessageId() );
+	    return rmsg;
+    }
+	
+	/**
+	 * @return a message which is the appropriate reply to this message.
+	 */
+	public Message reply()
+	{
+	    Message rmsg = new Message( type().getResult(), vf );
+	    rmsg.setInReplyTo( getMessageId() );
+	    return rmsg;
+	}
+
+	/**
+	 * @return the connection specific unique identifier of this
+	 * message, or null if there was no such identifier.
+	 */
+	public Long getMessageId()
+    {
+	    return vf.getMessageId( this );
+    }
+	
+	/**
+	 * Sets the message-id field of this message.
+	 * @param msgid the connection specific unique identifier of this
+	 * message. Null if the message has not been sent yet. NOTE: the
+	 * send process overwrites any value the user might set here. So
+	 * don't bother trying to set it.
+	 */
+	public void setMessageId( Long msgid )
+	{
+		vf.setMessageId( this, msgid );
+	}
+	
+	/**
+	 * @return the message-id of the message that this is a response to.
+	 * Null if this is an original message or if the original message did
+	 * not have a message-id.
+	 */
+	public Long getInReplyTo()
+	{
+		return vf.getInReplyTo( this );
+	}
+	
+	/**
+	 * Sets the in-reply-to field of this message.
+	 * @param msgid the message-id of the message that this is a response to.
+	 */
+	public void setInReplyTo( Long msgid )
+	{
+		vf.setInReplyTo( this, msgid );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/StructValue.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/StructValue.java
new file mode 100644
index 0000000..fe427c5
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/StructValue.java
@@ -0,0 +1,159 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.etch.bindings.java.msg.Validator.Level;
+
+
+/**
+ * A typed map of key/value pairs, where the type is a Type,
+ * each key is a Field, and each value is of arbitrary type
+ * chosen from the basic java types boolean, byte, short, int, long,
+ * float, double, String, an array of those, the extended types
+ * ArrayValue and StructValue, and specific types supported by
+ * ValueFactory.
+ * 
+ * StructValue is not protected against concurrent access.
+ */
+public class StructValue extends HashMap<Field, Object>
+	implements Iterable<Map.Entry<Field, Object>>
+{
+	/**
+	 * A bogus serial version uid.
+	 */
+	private static final long serialVersionUID = 1L;
+
+	// magic number 6 results in super( 8 ) in HashMap constructor.
+	private final static int DEFAULT_SIZE = 8;
+	
+	/**
+	 * Constructs the StructValue with default length.
+	 * 
+	 * @param type the type of the struct.
+	 * @param vf the value factory.
+	 */
+	public StructValue( Type type, ValueFactory vf )
+	{
+		this( type, vf, 0 );
+	}
+	
+	/**
+	 * Constructs the StructValue.
+	 * 
+	 * @param type the type of the struct.
+	 * @param vf the value factory.
+	 * @param length the number of name / value pairs expected. 0 means use
+	 * default.
+	 */
+	public StructValue( Type type, ValueFactory vf, int length )
+	{
+		super( length > 0 ? (length*4+2)/3 : DEFAULT_SIZE );
+		
+		if (type == null)
+			throw new IllegalArgumentException( "type == null" );
+		
+		this.type = type;
+		level = vf.getLevel();
+	}
+
+	private final Type type;
+	
+	private final Level level;
+	
+	/**
+	 * @return the struct type.
+	 */
+	public Type type()
+	{
+		return type;
+	}
+	
+	/**
+	 * @return validation level.
+	 */
+	public Level level()
+	{
+		return level;
+	}
+
+	/**
+	 * Compares the type of this struct to another type.
+	 * @param otherType the type to compare this type to.
+	 * @return true if this struct is of the specified type.
+	 */
+	public boolean isType( Type otherType )
+	{
+		return type.equals( otherType );
+	}
+
+	/**
+	 * Checks a struct for having the expected type.
+	 * @param expectedType the expected type of this struct.
+	 * @throws IllegalArgumentException if the type is not as expected.
+	 */
+	public void checkType( Type expectedType )
+	{
+		if (!isType( expectedType ))
+			throw new IllegalArgumentException();
+	}
+	
+	/**
+	 * @return an iterator over the entry set (key/value pairs) of this struct.
+	 * @see java.util.Map.Entry
+	 */
+	public final Iterator<Map.Entry<Field, Object>> iterator()
+	{
+		return entrySet().iterator();
+	}
+	
+	@Override
+	final public Object put( Field key, Object value )
+	{
+		if (value == null)
+			return remove( key );
+		
+		if (level != Level.NONE)
+		{
+		    Validator v = type.getValidator( key );
+		    
+		    if (level == Level.FULL && v == null)
+		    	throw new IllegalArgumentException( String.format(
+		    		"validator missing for type %s field %s", type, key ) );
+		    
+		    if (v != null && !v.validate( value ))
+		    	throw new IllegalArgumentException( String.format(
+		    		"validator %s failed for type %s field %s: value %s",
+		    		v, type, key, value ) );
+		}
+		
+	    return super.put( key, value );
+	}
+	
+	@Override
+	public String toString()
+	{
+		return String.format( "%s: %s", type, super.toString() );
+	}
+}
\ No newline at end of file
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/Type.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/Type.java
new file mode 100644
index 0000000..c67c91a
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/Type.java
@@ -0,0 +1,371 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Type denotes the type of a struct or message. When used with a
+ * message it typically denotes an action or event.
+ */
+public final class Type extends IdName
+{
+	/**
+	 * Constructs the Type.
+	 * @param id the id of the type.
+	 * @param name the name of the type.
+	 */
+	public Type( int id, String name )
+	{
+		super( id, name );
+	}
+
+	/**
+	 * Constructs the Type, computing the appropriate value
+	 * for the id.
+	 * @param name the name of the type.
+	 */
+	public Type( String name )
+	{
+		super( name );
+	}
+
+	/**
+	 * @param key
+	 * @return the validator for this key of this type.
+	 */
+	public Validator getValidator( Field key )
+    {
+	    return validators.get( key );
+    }
+	
+	/**
+	 * Adds the validator to the chain for this key.
+	 * @param key
+	 * @param vldtr
+	 */
+	public void putValidator( Field key, Validator vldtr )
+	{
+		checkNotLocked();
+		
+		if (vldtr == null)
+			return;
+		
+		if (fields.get( key.getId() ) == null)
+			addField( key );
+
+		Validator v = validators.get( key );
+		if (v != null)
+			validators.put( key, new ComboValidator( v, vldtr ) );
+		else
+			validators.put( key, vldtr );
+	}
+
+	/**
+	 * Removes the validator chain for this key.
+	 * @param key
+	 */
+	public void clearValidator( Field key )
+    {
+		checkNotLocked();
+	    validators.remove( key );
+    }
+	
+	private final Map<Field, Validator> validators = new HashMap<Field, Validator>();
+	
+	/**
+	 * @return the result message type of this message type.
+	 */
+	public Type getResult()
+	{
+		return rType;
+	}
+
+	/**
+	 * Sets the result message type of this message type.
+	 * @param rType
+	 */
+	public void setResult( Type rType )
+	{
+		checkNotLocked();
+		this.rType = rType;
+	}
+	
+	private Type rType;
+
+	/**
+	 * @return the associated import / export helper.
+	 */
+	public ImportExportHelper getImportExportHelper()
+	{
+		return helper;
+	}
+	
+	/**
+	 * Sets the associated import / export helper.
+	 * @param helper
+	 */
+	public void setImportExportHelper( ImportExportHelper helper )
+	{
+		checkNotLocked();
+		this.helper = helper;
+	}
+	
+	private ImportExportHelper helper;
+
+	/**
+	 * @return the associated component type for an array of this type.
+	 * This type is not used when de-serializing the array components,
+	 * just when allocating the array itself.
+	 */
+	public Class<?> getComponentType()
+	{
+		return clss;
+	}
+	
+	/**
+	 * Sets the associated component type for an array of this type.
+	 * This type is not used when de-serializing the array components,
+	 * just when allocating the array itself.
+	 * @param clss
+	 */
+	public void setComponentType( Class<?> clss )
+	{
+		checkNotLocked();
+		this.clss = clss;
+	}
+	
+	private Class<?> clss;
+
+	/**
+	 * @return an object to help the stub dispatch the received message.
+	 */
+	public Object getStubHelper()
+	{
+		return stubHelper;
+	}
+	
+	/**
+	 * Sets an object to help the stub dispatch the received message.
+	 * @param stubHelper
+	 */
+	public void setStubHelper( Object stubHelper )
+	{
+//		checkNotLocked(); called from stub and not from value factory.
+		if (this.stubHelper != null)
+			throw new IllegalStateException( "this.stubHelper != null" );
+		this.stubHelper = stubHelper;
+	}
+
+	private Object stubHelper;
+	
+	/**
+	 * Locks the fields for this type.
+	 */
+	public void lock()
+	{
+		locked = true;
+		fields.lock();
+	}
+	
+	private void checkNotLocked()
+	{
+		if (locked)
+			throw new IllegalStateException( "locked" );
+	}
+	
+	private boolean locked;
+	
+	/**
+	 * Adds a field to the set of fields.
+	 * 
+	 * @param field a field to add.
+	 * 
+	 * @return the argument. If there is a collision with
+	 * an id and name, both associated with the same field,
+	 * then that field is returned instead of the argument.
+	 * 
+	 * @throws IllegalArgumentException if there is a
+	 * collision in the id or name, or both id and name
+	 * when not associated with the same field.
+	 */
+	public Field addField( Field field )
+	{
+		return fields.add( field );
+	}
+
+	/**
+	 * Translates a field id into the appropriate Field object.
+	 * @param id a field id.
+	 * @return id translated into the appropriate Field.
+	 */
+	public Field getField( Integer id )
+	{
+		return fields.get( id );
+	}
+
+	/**
+	 * Translates a field name into the appropriate Field
+	 * object.
+	 * @param name a field name.
+	 * @return name translated into the appropriate Field.
+	 */
+	public Field getField( String name )
+	{
+		return fields.get( name );
+	}
+	
+	/**
+	 * @return a set of all the fields.
+	 */
+	public Set<Field> getFields()
+	{
+		return Collections.unmodifiableSet( fields.values() );
+	}
+	
+	private final FieldMap fields = new FieldMap();
+
+	/**
+	 * @return the time in milliseconds to wait for this response message.
+	 */
+	public int getTimeout()
+	{
+		return timeout;
+	}
+
+	/**
+	 * @param timeout the time in milliseconds to wait for this response message.
+	 */
+	public void setTimeout( int timeout )
+	{
+		checkNotLocked();
+		this.timeout = timeout;
+	}
+	
+	private int timeout;
+
+	/**
+	 * @return the field with the value of this response.
+	 */
+	public Field getResponseField()
+	{
+		return responseField;
+	}
+
+	/**
+	 * @param responseField the field with the value of this response.
+	 */
+	public void setResponseField( Field responseField )
+	{
+		checkNotLocked();
+		this.responseField = responseField;
+	}
+	
+	private Field responseField;
+	
+	/**
+	 * Checks whether this type is assignment compatible with other. This
+	 * means that other is a subclass of this.
+	 * @param other
+	 * @return true if this type is assignable from other.
+	 */
+	public boolean isAssignableFrom( Type other )
+	{
+		return other != null && (equals( other ) || isAssignableFrom( other.superType() ));
+	}
+
+	/**
+	 * Checks to see if this type is assignable from the other type.
+	 * @param other
+	 * @throws IllegalArgumentException if this not assignable from other.
+	 * @see #isAssignableFrom(Type)
+	 */
+	public void checkIsAssignableFrom( Type other )
+	{
+		if (!isAssignableFrom( other ))
+			throw new IllegalArgumentException( "this not super type of other" );
+	}
+
+	/**
+	 * @return the super type of this type. If struct A extends B, then
+	 * B is the super type of A.
+	 */
+	public Type superType()
+	{
+		return superType;
+	}
+	
+	/**
+	 * Sets the super type of this type. If struct A extends B, then
+	 * B is the super type of A.
+	 * @param superType
+	 */
+	public void setSuperType( Type superType )
+	{
+		checkNotLocked();
+		this.superType = superType;
+	}
+	
+	private Type superType;
+
+	/**
+	 * @return the AsyncMode for this type.
+	 */
+	public AsyncMode getAsyncMode()
+	{
+		return asyncMode;
+	}
+	
+	/**
+	 * Sets the AsyncMode for this type.
+	 * @param mode
+	 */
+	public void setAsyncMode( AsyncMode mode )
+	{
+		checkNotLocked();
+		asyncMode = mode;
+	}
+	
+	private AsyncMode asyncMode;
+
+	/**
+	 * @return the message direction.
+	 */
+	public Direction getDirection()
+	{
+		return direction;
+	}
+
+	/**
+	 * Sets the message direction.
+	 * @param direction the direction to set.
+	 */
+	public void setDirection( Direction direction )
+	{
+		checkNotLocked();
+		this.direction = direction;
+	}
+	
+	private Direction direction;
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/TypeMap.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/TypeMap.java
new file mode 100644
index 0000000..b17c514
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/TypeMap.java
@@ -0,0 +1,33 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+/**
+ * TypeMap is a IdNameMap for Type.
+ */
+public final class TypeMap extends IdNameMap<Type>
+{
+	@Override
+	public Type makeNew( String name )
+	{
+		return new Type( name );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/Validator.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/Validator.java
new file mode 100644
index 0000000..0664637
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/Validator.java
@@ -0,0 +1,71 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+/**
+ * Validate values put into messages.
+ */
+public interface Validator
+{
+	/**
+	 * The maximum number of dimensions for arrays (9).
+	 */
+	public final static int MAX_NDIMS = 9;
+	
+	/**
+	 * The maximum number of validators to cache per type.
+	 */
+	public final static int MAX_CACHED = 4;
+	
+	/** Validation level for put into StructValue and TaggedDataOutput */
+	public enum Level
+	{
+		/** No validation on put or output. */
+		NONE,
+		/** Validation on put or output if validator defined. */
+		MISSING_OK,
+		/** Like MISSING_OK, but fail if no validator defined. */
+		FULL
+	}
+	
+	/**
+	 * @return for an array type, return a validator for an element of
+	 * the array (which might be a scalar or another array element).
+	 */
+	public Validator elementValidator();
+
+	/**
+	 * Checks the value for being valid. If the value is valid
+	 * by this validator, return true.
+	 * @param value the value to be validated.
+	 * @return true if the value is valid by any validator in the
+	 * chain, or false if all reject it.
+	 */
+	public boolean validate( Object value );
+
+	/**
+	 * @param value
+	 * @return the appropriate value given the input value and this
+	 * validator's sensibility about what it should be really (e.g.,
+	 * input Byte but output Long.
+	 */
+	public Object validateValue( Object value );
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/ValueFactory.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/ValueFactory.java
new file mode 100644
index 0000000..de05fc0
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/msg/ValueFactory.java
@@ -0,0 +1,199 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+import java.util.Set;
+
+import org.apache.etch.bindings.java.msg.Validator.Level;
+
+
+/**
+ * Interface which defines the value factory which helps
+ * the idl compiler serialize and deserialize messages,
+ * convert values, etc.
+ */
+public interface ValueFactory
+{
+	//////////
+	// Type //
+	//////////
+	
+	/**
+	 * Translates a type id into the appropriate Type object. If the type does
+	 * not exist, and if dynamic typing is enabled, adds it to the dynamic types.
+	 * @param id a type id.
+	 * @return id translated into the appropriate Type.
+	 */
+	public Type getType( Integer id );
+
+	/**
+	 * Translates a type name into the appropriate Type object. If the type does
+	 * not exist, and if dynamic typing is enabled, adds it to the dynamic types.
+	 * @param name a type name.
+	 * @return name translated into the appropriate Type.
+	 */
+	public Type getType( String name );
+
+	/**
+	 * Adds the type if it doesn't already exist. Use this to dynamically add
+	 * types to a ValueFactory. The type is per instance of the ValueFactory,
+	 * not global. Not available if dynamic typing is locked.
+	 * @param type
+	 */
+	public void addType( Type type );
+
+	/**
+	 * Locks the dynamic typing so that no new types may be created by addType
+	 * or getType.
+	 */
+	public void lockDynamicTypes();
+
+	/**
+	 * Unlocks the dynamic typing so that new types may be created by addType
+	 * or getType.
+	 */
+	public void unlockDynamicTypes();
+	
+	/**
+	 * @return a collection of all the types.
+	 */
+	public Set<Type> getTypes();
+
+	/////////////////////
+	// STRING ENCODING //
+	/////////////////////
+
+	/**
+	 * @return the encoding to use for strings.
+	 */
+	public String getStringEncoding();
+
+	////////////////
+	// MESSAGE ID //
+	////////////////
+
+	/**
+	 * @param msg the message whose well-known message-id field is to be
+	 * returned.
+	 * @return the value of the well-known message-id field. This is a
+	 * unique identifier for this message on a particular transport
+	 * during a particular session. If there is no well-known message-id
+	 * field defined, or if the message-id field has not been set, then
+	 * return null.
+	 */
+	public Long getMessageId( Message msg );
+
+	/**
+	 * Sets the value of the well-known message-id field. This is a
+	 * unique identifier for this message on a particular transport
+	 * during a particular session. If there is no well-known message-id
+	 * field defined then nothing is done. If msgid is null, then the
+	 * field is cleared.
+	 * @param msg the message whose well-known message-id field is to
+	 * be set.
+	 * @param msgid the value of the well-known message-id field.
+	 */
+	public void setMessageId( Message msg, Long msgid );
+
+	/**
+	 * @return well-known message field for message id.
+	 */
+	public Field get_mf__messageId();
+
+	/////////////////
+	// IN REPLY TO //
+	/////////////////
+	
+	/**
+	 * @param msg the message whose well-known in-reply-to field is to
+	 * be returned.
+	 * @return the value of the in-reply-to field, or null if there is
+	 * none or if there is no such field defined.
+	 */
+	public Long getInReplyTo( Message msg );
+
+	/**
+	 * @param msg the message whose well-known in-reply-to field is to
+	 * be set.
+	 * @param msgid the value of the well-known in-reply-to field. If
+	 * there is no well-known in-reply-to field defined then nothing
+	 * is done. If msgid is null, then the field is cleared.
+	 */
+	public void setInReplyTo( Message msg, Long msgid );
+
+	/**
+	 * @return well-known message field for in reply to.
+	 */
+	public Field get_mf__inReplyTo();
+
+	//////////////////////
+	// VALUE CONVERSION //
+	//////////////////////
+
+	/**
+	 * Converts a value to a struct value representation to be exported
+	 * to a tagged data output.
+	 * @param value a custom type defined by a service, or a well-known
+	 * standard type (e.g., date).
+	 * @return a struct value representing the value.
+	 * @throws UnsupportedOperationException if the type cannot be exported.
+	 */
+	public StructValue exportCustomValue( Object value )
+		throws UnsupportedOperationException;
+	
+	/**
+	 * Converts a struct value imported from a tagged data input to
+	 * a normal type.
+	 * @param struct a struct value representation of a custom type, or a
+	 * well known standard type.
+	 * @return a custom type, or a well known standard type.
+	 * @throws UnsupportedOperationException if the type cannot be imported.
+	 */
+	public Object importCustomValue( StructValue struct )
+		throws UnsupportedOperationException;
+
+	/**
+	 * @param c the class of a custom value.
+	 * @return the struct type of a custom value class.
+	 * @throws UnsupportedOperationException
+	 * @see #exportCustomValue(Object)
+	 */
+	public Type getCustomStructType( Class<?> c )
+		throws UnsupportedOperationException;
+
+	/**
+	 * @return well-known message type for exception thrown by one-way
+	 * message.
+	 */
+	public Type get_mt__exception();
+
+	/**
+	 * @return the validation level of field StructValue.put and TaggedDataOutput.
+	 */
+	public Level getLevel();
+
+	/**
+	 * Sets the validation level of field StructValue.put and TaggedDataOutput.
+	 * @param level
+	 * @return the old value
+	 */
+	public Level setLevel( Level level );
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/AuthExceptionSerializer.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/AuthExceptionSerializer.java
new file mode 100644
index 0000000..7f51c7a
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/AuthExceptionSerializer.java
@@ -0,0 +1,73 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+
+/**
+ * Serializer for _Etch_AuthException.
+ */
+public class AuthExceptionSerializer implements ImportExportHelper
+{
+	private final static String FIELD_NAME = "msg";
+	
+	/**
+	 * Initialize the types and fields for this serializer.
+	 * @param type
+	 * @param class2type
+	 */
+	public static void init( Type type, Class2TypeMap class2type )
+	{
+		Field field = type.getField( FIELD_NAME );
+		class2type.put( _Etch_AuthException.class, type );
+		type.setComponentType( _Etch_AuthException.class );
+		type.setImportExportHelper( new AuthExceptionSerializer( type, field ) );
+		type.putValidator( field, Validator_string.get( 0 ) );
+		type.lock();
+	}
+	
+	private AuthExceptionSerializer( Type type, Field field )
+	{
+		this.type = type;
+		this.field = field;
+	}
+	
+	private final Type type;
+	
+	private final Field field;
+	
+	public StructValue exportValue( ValueFactory vf, Object value )
+	{
+		StructValue sv = new StructValue( type, vf );
+		sv.put( field, value.toString() );
+		return sv;
+	}
+
+	public Object importValue( StructValue struct )
+	{
+		struct.checkType( type );
+		return new _Etch_AuthException( (String) struct.get( field ) );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Class2TypeMap.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Class2TypeMap.java
new file mode 100644
index 0000000..ec93b42
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Class2TypeMap.java
@@ -0,0 +1,96 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.bindings.java.msg.Type;
+
+
+/**
+ * Mapping between Class and Type.
+ */
+public class Class2TypeMap
+{
+	/**
+	 * @param c
+	 * @return the Type for the specified class, or null.
+	 */
+	public Type get( Class<?> c )
+	{
+		return c2t.get( c );
+	}
+
+	/**
+	 * Adds a map entry from c to t.
+	 * @param c
+	 * @param t
+	 * @throws IllegalStateException if locked.
+	 * @throws IllegalArgumentException if conflict.
+	 */
+	public void put( Class<?> c, Type t )
+	{
+		if (locked)
+			throw new IllegalStateException( "locked" );
+		
+		Type x = c2t.get( c );
+		if (x != null)
+		{
+			if (!x.equals( t ))
+				throw new IllegalArgumentException( String.format(
+					"type %s: class %s is already mapped to type %s",
+					t, c, x ) );
+			
+			// x.equals( t ) therefore our work is finished.
+			return;
+		}
+		
+		c2t.put( c, t );
+	}
+
+	/**
+	 * Adds all the mappings from other to this.
+	 * @param other
+	 * @throws IllegalStateException if locked.
+	 * @throws IllegalArgumentException if conflict.
+	 */
+	public void addAll( Class2TypeMap other )
+	{
+		if (locked)
+			throw new IllegalStateException( "locked" );
+		
+		for (Map.Entry<Class<?>, Type> me: other.c2t.entrySet())
+			put( me.getKey(), me.getValue() );
+	}
+
+	/**
+	 * Locks the map, disallowing any more changes.
+	 */
+	public void lock()
+	{
+		locked = true;
+	}
+	
+	private final Map<Class<?>, Type> c2t = new HashMap<Class<?>, Type>();
+	
+	private boolean locked;
+}
\ No newline at end of file
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/DefaultServerFactory.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/DefaultServerFactory.java
new file mode 100644
index 0000000..740e9cf
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/DefaultServerFactory.java
@@ -0,0 +1,103 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.util.core.io.Session;
+import org.apache.etch.util.core.io.Transport;
+
+/**
+ * Default implementation of ServerFactory. Used by Etch generated Helper files
+ * to provide listeners with backstop implementations of Session methods which
+ * forward to user's implementation factory.
+ */
+abstract public class DefaultServerFactory implements ServerFactory
+{
+	/**
+	 * Constructs the DefaultServerFactory.
+	 * @param listener 
+	 * @param implFactory
+	 */
+	public DefaultServerFactory( Transport<ServerFactory> listener,
+		Object implFactory )
+	{
+		this.listener = listener;
+		
+		if (implFactory instanceof Session)
+			setSession( (Session) implFactory );
+		
+		listener.setSession( this );
+	}
+	
+	private final Transport<ServerFactory> listener;
+
+	public Object sessionQuery( Object query ) throws Exception
+	{
+		if (session != null)
+			return session.sessionQuery( query );
+
+		throw new UnsupportedOperationException( "unknown query " + query );
+	}
+
+	public void sessionControl( Object control, Object value ) throws Exception
+	{
+		if (session != null)
+		{
+			session.sessionControl( control, value );
+			return;
+		}
+
+		throw new UnsupportedOperationException( "unknown control " + control );
+	}
+
+	public void sessionNotify( Object event ) throws Exception
+	{
+		if (session != null)
+			session.sessionNotify( event );
+	}
+
+	public Session getSession()
+	{
+		return session;
+	}
+
+	public void setSession( Session session )
+	{
+		this.session = session;
+	}
+	
+	private Session session;
+
+	public void transportControl( Object control, Object value )
+		throws Exception
+	{
+		listener.transportControl( control, value );
+	}
+
+	public void transportNotify( Object event ) throws Exception
+	{
+		listener.transportNotify( event );
+	}
+
+	public Object transportQuery( Object query ) throws Exception
+	{
+		return listener.transportQuery( query );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/DefaultValueFactory.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/DefaultValueFactory.java
new file mode 100644
index 0000000..b354386
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/DefaultValueFactory.java
@@ -0,0 +1,433 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.TypeMap;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.msg.Validator.Level;
+import org.apache.etch.bindings.java.util.DateSerializer;
+import org.apache.etch.bindings.java.util.ListSerializer;
+import org.apache.etch.bindings.java.util.MapSerializer;
+import org.apache.etch.bindings.java.util.SetSerializer;
+import org.apache.etch.util.URL;
+
+
+/**
+ * Default implementation of ValueFactory which provides some
+ * dynamic type and field support, as well as standard
+ * value conversions and import and rt.
+ */
+public class DefaultValueFactory implements ValueFactory
+{
+	private static final String ETCH_RUNTIME_EXCEPTION_TYPE_NAME = "_Etch_RuntimeException";
+
+	private static final String ETCH_LIST_TYPE_NAME = "_Etch_List";
+
+	private static final String ETCH_MAP_TYPE_NAME = "_Etch_Map";
+
+	private static final String ETCH_SET_TYPE_NAME = "_Etch_Set";
+
+	private static final String ETCH_DATETIME_TYPE_NAME = "_Etch_Datetime";
+
+	private static final String ETCH_AUTH_EXCEPTION_TYPE_NAME = "_Etch_AuthException";
+
+	private static final String ETCH_EXCEPTION_MESSAGE_NAME = "_exception";
+
+	private static final String MSG_FIELD_NAME = "msg";
+
+	private static final String MESSAGE_ID_FIELD_NAME = "_messageId";
+
+	private static final String IN_REPLY_TO_FIELD_NAME = "_inReplyTo";
+
+	private static final String RESULT_FIELD_NAME = "result";
+
+	/**
+	 * Initializes the standard types and fields needed by
+	 * all etch generated value factories.
+	 * @param types
+	 * @param class2type
+	 */
+	public static final void init( TypeMap types, Class2TypeMap class2type )
+	{
+		RuntimeExceptionSerializer.init(
+			types.get( ETCH_RUNTIME_EXCEPTION_TYPE_NAME ), class2type );
+		
+		ListSerializer.init(
+			types.get( ETCH_LIST_TYPE_NAME ), class2type );
+		
+		MapSerializer.init(
+			types.get( ETCH_MAP_TYPE_NAME ), class2type );
+		
+		SetSerializer.init(
+			types.get( ETCH_SET_TYPE_NAME ), class2type );
+		
+		DateSerializer.init(
+			types.get( ETCH_DATETIME_TYPE_NAME ), class2type );
+		
+		AuthExceptionSerializer.init(
+			types.get( ETCH_AUTH_EXCEPTION_TYPE_NAME ), class2type );
+
+		// ------------------ _mt__Etch_AuthException ------------------
+		
+		{
+			final Type t = types.get( ETCH_EXCEPTION_MESSAGE_NAME );
+			t.putValidator( _mf_result, Validator_RuntimeException.get() );
+			t.putValidator( _mf__messageId, Validator_long.get( 0 ) );
+			t.putValidator( _mf__inReplyTo, Validator_long.get( 0 ) );
+		}
+	}
+	
+	/**
+	 * The msg field of the standard unchecked exception.
+	 */
+	public static final Field _mf_msg = new Field( MSG_FIELD_NAME );
+	
+	/**
+	 *  The well-known _messageId field.
+	 */
+	public static final Field _mf__messageId = new Field( MESSAGE_ID_FIELD_NAME );
+	
+	/**
+	 * The well-known _inReplyTo field.
+	 */
+	public static final Field _mf__inReplyTo = new Field( IN_REPLY_TO_FIELD_NAME );
+	
+	/**
+	 * The well-known result field.
+	 */
+	public static final Field _mf_result = new Field( RESULT_FIELD_NAME );
+
+	///////////////////////
+	// ValueFactory impl //
+	///////////////////////
+	
+	/**
+	 * Constructs the DefaultValueFactory.
+	 * @param uri uri of this transport stack.
+	 * @param types the type map for this instance of value factory.
+	 * @param class2type the class to type map for this instance of value factory.
+	 */
+	public DefaultValueFactory( String uri, TypeMap types,
+		Class2TypeMap class2type )
+	{
+		URL u = new URL( uri );
+		
+		level = Level.valueOf( u.getTerm( "DefaultValueFactory.level", "FULL" ) );
+		
+		this.types = types;
+		this.class2type = class2type;
+		
+		_mt__Etch_RuntimeException = types.get( ETCH_RUNTIME_EXCEPTION_TYPE_NAME );
+		_mt__Etch_List = types.get( ETCH_LIST_TYPE_NAME );
+		_mt__Etch_Map = types.get( ETCH_MAP_TYPE_NAME );
+		_mt__Etch_Set = types.get( ETCH_SET_TYPE_NAME );
+		_mt__Etch_Datetime = types.get( ETCH_DATETIME_TYPE_NAME );
+		_mt__Etch_AuthException = types.get( ETCH_AUTH_EXCEPTION_TYPE_NAME );
+		_mt__exception = types.get( ETCH_EXCEPTION_MESSAGE_NAME );
+	}
+	
+	private final TypeMap types;
+	
+	private final TypeMap dynamicTypes = new TypeMap();
+
+	private final Class2TypeMap class2type;
+	
+	private final Type _mt__Etch_RuntimeException;
+	
+	private final Type _mt__Etch_List;
+	
+	private final Type _mt__Etch_Map;
+	
+	private final Type _mt__Etch_Set;
+	
+	private final Type _mt__Etch_Datetime;
+	
+	private final Type _mt__Etch_AuthException;
+	
+	private final Type _mt__exception;
+	
+	/**
+	 * @return the standard _mt__Etch_RuntimeException.
+	 */
+	public final Type get_mt__Etch_RuntimeException()
+	{
+		return _mt__Etch_RuntimeException;
+	}
+	
+	/**
+	 * @return the standard _mt__Etch_List.
+	 */
+	public final Type get_mt__Etch_List()
+	{
+		return _mt__Etch_List;
+	}
+	
+	/**
+	 * @return the standard _mt__Etch_Map.
+	 */
+	public final Type get_mt__Etch_Map()
+	{
+		return _mt__Etch_Map;
+	}
+	
+	/**
+	 * @return the standard _mt__Etch_Set.
+	 */
+	public final Type get_mt__Etch_Set()
+	{
+		return _mt__Etch_Set;
+	}
+	
+	/**
+	 * @return the standard _mt__Etch_Datetime.
+	 */
+	public final Type get_mt__Etch_Datetime()
+	{
+		return _mt__Etch_Datetime;
+	}
+	
+	/**
+	 * @return the standard _mt__Etch_AuthException.
+	 */
+	public final Type get_mt__Etch_AuthException()
+	{
+		return _mt__Etch_AuthException;
+	}
+	
+	public final Type get_mt__exception()
+	{
+		return _mt__exception;
+	}
+
+	/**
+	 * Adds a value factory as a mixin to this one.
+	 * @param vf
+	 */
+	protected void addMixin( ValueFactory vf )
+	{
+		ValueFactory[] newMixins = new ValueFactory[mixins.length+1];
+		System.arraycopy( mixins, 0, newMixins, 0, mixins.length );
+		newMixins[mixins.length] = vf;
+		mixins = newMixins;
+	}
+	
+	private ValueFactory[] mixins = {};
+	
+	public final Type getType( Integer id )
+	{
+		Type type = types.get( id );
+		if (type != null)
+			return type;
+		
+		for (ValueFactory vf: mixins)
+			if ((type = vf.getType( id )) != null)
+				return type;
+
+		synchronized (dynamicTypes)
+		{
+			return dynamicTypes.get( id );
+		}
+	}
+
+	public final Type getType( String name )
+	{
+		Type type = types.get( name );
+		if (type != null)
+			return type;
+		
+		for (ValueFactory vf: mixins)
+			if ((type = vf.getType( name )) != null)
+				return type;
+		
+		synchronized (dynamicTypes)
+		{
+			return dynamicTypes.get( name );
+		}
+	}
+
+	public void addType( Type type )
+	{
+		try
+		{
+			synchronized (dynamicTypes)
+			{
+				dynamicTypes.add( type );
+			}
+		}
+		catch ( IllegalArgumentException e )
+		{
+			// ignore.
+		}
+	}
+	
+	public final Set<Type> getTypes()
+	{
+		Set<Type> values = types.values();
+		
+		for (ValueFactory vf: mixins)
+			values.addAll( vf.getTypes() );
+
+		synchronized (dynamicTypes)
+		{
+			values.addAll( dynamicTypes.values() );
+		}
+		
+		return values;
+	}
+
+	public final StructValue exportCustomValue( Object value )
+	{
+		Class<?> clss = value.getClass();
+		
+		Type type = getCustomStructType( clss );
+		
+		if (type == null && clss == StructValue.class)
+		{
+			StructValue struct = (StructValue) value;
+			type = struct.type();
+		}
+		
+		if (type == null)
+		{
+			if (Throwable.class.isAssignableFrom( clss ))
+				type = _mt__Etch_RuntimeException;
+			else if (List.class.isAssignableFrom( clss ))
+				type = _mt__Etch_List;
+			else if (Map.class.isAssignableFrom( clss ))
+				type = _mt__Etch_Map;
+			else if (Set.class.isAssignableFrom( clss ))
+				type = _mt__Etch_Set;
+			else
+				return null;
+		}
+		
+		ImportExportHelper helper = type.getImportExportHelper();
+		
+		if (helper == null)
+			return null;
+		
+		return helper.exportValue( this, value );
+	}
+
+	public final Object importCustomValue( StructValue struct )
+	{
+		ImportExportHelper helper = struct.type().getImportExportHelper();
+		
+		if (helper == null)
+			return null;
+		
+		return helper.importValue( struct );
+	}
+
+	public final Type getCustomStructType( Class<?> c )
+	{
+		Type type = class2type.get( c );
+		if (type != null)
+			return type;
+		
+		for (ValueFactory vf: mixins)
+			if ((type = vf.getCustomStructType( c )) != null)
+				return type;
+		
+		return null;
+	}
+
+	/////////////////////
+	// STRING ENCODING //
+	/////////////////////
+	
+	public String getStringEncoding()
+	{
+		return "utf-8";
+	}
+
+	////////////////
+	// MESSAGE ID //
+	////////////////
+
+	public final Long getMessageId( Message msg )
+	{
+		return (Long) msg.get( _mf__messageId );
+	}
+
+	public final void setMessageId( Message msg, Long msgid )
+	{
+		msg.put( _mf__messageId, msgid );
+	}
+
+	public Field get_mf__messageId()
+	{
+		return _mf__messageId;
+	}
+
+	/////////////////
+	// IN REPLY TO //
+	/////////////////
+
+	public final Long getInReplyTo( Message msg )
+	{
+		return (Long) msg.get( _mf__inReplyTo );
+	}
+
+	public final void setInReplyTo( Message msg, Long msgid )
+	{
+		msg.put( _mf__inReplyTo, msgid );
+	}
+
+	public Field get_mf__inReplyTo()
+	{
+		return _mf__inReplyTo;
+	}
+
+	public void lockDynamicTypes()
+	{
+		dynamicTypes.lock();
+	}
+
+	public Level getLevel()
+	{
+		return level;
+	}
+
+	public Level setLevel( Level level )
+	{
+		Level oldLevel = this.level;
+		this.level = level;
+		return oldLevel;
+	}
+
+	private Level level = Level.FULL;
+
+	public void unlockDynamicTypes()
+	{
+		// TODO implement dynamicTypes.unlock();
+		throw new UnsupportedOperationException( "unlockDynamicTypes not implemented" );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/DeliveryService.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/DeliveryService.java
new file mode 100644
index 0000000..19a5ad1
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/DeliveryService.java
@@ -0,0 +1,54 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.transport.SessionMessage;
+import org.apache.etch.bindings.java.transport.TransportMessage;
+
+/**
+ * Adapter between remote and message source.
+ */
+public interface DeliveryService extends SessionMessage, TransportMessage
+{
+	/**
+	 * Sends the message which begins a call sequence.
+	 * 
+	 * @param msg the message to send.
+	 * @return a mailbox which can be used to read the response, using
+	 * {@link #endcall(Mailbox, Type)}.
+	 * @throws Exception if there is a problem sending
+	 */
+	public Mailbox begincall( Message msg ) throws Exception;
+
+	/**
+	 * Finishes a call sequence by waiting for the response message.
+	 * 
+	 * @param mb a mailbox which will be used to read the response, returned by
+	 * {@link #begincall(Message)}.
+	 * @param responseType the type of the expected response.
+	 * @return the value of the response field if it isn't an exception.
+	 * @throws Exception if there is a problem sending or a timeout waiting or
+	 * if the result value was an exception.
+	 */
+	public Object endcall( Mailbox mb, Type responseType ) throws Exception;
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/DummyValueFactory.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/DummyValueFactory.java
new file mode 100644
index 0000000..a71879e
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/DummyValueFactory.java
@@ -0,0 +1,133 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import java.util.Set;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.msg.Validator.Level;
+
+
+/** Dummy implementation of ValueFactory used for testing. */
+public class DummyValueFactory implements ValueFactory
+{
+	public StructValue exportCustomValue( Object value )
+		throws UnsupportedOperationException
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Type getCustomStructType( Class<?> c )
+		throws UnsupportedOperationException
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Long getInReplyTo( Message msg )
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Long getMessageId( Message msg )
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public String getStringEncoding()
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Type getType( Integer id )
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Type getType( String name )
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Set<Type> getTypes()
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Type get_mt__exception()
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Object importCustomValue( StructValue struct )
+		throws UnsupportedOperationException
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public void setInReplyTo( Message msg, Long msgid )
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public void setMessageId( Message msg, Long msgid )
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public void addType( Type type )
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Field get_mf__inReplyTo()
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Field get_mf__messageId()
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public void lockDynamicTypes()
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public void unlockDynamicTypes()
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Level setLevel( Level level )
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Level getLevel()
+	{
+		return Level.FULL;
+	}
+}
\ No newline at end of file
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/FreePool.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/FreePool.java
new file mode 100644
index 0000000..bdbf733
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/FreePool.java
@@ -0,0 +1,97 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+/**
+ * A free implementation of Pool.
+ */
+public class FreePool implements Pool
+{
+	/**
+	 * Constructs a FreePool with specified maxSize.
+	 * @param maxSize maximum number of free threads at one
+	 * time. after that, reject requests.
+	 */
+	public FreePool( int maxSize )
+	{
+		this.maxSize = maxSize;
+	}
+	
+	/**
+	 * Constructs a FreePool with maxSize 50.
+	 */
+	public FreePool()
+	{
+		this( 50 );
+	}
+	
+	private final int maxSize;
+	
+	private final ThreadGroup tg = new ThreadGroup( "FreePoolThreadGroup" );
+	
+	private boolean open = true;
+	
+	/**
+	 * Closes the pool. This just marks the pool as being closed, it doesn't
+	 * actually do anything to the currently running thread. But no more
+	 * threads are allowed to start.
+	 */
+	public void close()
+	{
+		open = false;
+	}
+	
+	/**
+	 * Joins each of the threads in this pool until there
+	 * are none left. The pool will be closed first.
+	 * @throws InterruptedException
+	 */
+	public void join() throws InterruptedException
+	{
+		close();
+		Thread[] list = new Thread[10];
+		int n;
+		while ((n = tg.enumerate( list )) > 0)
+			for (int i = 0; i < n; i++)
+				list[i].join();
+	}
+	
+	public synchronized void run( final PoolRunnable runnable )
+	{
+		if (!open || tg.activeCount() >= maxSize)
+			throw new IllegalStateException( "free pool thread count exceeded or pool closed" );
+		
+		new Thread( tg, new Runnable()
+		{
+			public void run()
+			{
+				try
+				{
+					runnable.run();
+				}
+				catch ( Exception e )
+				{
+					runnable.exception( e );
+				}
+			}
+		} ).start();
+	}
+}
\ No newline at end of file
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Mailbox.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Mailbox.java
new file mode 100644
index 0000000..3b95407
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Mailbox.java
@@ -0,0 +1,165 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.util.core.Who;
+
+
+/**
+ * An interface used to deliver responses to a message. Support for
+ * the mechanism is somewhat dependent upon properties of the transport
+ * and message format.
+ */
+public interface Mailbox
+{
+	/**
+	 * @return the message id of this mailbox.
+	 */
+	public Long getMessageId();
+
+	/**
+	 * Queues the message to the mailbox.
+	 * @param sender
+	 * @param msg
+	 * @return true if the message was accepted.
+	 * @throws Exception
+	 */
+	public boolean message( Who sender, Message msg ) throws Exception;
+
+	/**
+	 * @return the next message to be read from the mailbox, or null if
+	 * the mailbox is empty and closed. Wait forever for such a message
+	 * to be delivered.
+	 * @throws InterruptedException thread interrupt.
+	 */
+	public Element read() throws InterruptedException;
+
+	/**
+	 * @param maxDelay the maximum amount of time in milliseconds to
+	 * wait to read a message from an empty mailbox. 0 means wait
+	 * forever, -1 means don't wait at all.
+	 * @return the message read from the mailbox, or null if the mailbox
+	 * is empty and closed, or if the time limit was exceeeded.
+	 * @throws InterruptedException thread interrupt.
+	 */
+	public Element read( int maxDelay ) throws InterruptedException;
+	
+	/**
+	 * Closes the mailbox so that no more messages can be delivered.
+	 * Queued messages remain to be read. Reading an empty closed
+	 * mailbox returns null.
+	 * @return true if this call closed the mailbox (that is, if action was
+	 * taken), false if the mailbox was already closed.
+	 */
+	public boolean closeDelivery();
+	
+	/**
+	 * Closes the mailbox so that no more messages will be delivered or
+	 * read. Any remaining queued messages are delivered to a default
+	 * handler.
+	 * @return true if this call closed the mailbox (that is, if action was
+	 * taken), false if the mailbox was already closed.
+	 * @throws Exception
+	 */
+	public boolean closeRead() throws Exception;
+	
+	/**
+	 * Registers a Notify interface implementation to receive a callback
+	 * when a mailbox's status is changed.
+	 * @param notify a Notify interface implementation to report the
+	 * delivery status to.
+	 * @param state a state value to pass thru to the Notify interface
+	 * implementation.
+	 * @param maxDelay the maximum amount of time in milliseconds to
+	 * wait for delivery of a message to the mailbox. 0 means wait
+	 * forever. The mailbox is closed upon timeout.
+	 * @throws IllegalStateException notify already registered.
+	 */
+	public void registerNotify( Notify notify, Object state, int maxDelay );
+	
+	/**
+	 * Unregisters a Notify interface implementation from receiving a callback
+	 * when a mailbox's status is changed. Cancels any timeout.
+	 * @param notify a Notify interface implementation which was previously
+	 * registered.
+	 * @throws IllegalStateException the specified notify is not registered.
+	 */
+	public void unregisterNotify( Notify notify );
+
+	/**
+	 * @return true if the mailbox is empty.
+	 */
+	public boolean isEmpty();
+	
+	/**
+	 * @return true if the mailbox is closed.
+	 */
+	public boolean isClosed();
+
+	/**
+	 * @return true if the mailbox is full.
+	 */
+	public boolean isFull();
+	
+	/**
+	 * The message as queued, including src and sender.
+	 */
+	public final class Element
+	{
+		/**
+		 * @param sender the message sender.
+		 * @param msg the message.
+		 */
+		public Element( Who sender, Message msg )
+		{
+			this.sender = sender;
+			this.msg = msg;
+		}
+		
+		/**
+		 * The message sender.
+		 */
+		
+		public final Who sender;
+		/**
+		 * the message.
+		 */
+		public final Message msg;
+	}
+	
+	/**
+	 * Interface used to notify of mailbox status.
+	 */
+	public interface Notify
+	{
+		/**
+		 * Notifies of mailbox status change.
+		 * @param mb the mailbox whose status has changed.
+		 * @param state the state object passed in the register
+		 * method.
+		 * @param closed true if the mailbox timeout has expired and
+		 * the mailbox is now closed to delivery, false if a message
+		 * has arrived.
+		 */
+		public void mailboxStatus( Mailbox mb, Object state, boolean closed );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/NullPool.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/NullPool.java
new file mode 100644
index 0000000..05c571a
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/NullPool.java
@@ -0,0 +1,39 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+/**
+ * A pool which runs the runnable directly.
+ */
+public class NullPool implements Pool
+{
+	public void run( PoolRunnable runnable ) throws Exception
+	{
+		try
+		{
+			runnable.run();
+		}
+		catch ( Exception e )
+		{
+			runnable.exception( e );
+		}
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/ObjSession.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/ObjSession.java
new file mode 100644
index 0000000..4dd50a0
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/ObjSession.java
@@ -0,0 +1,88 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+/**
+ * Out-of-band query, control, and notification interface for sessions.
+ * This is exactly the same as etch.bindings.java.transport.Session except
+ * the names are changed to prevent collisions with service defined names.
+ * @see org.apache.etch.util.core.io.Session
+ */
+public interface ObjSession
+{
+	/**
+	 * Gets a configuration or operational value from the handler. The
+	 * request is passed up the chain of sessions until some session
+	 * recognizes the query, whereupon it returns the requested value.
+	 * 
+	 * @param query an object representing a query, which could be as
+	 * simple as a string, integer, or enum, or more complex such as
+	 * a class with instance variables for query terms.
+	 * 
+	 * @return the requested value, or null if not defined.
+	 * 
+	 * @throws UnsupportedOperationException if the query is not recognized
+	 * by any session (which is to say, if the last session in the session
+	 * chain does not recognize it, it should throw this exception). Typically
+	 * this would be a service's client or server implementation.
+	 * 
+	 * @throws Exception
+	 */
+	public Object _sessionQuery( Object query ) throws Exception;
+
+	/**
+	 * Sets a configuration or operational value in the session. The
+	 * request is passed up the chain of sessions until some session
+	 * recognizes the control, whereupon it stores the specified value
+	 * and returns.
+	 * 
+	 * @param control an object representing a control, which could be as
+	 * simple as a string, integer, or enum, or more complex such as
+	 * a class with instance variables for control terms.
+	 * 
+	 * @param value the value to set.
+	 * 
+	 * @throws IllegalArgumentException if the value is not the right
+	 * type or if the value is inappropriate.
+	 * 
+	 * @throws UnsupportedOperationException if the control is not recognized
+	 * by any session (which is to say, if the last session in the session
+	 * chain does not recognize it, it should throw this exception). Typically
+	 * this would be a service's client or server implementation.
+	 * 
+	 * @throws Exception
+	 */
+	public void _sessionControl( Object control, Object value ) throws Exception;
+
+	/**
+	 * Notifies the chain of sessions of the specified event. Unlike query
+	 * and control operations above, events are always passed up to the
+	 * top to allow all sessions to notice them.
+	 * 
+	 * @param event a class which represents the event, possibly with
+	 * parameters. The simplest event could be a string, integer,
+	 * or enum, but any class instance will do (as long as some session
+	 * in the chain expects it).
+	 * 
+	 * @throws Exception
+	 */
+	public void _sessionNotify( Object event ) throws Exception;
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Pool.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Pool.java
new file mode 100644
index 0000000..b20362c
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Pool.java
@@ -0,0 +1,51 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+/**
+ * Interface to a queued or free thread pool.
+ */
+public interface Pool
+{
+	/**
+	 * @param runnable the thing to run.
+	 * @throws Exception if there is a problem scheduling the
+	 * runnable to run.
+	 */
+	void run( PoolRunnable runnable ) throws Exception;
+	
+	/**
+	 * A runnable which can throw an exception.
+	 */
+	public interface PoolRunnable
+	{
+		/**
+		 * @throws Exception
+		 */
+		public void run() throws Exception;
+
+		/**
+		 * Reports an exception thrown by the run method.
+		 * @param e
+		 */
+		public void exception( Exception e );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/QueuedPool.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/QueuedPool.java
new file mode 100644
index 0000000..191c192
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/QueuedPool.java
@@ -0,0 +1,66 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.util.Todo;
+import org.apache.etch.util.TodoManager;
+
+/**
+ * A queued implementation of pool.
+ */
+public class QueuedPool implements Pool
+{
+	/**
+	 * Constructs the queued pool with a specified todo manager.
+	 * @param mgr
+	 */
+	public QueuedPool( TodoManager mgr )
+	{
+		this.mgr = mgr;
+	}
+	
+	/**
+	 * Constructs the queued pool with a default todo manager.
+	 * @throws Exception
+	 */
+	public QueuedPool() throws Exception
+	{
+		this( TodoManager.getTodoManager() );
+	}
+	
+	private final TodoManager mgr;
+	
+	public void run( final PoolRunnable runnable ) throws Exception
+    {
+        mgr.add( new Todo()
+        {
+			public void doit( TodoManager mgr ) throws Exception
+            {
+                runnable.run();
+            }
+
+			public void exception( TodoManager mgr, Exception e )
+            {
+                runnable.exception( e );
+            }
+        } );
+    }
+}
\ No newline at end of file
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/RemoteBase.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/RemoteBase.java
new file mode 100644
index 0000000..a4be9ff
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/RemoteBase.java
@@ -0,0 +1,258 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.util.core.io.Transport;
+import org.apache.etch.util.core.io.Transport.WaitDown;
+import org.apache.etch.util.core.io.Transport.WaitUp;
+
+
+/**
+ * Base class for call to message translators.
+ */
+public class RemoteBase
+{
+	/**
+	 * Constructs the RemoteBase.
+	 *
+	 * @param svc the delivery service used to send messages.
+	 * @param vf the value factory used to create messages and encode/decode types.
+	 */
+	public RemoteBase( DeliveryService svc, ValueFactory vf )
+	{
+		_svc = svc;
+		_vf = vf;
+	}
+	
+	private final DeliveryService _svc;
+	
+	private final ValueFactory _vf;
+	
+	@Override
+	public String toString()
+	{
+		return String.format( "%s/%s", getClass().getName(), _svc );
+	}
+	
+	/**
+	 * Constructs a new message to send using {@link #_send(Message)} or
+	 * {@link #_begincall(Message)};
+	 * @param type the type of the message.
+	 * @return a new message
+	 */
+	public final Message _newMessage( Type type )
+	{
+		return new Message( type, _vf );
+	}
+	
+	/**
+	 * Sends the message to the recipient, but does not wait for any response.
+	 * 
+	 * @param msg the message to send
+	 * @throws Exception if there is a problem sending
+	 */
+	public void _send( Message msg ) throws Exception
+	{
+		_svc.transportMessage( null, msg );
+	}
+	
+	/**
+	 * Sends the message which begins a call sequence.
+	 * 
+	 * @param msg the message to send.
+	 * @return a mailbox which can be used to read the response, using
+	 * {@link #_endcall(Mailbox, Type)}.
+	 */
+	public Mailbox _begincall( Message msg )
+	{
+		try
+		{
+			return _svc.begincall( msg );
+		}
+		catch ( RuntimeException e )
+		{
+			throw e;
+		}
+		catch ( Exception e )
+		{
+			throw new RuntimeException( e );
+		}
+	}
+
+	/**
+	 * Finishes a call sequence by waiting for the response message.
+	 * 
+	 * @param mb a mailbox which will be used to read the response, returned by
+	 * {@link #_begincall(Message)}.
+	 * @param responseType the type of the expected response.
+	 * @return the value of the response field if it isn't an exception.
+	 * @throws Exception if there is a problem sending or a timeout waiting or
+	 * if the result value was an exception.
+	 */
+	public Object _endcall( Mailbox mb, Type responseType ) throws Exception
+	{
+		return _svc.endcall( mb, responseType );
+	}
+
+	/**
+	 * Gets a configuration or operational value from the source. The
+	 * request is passed down the chain of sources until some source
+	 * recognizes the query, whereupon it returns the requested value.
+	 * 
+	 * @param query an object representing a query, which could be as
+	 * simple as a string, integer, or enum, or more complex such as
+	 * a class with instance variables for query terms.
+	 * 
+	 * @return the requested value, or null if not defined.
+	 * 
+	 * @throws UnsupportedOperationException if the query is not recognized
+	 * by any source (which is to say, if the last source in the source
+	 * chain does not recognize it, it should throw this exception).
+	 * 
+	 * @throws Exception
+	 */
+	public Object _transportQuery( Object query ) throws Exception
+	{
+		return _svc.transportQuery( query );
+	}
+
+	/**
+	 * Sets a configuration or operational value in the source. The
+	 * request is passed down the chain of sources until some source
+	 * recognizes the control, whereupon it stores the specified value
+	 * and returns.
+	 * 
+	 * @param control an object representing a control, which could be as
+	 * simple as a string, integer, or enum, or more complex such as
+	 * a class with instance variables for control terms.
+	 * 
+	 * @param value the value to set.
+	 * 
+	 * @throws IllegalArgumentException if the value is not the right
+	 * type or if the value is inappropriate.
+	 * 
+	 * @throws UnsupportedOperationException if the control is not recognized
+	 * by any source (which is to say, if the last source in the source
+	 * chain does not recognize it, it should throw this exception).
+	 * 
+	 * @throws Exception
+	 */
+	public void _transportControl( Object control, Object value ) throws Exception
+	{
+		_svc.transportControl( control, value );
+	}
+
+	/**
+	 * Notifies the chain of sources of the specified event. Unlike query
+	 * and control operations above, events are always passed down to the
+	 * bottom to allow all sources to notice them.
+	 * 
+	 * @param event a class which represents the event, possibly with
+	 * parameters. The simplest event could be a string, integer,
+	 * or enum, but any class instance will do (as long as some source
+	 * in the chain expects it).
+	 * 
+	 * @throws Exception
+	 */
+	public void _transportNotify( Object event ) throws Exception
+	{
+		_svc.transportNotify( event );
+	}
+
+	////////////////////////////
+	// Convenience operations //
+	////////////////////////////
+	
+	/**
+	 * Starts the transport.
+	 * @throws Exception
+	 * @see #_transportControl(Object, Object)
+	 * @see Transport#START
+	 */
+	public void _start() throws Exception
+	{
+		_transportControl( Transport.START, null );
+	}
+	
+	/**
+	 * Waits for the transport to come up.
+	 * @param maxDelay max delay in milliseconds.
+	 * @throws Exception
+	 * @see #_transportQuery(Object)
+	 * @see WaitUp
+	 */
+	public void _waitUp( int maxDelay ) throws Exception
+	{
+		_transportQuery( new WaitUp( maxDelay ) );
+	}
+	
+	/**
+	 * Starts the transport and waits for it to come up.
+	 * @param maxDelay max delay in milliseconds.
+	 * @throws Exception
+	 * @see #_start()
+	 * @see #_waitUp(int)
+	 */
+	public void _startAndWaitUp( int maxDelay ) throws Exception
+	{
+		_start();
+		_waitUp( maxDelay );
+	}
+	
+	/**
+	 * Stops the transport.
+	 * @throws Exception
+	 * @see #_transportControl(Object, Object)
+	 * @see Transport#STOP
+	 */
+	public void _stop() throws Exception
+	{
+		_transportControl( Transport.STOP, null );
+	}
+	
+	/**
+	 * Waits for the transport to go down.
+	 * @param maxDelay max delay in milliseconds.
+	 * @throws Exception
+	 * @see #_transportQuery(Object)
+	 * @see WaitDown
+	 */
+	public void _waitDown( int maxDelay ) throws Exception
+	{
+		_transportQuery( new WaitDown( maxDelay ) );
+	}
+	
+	/**
+	 * Stops the transport and waits for it to go down.
+	 * @param maxDelay max delay in milliseconds.
+	 * @throws Exception
+	 * @see #_start()
+	 * @see #_waitDown(int)
+	 */
+	public void _stopAndWaitDown( int maxDelay ) throws Exception
+	{
+		_stop();
+		_waitDown( maxDelay );
+	}
+}
\ No newline at end of file
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/RuntimeExceptionSerializer.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/RuntimeExceptionSerializer.java
new file mode 100644
index 0000000..704d5ec
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/RuntimeExceptionSerializer.java
@@ -0,0 +1,80 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+
+/**
+ * Serializer for RuntimeException.
+ */
+public class RuntimeExceptionSerializer implements ImportExportHelper
+{
+	private final static String FIELD_NAME = "msg";
+
+	/**
+	 * Defines custom fields in the value factory so that the importer
+	 * can find them.
+	 * @param type
+	 * @param class2type
+	 */
+	public static void init( Type type, Class2TypeMap class2type )
+	{
+		Field field = type.getField( FIELD_NAME );
+		class2type.put( _Etch_RuntimeException.class, type );
+		type.setComponentType( _Etch_RuntimeException.class );
+		type.setImportExportHelper( new RuntimeExceptionSerializer( type, field ) );
+		type.putValidator( field, Validator_string.get( 0 ) );
+		type.lock();
+	}
+
+	/**
+	 * Constructs the RuntimeExceptionSerializer.
+	 *
+	 * @param type
+	 * @param field
+	 */
+	public RuntimeExceptionSerializer( Type type, Field field )
+	{
+		this.type = type;
+		this.field = field;
+	}
+	
+	private final Type type;
+	
+	private final Field field;
+
+	public StructValue exportValue( ValueFactory vf, Object value )
+	{
+		StructValue sv = new StructValue( type, vf );
+		sv.put( field, value.toString() );
+		return sv;
+	}
+
+	public Object importValue( StructValue struct )
+	{
+		struct.checkType( type );
+		return new _Etch_RuntimeException( (String) struct.get( field ) );
+	}
+}
\ No newline at end of file
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/ServerFactory.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/ServerFactory.java
new file mode 100644
index 0000000..9fce33d
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/ServerFactory.java
@@ -0,0 +1,50 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.transport.TransportMessage;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.core.io.Session;
+import org.apache.etch.util.core.io.Transport;
+
+
+/**
+ * Interface to use for constructing new server instances by
+ * TransportHelper.
+ */
+public interface ServerFactory extends Session, Transport<Session>
+{
+	/**
+	 * @param transport the TransportMessage to use with the new server instance.
+	 * @param uri the uri to use to configure the new server instance.
+	 * @param resources the resources to use for the new server instance.
+	 * @throws Exception
+	 */
+	public void newServer( TransportMessage transport, String uri,
+		Resources resources ) throws Exception;
+	
+	/**
+	 * @param uri the uri to use to configure the new value factory.
+	 * @return a new instance of value factory for this connection.
+	 */
+	public ValueFactory newValueFactory( String uri );
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/StubBase.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/StubBase.java
new file mode 100644
index 0000000..5b8d8ef
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/StubBase.java
@@ -0,0 +1,205 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.support.Pool.PoolRunnable;
+import org.apache.etch.bindings.java.transport.SessionMessage;
+import org.apache.etch.util.core.Who;
+
+
+/**
+ * Base class of stub implementations.
+ * @param <T> The type of object used to implement stub.
+ */
+public class StubBase<T> implements SessionMessage
+{
+	/**
+	 * Constructs the StubBase.
+	 * @param svc the message source.
+	 * @param obj the target of decoded messages.
+	 * @param queued thread pool used to run AsyncMode.QUEUED methods.
+	 * @param free thread pool used to run AsyncMode.FREE methods.
+	 */
+	public StubBase( DeliveryService svc, T obj, Pool queued, Pool free )
+	{
+		if (svc == null)
+			throw new NullPointerException( "svc == null" );
+		
+		if (obj == null)
+			throw new NullPointerException( "obj == null" );
+		
+		this._svc = svc;
+		this._obj = obj;
+		this._queued = queued;
+		this._free = free;
+		
+		svc.setSession( this );
+	}
+	
+	/**
+	 * The message source.
+	 */
+	protected final DeliveryService _svc;
+	
+	/**
+	 * The object used to implement stub.
+	 */
+	protected final T _obj;
+	
+	/**
+	 * The thread pool used to run AsyncMode.QUEUED methods.
+	 */
+	protected final Pool _queued;
+	
+	/**
+	 * The thread pool used to run AsyncMode.FREE methods.
+	 */
+	protected final Pool _free;
+
+	@SuppressWarnings("unchecked")
+	public final boolean sessionMessage( Who sender, Message msg ) throws Exception
+	{
+		Type type = msg.type();
+		
+		StubHelper<T> helper = (StubHelper<T>) type.getStubHelper();
+		if (helper == null)
+			return false;
+		
+		switch (type.getAsyncMode())
+		{
+			case QUEUED:
+				try
+				{
+					_queued.run( new StubPoolRunnable( sender, msg, helper ) );
+				}
+				catch ( Exception e )
+				{
+					sessionNotify( _obj, e );
+				}
+				break;
+			case FREE:
+				try
+				{
+					_free.run( new StubPoolRunnable( sender, msg, helper ) );
+				}
+				catch ( Exception e )
+				{
+					sessionNotify( _obj, e );
+				}
+				break;
+			case NONE:
+				try
+				{
+					helper.run( _svc, _obj, sender, msg );
+				}
+				catch ( Exception e )
+				{
+					sessionNotify( _obj, e );
+				}
+				break;
+            default:
+                throw new IllegalArgumentException("unknown async mode "+type.getAsyncMode());
+		}
+		
+		return true;
+	}
+
+	public Object sessionQuery( Object query ) throws Exception
+	{
+		if (_obj instanceof ObjSession)
+			return ((ObjSession) _obj)._sessionQuery( query );
+		throw new UnsupportedOperationException( "unknown query "+query );
+	}
+
+	public void sessionControl( Object control, Object value ) throws Exception
+	{
+		if (_obj instanceof ObjSession)
+			((ObjSession) _obj)._sessionControl( control, value );
+		else
+			throw new UnsupportedOperationException( "unknown control "+control );
+	}
+
+	public void sessionNotify( Object event ) throws Exception
+	{
+		sessionNotify( _obj, event );
+	}
+	
+	/**
+	 * Notifies the session of events going on "below the hood". Among
+	 * other things, used to report exceptions from the transport stack,
+	 * including exceptions caught by the stub which were thrown by obj.
+	 * @param obj the service implementation, client or server.
+	 * @param event an event which might or might not be an exception.
+	 * @throws Exception
+	 */
+	public static void sessionNotify( Object obj, Object event ) throws Exception
+	{
+		if (obj instanceof ObjSession)
+			((ObjSession) obj)._sessionNotify( event );
+		else if (event instanceof Throwable)
+			((Throwable) event).printStackTrace();
+	}
+	
+	/**
+	 * A PoolRunnable used by the stub to dispatch asynchronous
+	 * receiver methods from messages.
+	 */
+	private final class StubPoolRunnable implements PoolRunnable
+	{
+		/**
+		 * Constructs the StubPoolRunnable.
+		 * @param sender the sender of the message.
+		 * @param msg the message.
+		 * @param helper the StubHelper which will dispatch the message.
+		 */
+		public StubPoolRunnable( Who sender, Message msg, StubHelper<T> helper )
+		{
+			this.sender = sender;
+			this.msg = msg;
+			this.helper = helper;
+		}
+		
+		private final Who sender;
+		
+		private final Message msg;
+		
+		private final StubHelper<T> helper;
+
+		public void exception( Exception e )
+		{
+			try
+			{
+				sessionNotify( e );
+			}
+			catch ( Exception e1 )
+			{
+				e1.printStackTrace();
+			}
+		}
+
+		public void run() throws Exception
+		{
+			helper.run( _svc, _obj, sender, msg );
+		}
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/StubHelper.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/StubHelper.java
new file mode 100644
index 0000000..26d0c07
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/StubHelper.java
@@ -0,0 +1,52 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.util.core.Who;
+
+
+/**
+ * Generated code to dispatch method from message.
+ * @param <T> the service interface type.
+ */
+abstract public class StubHelper<T>
+{
+	/**
+	 * Constructs a StubHelper which uses synchronous mode to dispatch
+	 * method from message.
+	 */
+	public StubHelper()
+	{
+		// nothing to do.
+	}
+	
+	/**
+	 * Dispatches the method from message.
+	 * @param svc
+	 * @param obj
+	 * @param sender
+	 * @param msg
+	 * @throws Exception
+	 */
+	abstract public void run( DeliveryService svc, T obj, Who sender, Message msg )
+		throws Exception;
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/TransportFactory.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/TransportFactory.java
new file mode 100644
index 0000000..3d0e11f
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/TransportFactory.java
@@ -0,0 +1,303 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.apache.etch.bindings.java.transport.SessionMessage;
+import org.apache.etch.bindings.java.transport.TcpTransportFactory;
+import org.apache.etch.bindings.java.transport.TransportMessage;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.io.Transport;
+
+
+/**
+ * Interface to transport factory.
+ */
+abstract public class TransportFactory
+{
+	/**
+	 * Constructs a new Transport stack topped by a TransportMessage
+	 * which is used by the remote service implementations to send
+	 * messages.
+	 * @param uri transport configuration parameters.
+	 * @param resources additional resources needed by the stack.
+	 * @return the TransportMessage topping the transport stack.
+	 * @throws Exception
+	 */
+	abstract protected TransportMessage newTransport( String uri,
+		Resources resources ) throws Exception;
+
+	/**
+	 * Constructs a new Transport stack topped by a TransportMessage
+	 * which is used by the remote service implementations to send
+	 * messages.
+	 * @param uri transport configuration parameters.
+	 * @param resources additional resources needed by the stack.
+	 * @return the TransportMessage topping the transport stack.
+	 * @throws Exception
+	 */
+	static public TransportMessage getTransport( String uri,
+		Resources resources ) throws Exception
+	{
+		URL u = new URL( uri );
+		TransportFactory f = getTransportFactory( u.getScheme() );
+		return f.newTransport( uri, resources );
+	}
+
+	/**
+	 * Constructs a new Transport Listener which is used to construct
+	 * server sessions.
+	 * @param uri listener configuration parameters.
+	 * @param resources additional resources needed by the listener.
+	 * @return an out-of-band source which may be used to control the listener.
+	 * @throws Exception
+	 */
+	abstract protected Transport<ServerFactory> newListener( String uri,
+		Resources resources ) throws Exception;
+
+	/**
+	 * Constructs a new Transport Listener which is used to construct
+	 * server sessions.
+	 * @param uri listener configuration parameters.
+	 * @param resources additional resources needed by the listener.
+	 * @return an out-of-band source which may be used to control the listener.
+	 * @throws Exception
+	 */
+	static public Transport<ServerFactory> getListener( String uri,
+		Resources resources ) throws Exception
+	{
+		URL u = new URL( uri );
+		TransportFactory f = getTransportFactory( u.getScheme() );
+		return f.newListener( uri, resources );
+	}
+
+	/**
+	 * Adds any message filters specified on the uri. They are added in order
+	 * from transport to session. The first filter is the session for Messagizer,
+	 * the second is the session for the first, etc. The last filter added is
+	 * returned, and becomes the TransportMessage for what follows.
+	 * @param transport
+	 * @param uri
+	 * @param resources
+	 * @return the newly added filter
+	 */
+	protected TransportMessage addFilters( TransportMessage transport, URL uri,
+		Resources resources )
+	{
+		String s = uri.getTerm( FILTER );
+		if (s == null || s.length() == 0)
+			return transport;
+		
+		StringTokenizer st = new StringTokenizer( s, ",:;| \t\r\n" );
+		while (st.hasMoreTokens())
+		{
+			String t = st.nextToken();
+			transport = addFilter( transport, t, uri, resources );
+		}
+		
+		return transport;
+	}
+	
+	/**
+	 * Query term on the transport uri which defines a set of filters which
+	 * process messages as they move up and down the transport stack. Filter
+	 * names are separated by one or more of these characters: ",:;| \t\r\n".
+	 */
+	public final static String FILTER = "filter";
+
+	private TransportMessage addFilter( TransportMessage transport, String name,
+		URL uri, Resources resources )
+	{
+		String className = getFilter( name );
+		
+		if (className == null)
+			throw new IllegalArgumentException(
+				String.format( "Filter name '%s' not defined", name ) );
+		
+		Class<?> clss;
+		
+		try
+		{
+			clss = Class.forName( className );
+		}
+		catch ( ClassNotFoundException e )
+		{
+			throw new IllegalArgumentException(
+				String.format( "Class '%s' for filter name '%s' not defined",
+					className, name ) );
+		}
+		
+		if (!TransportMessage.class.isAssignableFrom( clss ))
+			throw new IllegalArgumentException(
+				String.format( "Class '%s' for filter name '%s' does not implement TransportMessage",
+					className, name ) );
+		
+		if (!SessionMessage.class.isAssignableFrom( clss ))
+			throw new IllegalArgumentException(
+				String.format( "Class '%s' for filter name '%s' does not implement SessionMessage",
+					className, name ) );
+		
+		Constructor<?> c;
+		
+		try
+		{
+			c = clss.getConstructor( PARAMS );
+		}
+		catch ( SecurityException e )
+		{
+			throw new IllegalArgumentException(
+				String.format( "Constructor %s(TransportMessage, URL, Resources) for filter name '%s' cannot be accessed",
+					className, name ) );
+		}
+		catch ( NoSuchMethodException e )
+		{
+			throw new IllegalArgumentException(
+				String.format( "Constructor %s(TransportMessage, URL, Resources) for filter name '%s' not defined",
+					className, name ) );
+		}
+		
+		try
+		{
+			return (TransportMessage) c.newInstance( new Object[] { transport, uri, resources } );
+		}
+		catch ( IllegalArgumentException e )
+		{
+			throw new IllegalArgumentException(
+				String.format( "Constructor %s(TransportMessage, URL, Resources) for filter name '%s' failed",
+					className, name ), e );
+		}
+		catch ( InstantiationException e )
+		{
+			throw new IllegalArgumentException(
+				String.format( "Constructor %s(TransportMessage, URL, Resources) for filter name '%s' failed",
+					className, name ), e );
+		}
+		catch ( IllegalAccessException e )
+		{
+			throw new IllegalArgumentException(
+				String.format( "Constructor %s(TransportMessage, URL, Resources) for filter name '%s' failed",
+					className, name ), e );
+		}
+		catch ( InvocationTargetException e )
+		{
+			throw new IllegalArgumentException(
+				String.format( "Constructor %s(TransportMessage, URL, Resources) for filter name '%s' failed",
+					className, name ), e.getTargetException() );
+		}
+	}
+	
+	/**
+	 * @param name the filter name.
+	 * @return the fully qualified class name of the filter.
+	 */
+	public static String getFilter( String name )
+	{
+		return filters.get( name );
+	}
+	
+	/**
+	 * Sets the fully qualified class name of the filter.
+	 * @param name the filter name.
+	 * @param className the fully qualified class name of the filter.
+	 */
+	public static void defineFilter( String name, String className )
+	{
+		filters.put( name, className );
+	}
+	
+	private final static Map<String, String> filters =
+		Collections.synchronizedMap( new HashMap<String, String>() );
+	
+	private final static Class<?>[] PARAMS = { TransportMessage.class, URL.class, Resources.class };
+	
+	static
+	{
+		defineFilter( "KeepAlive", "org.apache.etch.bindings.java.transport.filters.KeepAlive" );
+		defineFilter( "PwAuth", "org.apache.etch.bindings.java.transport.filters.PwAuth" );
+		defineFilter( "Logger", "org.apache.etch.bindings.java.transport.filters.Logger" );
+	}
+	
+	/**
+	 * Gets the named transport factory.
+	 * @param name the name of a configured transport factory.
+	 * @return the named transport factory.
+	 * @throws Exception if the transport factory is not defined.
+	 */
+	private static TransportFactory getTransportFactory( String name ) throws Exception
+	{
+		Object tfspec = get( name );
+		
+		if (tfspec == null)
+			throw new IOException( "transport factory scheme '"+name+"' unknown" );
+		
+		if (tfspec instanceof String)
+			tfspec = Class.forName( (String) tfspec );
+		
+		if (tfspec instanceof Class<?>)
+			tfspec = ((Class<?>) tfspec).newInstance();
+		
+		if (tfspec instanceof TransportFactory)
+			return (TransportFactory) tfspec;
+		
+		throw new IllegalArgumentException(String.format(
+			"Cannot create an instance of TransportFactory from transport factory name '%s'", name ) );
+	}
+	
+	/**
+	 * Gets the named transport factory spec.
+	 * @param name
+	 * @return the transport factory spec.
+	 */
+	public static Object get(String name)
+	{
+		return transportFactories.get( name );
+	}
+	
+	/**
+	 * Defines a transport factory.
+	 * @param name the uri scheme of this transport factory.
+	 * @param tfspec the transport factory to associate with the name. This may
+	 * either be an instance of TransportFactory or a class which is a subclass
+	 * of TransportFactory or a string which is a name of a class which is a
+	 * subclass of transport factory.
+	 */
+	public static void define( String name, Object tfspec )
+	{
+		transportFactories.put( name, tfspec );
+	}
+	
+	private final static Map<String, Object> transportFactories =
+		Collections.synchronizedMap( new HashMap<String, Object>() );
+	
+	static
+	{
+		define( "tcp", new TcpTransportFactory( false ) );
+		define( "tls", new TcpTransportFactory( true ) );
+	}
+}
\ No newline at end of file
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/TransportHelper.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/TransportHelper.java
new file mode 100644
index 0000000..5d1d6b9
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/TransportHelper.java
@@ -0,0 +1,75 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.util.Resources;
+
+/**
+ * Class to help construct transport stacks.
+ */
+public class TransportHelper
+{
+	///////////////
+	// RESOURCES //
+	///////////////
+
+	/** The Pool to use to execute queued async receiver messages. */
+	public static final String QUEUED_POOL = "QUEUED_POOL";
+	
+	/** The Pool to use to execute free async receiver messages. */
+	public static final String FREE_POOL = "FREE_POOL";
+	
+	/** Binary transport format */
+	public final static String BINARY = "binary";
+	
+	/** Xml transport format */
+	public final static String XML = "xml";
+
+	///////////////
+	// UTILITIES //
+	///////////////
+	
+	/**
+	 * Initializes standard resources.
+	 * 
+	 * @param resources some initial values for resources. May be null to accept
+	 * all the defaults.
+	 * @return copy of resources initialized with default values for standard
+	 * items.
+	 * @throws Exception
+	 */
+	public static Resources initResources( Resources resources ) throws Exception
+	{
+		if (resources == null)
+			resources = new Resources();
+		else
+			resources = new Resources( resources );
+		
+		if (!resources.containsKey( QUEUED_POOL ))
+			resources.put( QUEUED_POOL, new QueuedPool() );
+		
+		if (!resources.containsKey( FREE_POOL ))
+			resources.put( FREE_POOL, new FreePool() );
+		
+		return resources;
+	}
+}
+
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/TypeValidator.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/TypeValidator.java
new file mode 100644
index 0000000..7db94a3
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/TypeValidator.java
@@ -0,0 +1,152 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import java.lang.reflect.Array;
+
+import org.apache.etch.bindings.java.msg.Validator;
+
+
+/**
+ * Base class of validators which validate based on exact type.
+ */
+abstract public class TypeValidator implements Validator
+{
+	/**
+	 * Constructs the TypeValidator.
+	 *
+	 * @param scalarClass class to use if nDims == 0
+	 * @param arrayClass class to use if nDims > 0
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 * @param descr a description of the expected value.
+	 */
+	public TypeValidator( Class<?> scalarClass, Class<?> arrayClass, int nDims,
+		String descr )
+	{
+		this( scalarClass, arrayClass, nDims, descr, false );
+	}
+	
+	/**
+	 * Constructs the TypeValidator.
+	 *
+	 * @param scalarClass class to use if nDims == 0
+	 * @param arrayClass class to use if nDims > 0
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 * @param descr a description of the expected value.
+	 * @param subclassOk true of a subclass of the expected class is ok.
+	 */
+	public TypeValidator( Class<?> scalarClass, Class<?> arrayClass, int nDims,
+		String descr, boolean subclassOk )
+	{
+		checkDims( nDims );
+		expectedClass = mkExpectedClass( scalarClass, arrayClass, nDims );
+		this.nDims = nDims;
+		this.descr = descr;
+		this.subclassOk = subclassOk;
+	}
+	
+	private final Class<?> expectedClass;
+	
+	/**
+	 * The number of dimensions if this is an array.
+	 */
+	protected final int nDims;
+	
+	private final String descr;
+	
+	/**
+	 * Allow subclassing of this type.
+	 */
+	protected final boolean subclassOk;
+	
+	/**
+	 * Checks the number of dimensions for standard validators.
+	 * @param nDims
+	 * @throws IllegalArgumentException if nDims < 0 || nDims > MAX_NDIMS
+	 * @see #MAX_NDIMS
+	 */
+	public final static void checkDims( int nDims )
+		throws IllegalArgumentException
+	{
+		if (nDims < 0 || nDims > MAX_NDIMS)
+			throw new IllegalArgumentException( "nDims < 0 || nDims > MAX_NDIMS" );
+	}
+
+	/**
+	 * @return the expected class of this validator.
+	 */
+	public Class<?> getExpectedClass()
+	{
+		return expectedClass;
+	}
+	
+	/**
+	 * @return the expected number of dimensions.
+	 */
+	public int getNDims()
+	{
+		return nDims;
+	}
+	
+	@Override
+	final public String toString()
+	{
+		return descr;
+	}
+	
+	public boolean validate( Object value )
+	{
+		if (value == null)
+			return false;
+		
+		Class<?> clss = value.getClass();
+		
+		if (clss == expectedClass)
+			return true;
+		
+		// if clss is a subclass of expectedClass, that's ok.
+		
+		return subclassOk && expectedClass.isAssignableFrom( clss );
+	}
+
+	public Object validateValue( Object value )
+	{
+		if (validate( value ))
+			return value;
+		
+		throw new IllegalArgumentException( "value not appropriate for "+descr+": "+value );
+	}
+	
+	/**
+	 * @param scalarClass class to use if nDims == 0
+	 * @param arrayClass class to use if nDims > 0
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 * @return an appropriate class given nDims.
+	 */
+	private static Class<?> mkExpectedClass( Class<?> scalarClass,
+		Class<?> arrayClass, int nDims )
+	{
+		if (nDims == 0)
+			return scalarClass;
+		
+		return Array.newInstance( arrayClass, new int[nDims] ).getClass();
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_RuntimeException.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_RuntimeException.java
new file mode 100644
index 0000000..1594eca
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_RuntimeException.java
@@ -0,0 +1,68 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Validator;
+
+/**
+ * Validator for RuntimeException.
+ */
+public class Validator_RuntimeException implements Validator
+{
+	/**
+	 * @return an instance of the validator.
+	 */
+	public static Validator_RuntimeException get()
+	{
+		if (validator == null)
+			validator = new Validator_RuntimeException();
+		
+		return validator;
+	}
+	
+	private static Validator_RuntimeException validator;
+	
+	/**
+	 * Constructs the Validator.
+	 */
+	private Validator_RuntimeException()
+	{
+		// nothing to do.
+	}
+
+	public Validator elementValidator()
+	{
+		throw new IllegalArgumentException( "not an array" );
+	}
+	
+	public boolean validate( Object value )
+	{
+		return value instanceof RuntimeException;
+	}
+
+	public Object validateValue( Object value )
+	{
+		if (validate( value ))
+			return value;
+		
+		throw new IllegalArgumentException( "value not appropriate for RuntimeException: "+value );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_StructValue.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_StructValue.java
new file mode 100644
index 0000000..27ae59a
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_StructValue.java
@@ -0,0 +1,87 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.Validator;
+
+/**
+ * Validator for StructValue.
+ */
+public class Validator_StructValue extends TypeValidator
+{
+	/**
+	 * @param type the expected type of a scalar StructValue.
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 * @return an instance of the validator.
+	 */
+	public static Validator_StructValue get( Type type, int nDims )
+	{
+		checkDims( nDims );
+		
+//		if (nDims >= validators.length)
+			return new Validator_StructValue( type, nDims );
+		
+//		Validator_StructValue v = validators[nDims];
+//
+//		if (v == null)
+//			v = validators[nDims] = new Validator_StructValue( type, nDims );
+//
+//		return v;
+	}
+	
+//	private static Validator_StructValue[] validators = new Validator_StructValue[MAX_CACHED];
+	
+	/**
+	 * Constructs the Validator.
+	 *
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 */
+	private Validator_StructValue( Type type, int nDims )
+	{
+		super( StructValue.class, StructValue.class, nDims, "StructValue["+type+", "+nDims+"]" );
+		this.type = type;
+	}
+	
+	private final Type type;
+
+	/**
+	 * @return the type of this validator.
+	 */
+	public Type getType()
+	{
+		return type;
+	}
+
+	public Validator elementValidator()
+	{
+		return get( type, nDims-1 );
+	}
+
+	@Override
+	public boolean validate( Object value )
+	{
+		return super.validate( value ) &&
+			(value.getClass() != StructValue.class ||
+				type.isAssignableFrom( ((StructValue) value).type() ) );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_boolean.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_boolean.java
new file mode 100644
index 0000000..e0acfc9
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_boolean.java
@@ -0,0 +1,65 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Validator;
+
+/**
+ * Validator for boolean.
+ */
+public class Validator_boolean extends TypeValidator
+{
+	/**
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 * @return an instance of the validator.
+	 */
+	public static Validator_boolean get( int nDims )
+	{
+		checkDims( nDims );
+		
+		if (nDims >= validators.length)
+			return new Validator_boolean( nDims );
+		
+		Validator_boolean v = validators[nDims];
+		
+		if (v == null)
+			v = validators[nDims] = new Validator_boolean( nDims );
+		
+		return v;
+	}
+	
+	private static Validator_boolean[] validators = new Validator_boolean[MAX_CACHED];
+	
+	/**
+	 * Constructs the Validator.
+	 *
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 */
+	private Validator_boolean( int nDims )
+	{
+		super( Boolean.class, boolean.class, nDims, "boolean["+nDims+"]" );
+	}
+
+	public Validator elementValidator()
+	{
+		return get( nDims-1 );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_byte.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_byte.java
new file mode 100644
index 0000000..5677637
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_byte.java
@@ -0,0 +1,111 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Validator;
+
+/**
+ * Validator for byte.
+ */
+public class Validator_byte extends TypeValidator
+{
+	/**
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 * @return an instance of the validator.
+	 */
+	public static Validator_byte get( int nDims )
+	{
+		checkDims( nDims );
+		
+		if (nDims >= validators.length)
+			return new Validator_byte( nDims );
+		
+		Validator_byte v = validators[nDims];
+		
+		if (v == null)
+			v = validators[nDims] = new Validator_byte( nDims );
+		
+		return v;
+	}
+	
+	private static Validator_byte[] validators = new Validator_byte[MAX_CACHED];
+	
+	/**
+	 * Constructs the Validator.
+	 *
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 */
+	private Validator_byte( int nDims )
+	{
+		super( Byte.class, byte.class, nDims, "byte["+nDims+"]" );
+	}
+
+	public Validator elementValidator()
+	{
+		return get( nDims-1 );
+	}
+	
+	@Override
+	public boolean validate( Object value )
+	{
+		if (nDims > 0)
+			return super.validate( value );
+		
+		if (value == null)
+			return false;
+		
+		Class<?> c = value.getClass();
+		
+		if (c == Byte.class)
+			return true;
+		
+		if (c == Short.class)
+		{
+			short v = (Short) value;
+			return v >= Byte.MIN_VALUE && v <= Byte.MAX_VALUE;
+		}
+		
+		if (c == Integer.class)
+		{
+			int v = (Integer) value;
+			return v >= Byte.MIN_VALUE && v <= Byte.MAX_VALUE;
+		}
+		
+		if (c == Long.class)
+		{
+			long v = (Long) value;
+			return v >= Byte.MIN_VALUE && v <= Byte.MAX_VALUE;
+		}
+		
+		return false;
+	}
+	
+	@Override
+	public Object validateValue( Object value )
+	{
+		value = super.validateValue( value );
+		
+		if (value.getClass() == Byte.class || nDims > 0)
+			return value;
+		
+		return ((Number) value).byteValue();
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_custom.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_custom.java
new file mode 100644
index 0000000..3c0d48f
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_custom.java
@@ -0,0 +1,133 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.bindings.java.msg.Validator;
+
+
+/**
+ * Validator for custom type.
+ */
+public class Validator_custom extends TypeValidator
+{
+	/**
+	 * @param clss the class of the custom type.
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 * @param subclassOk if true allow subclasses of the
+	 * class.
+	 * @return an instance of Validator.
+	 */
+	public static Validator get( Class<?> clss, int nDims, boolean subclassOk )
+	{
+		checkDims( nDims );
+		
+		if (nDims > MAX_CACHED)
+			return new Validator_custom( clss, nDims, subclassOk );
+		
+		Key key = new Key( clss, nDims, subclassOk );
+		Validator v = validators.get( key );
+		
+		if (v == null)
+		{
+			v = new Validator_custom( clss, nDims, subclassOk );
+			validators.put( key, v );
+		}
+		
+		return v;
+	}
+	
+	private static class Key
+	{
+		/**
+		 * Constructs the key
+		 * @param clss
+		 * @param dims
+		 * @param subclassOk
+		 */
+		public Key( Class<?> clss, int dims, boolean subclassOk )
+		{
+			this.clss = clss;
+			this.dims = dims;
+			this.subclassOk = subclassOk;
+		}
+		
+		private final Class<?> clss;
+		
+		private final int dims;
+		
+		private final boolean subclassOk;
+		
+		@Override
+		public int hashCode()
+		{
+			return clss.hashCode() ^ dims * 9131 ^ (subclassOk ? 21357 : 8547);
+		}
+		
+		@Override
+		public boolean equals( Object obj )
+		{
+			if (obj == this)
+				return true;
+			
+			if (obj == null)
+				return false;
+			
+			if (obj.getClass() != getClass())
+				return false;
+			
+			Key other = (Key) obj;
+			
+			return other.clss.equals( clss)
+				&& other.dims == dims
+				&& other.subclassOk == subclassOk;
+		}
+	}
+	
+	private final static Map<Key, Validator> validators =
+		Collections.synchronizedMap( new HashMap<Key, Validator>() );
+	
+	/**
+	 * Constructs the Validator.
+	 *
+	 * @param clss the class of the custom type.
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 */
+	private Validator_custom( Class<?> clss, int nDims, boolean subclassOk )
+	{
+		super( clss, clss, nDims,
+			subclassOk
+				? clss.toString()+"["+nDims+"]*"
+				: clss.toString()+"["+nDims+"]",
+			subclassOk );
+		this.clss = clss;
+	}
+	
+	private final Class<?> clss;
+
+	public Validator elementValidator()
+	{
+		return get( clss, nDims-1, subclassOk );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_double.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_double.java
new file mode 100644
index 0000000..3230590
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_double.java
@@ -0,0 +1,65 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Validator;
+
+/**
+ * Validator for double.
+ */
+public class Validator_double extends TypeValidator
+{
+	/**
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 * @return an instance of the validator.
+	 */
+	public static Validator_double get( int nDims )
+	{
+		checkDims( nDims );
+		
+		if (nDims >= validators.length)
+			return new Validator_double( nDims );
+		
+		Validator_double v = validators[nDims];
+		
+		if (v == null)
+			v = validators[nDims] = new Validator_double( nDims );
+		
+		return v;
+	}
+	
+	private static Validator_double[] validators = new Validator_double[MAX_CACHED];
+	
+	/**
+	 * Constructs the Validator.
+	 *
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 */
+	private Validator_double( int nDims )
+	{
+		super( Double.class, double.class, nDims, "double["+nDims+"]" );
+	}
+
+	public Validator elementValidator()
+	{
+		return get( nDims-1 );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_float.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_float.java
new file mode 100644
index 0000000..bb7a782
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_float.java
@@ -0,0 +1,65 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Validator;
+
+/**
+ * Validator for float.
+ */
+public class Validator_float extends TypeValidator
+{
+	/**
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 * @return an instance of the validator.
+	 */
+	public static Validator_float get( int nDims )
+	{
+		checkDims( nDims );
+		
+		if (nDims >= validators.length)
+			return new Validator_float( nDims );
+		
+		Validator_float v = validators[nDims];
+		
+		if (v == null)
+			v = validators[nDims] = new Validator_float( nDims );
+		
+		return v;
+	}
+	
+	private static Validator_float[] validators = new Validator_float[MAX_CACHED];
+	
+	/**
+	 * Constructs the Validator.
+	 *
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 */
+	private Validator_float( int nDims )
+	{
+		super( Float.class, float.class, nDims, "float["+nDims+"]" );
+	}
+
+	public Validator elementValidator()
+	{
+		return get( nDims-1 );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_int.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_int.java
new file mode 100644
index 0000000..f88e015
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_int.java
@@ -0,0 +1,99 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Validator;
+
+/**
+ * Validator for int.
+ */
+public class Validator_int extends TypeValidator
+{
+	/**
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 * @return an instance of the validator.
+	 */
+	public static Validator_int get( int nDims )
+	{
+		checkDims( nDims );
+		
+		if (nDims >= validators.length)
+			return new Validator_int( nDims );
+		
+		Validator_int v = validators[nDims];
+		
+		if (v == null)
+			v = validators[nDims] = new Validator_int( nDims );
+		
+		return v;
+	}
+	
+	private static Validator_int[] validators = new Validator_int[MAX_CACHED];
+	
+	/**
+	 * Constructs the Validator.
+	 *
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 */
+	private Validator_int( int nDims )
+	{
+		super( Integer.class, int.class, nDims, "int["+nDims+"]" );
+	}
+
+	public Validator elementValidator()
+	{
+		return get( nDims-1 );
+	}
+	
+	@Override
+	public boolean validate( Object value )
+	{
+		if (nDims > 0)
+			return super.validate( value );
+		
+		if (value == null)
+			return false;
+		
+		Class<?> c = value.getClass();
+		
+		if (c == Integer.class || c == Short.class || c == Byte.class)
+			return true;
+		
+		if (c == Long.class)
+		{
+			long v = (Long) value;
+			return v >= Integer.MIN_VALUE && v <= Integer.MAX_VALUE;
+		}
+		
+		return false;
+	}
+	
+	@Override
+	public Object validateValue( Object value )
+	{
+		value = super.validateValue( value );
+		
+		if (value.getClass() == Integer.class || nDims > 0)
+			return value;
+		
+		return ((Number) value).intValue();
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_long.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_long.java
new file mode 100644
index 0000000..7836b78
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_long.java
@@ -0,0 +1,91 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Validator;
+
+/**
+ * Validator for long.
+ */
+public class Validator_long extends TypeValidator
+{
+	/**
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 * @return an instance of the validator.
+	 */
+	public static Validator_long get( int nDims )
+	{
+		checkDims( nDims );
+		
+		if (nDims >= validators.length)
+			return new Validator_long( nDims );
+		
+		Validator_long v = validators[nDims];
+		
+		if (v == null)
+			v = validators[nDims] = new Validator_long( nDims );
+		
+		return v;
+	}
+	
+	private static Validator_long[] validators = new Validator_long[MAX_CACHED];
+	
+	/**
+	 * Constructs the Validator.
+	 *
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 */
+	private Validator_long( int nDims )
+	{
+		super( Long.class, long.class, nDims, "long["+nDims+"]" );
+	}
+
+	public Validator elementValidator()
+	{
+		return get( nDims-1 );
+	}
+	
+	@Override
+	public boolean validate( Object value )
+	{
+		if (nDims > 0)
+			return super.validate( value );
+		
+		if (value == null)
+			return false;
+		
+		Class<?> c = value.getClass();
+		
+		return c == Long.class || c == Integer.class ||
+			c == Short.class || c == Byte.class;
+	}
+	
+	@Override
+	public Object validateValue( Object value )
+	{
+		value = super.validateValue( value );
+		
+		if (value.getClass() == Long.class || nDims > 0)
+			return value;
+		
+		return ((Number) value).longValue();
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_object.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_object.java
new file mode 100644
index 0000000..6b444b6
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_object.java
@@ -0,0 +1,65 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Validator;
+
+/**
+ * Validator for object.
+ */
+public class Validator_object extends TypeValidator
+{
+	/**
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 * @return an instance of the validator.
+	 */
+	public static Validator_object get( int nDims )
+	{
+		checkDims( nDims );
+		
+		if (nDims >= validators.length)
+			return new Validator_object( nDims );
+		
+		Validator_object v = validators[nDims];
+		
+		if (v == null)
+			v = validators[nDims] = new Validator_object( nDims );
+		
+		return v;
+	}
+	
+	private static Validator_object[] validators = new Validator_object[MAX_CACHED];
+	
+	/**
+	 * Constructs the Validator.
+	 *
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 */
+	private Validator_object( int nDims )
+	{
+		super( Object.class, Object.class, nDims, "object["+nDims+"]", true );
+	}
+
+	public Validator elementValidator()
+	{
+		return nDims > 0 ? get( nDims-1 ) : this;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_short.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_short.java
new file mode 100644
index 0000000..e803123
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_short.java
@@ -0,0 +1,105 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Validator;
+
+/**
+ * Validator for short.
+ */
+public class Validator_short extends TypeValidator
+{
+	/**
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 * @return an instance of the validator.
+	 */
+	public static Validator_short get( int nDims )
+	{
+		checkDims( nDims );
+		
+		if (nDims >= validators.length)
+			return new Validator_short( nDims );
+		
+		Validator_short v = validators[nDims];
+		
+		if (v == null)
+			v = validators[nDims] = new Validator_short( nDims );
+		
+		return v;
+	}
+	
+	private static Validator_short[] validators = new Validator_short[MAX_CACHED];
+	
+	/**
+	 * Constructs the Validator.
+	 *
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 */
+	private Validator_short( int nDims )
+	{
+		super( Short.class, short.class, nDims, "short["+nDims+"]" );
+	}
+
+	public Validator elementValidator()
+	{
+		return get( nDims-1 );
+	}
+	
+	@Override
+	public boolean validate( Object value )
+	{
+		if (nDims > 0)
+			return super.validate( value );
+		
+		if (value == null)
+			return false;
+		
+		Class<?> c = value.getClass();
+		
+		if (c == Short.class || c == Byte.class)
+			return true;
+		
+		if (c == Integer.class)
+		{
+			int v = (Integer) value;
+			return v >= Short.MIN_VALUE && v <= Short.MAX_VALUE;
+		}
+		
+		if (c == Long.class)
+		{
+			long v = (Long) value;
+			return v >= Short.MIN_VALUE && v <= Short.MAX_VALUE;
+		}
+		
+		return false;
+	}
+	
+	@Override
+	public Object validateValue( Object value )
+	{
+		value = super.validateValue( value );
+		
+		if (value.getClass() == Short.class || nDims > 0)
+			return value;
+		
+		return ((Number) value).shortValue();
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_string.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_string.java
new file mode 100644
index 0000000..0d66cc3
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_string.java
@@ -0,0 +1,65 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Validator;
+
+/**
+ * Validator for string.
+ */
+public class Validator_string extends TypeValidator
+{
+	/**
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 * @return an instance of the validator.
+	 */
+	public static Validator_string get( int nDims )
+	{
+		checkDims( nDims );
+		
+		if (nDims >= validators.length)
+			return new Validator_string( nDims );
+		
+		Validator_string v = validators[nDims];
+		
+		if (v == null)
+			v = validators[nDims] = new Validator_string( nDims );
+		
+		return v;
+	}
+	
+	private static Validator_string[] validators = new Validator_string[MAX_CACHED];
+	
+	/**
+	 * Constructs the Validator.
+	 *
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 */
+	private Validator_string( int nDims )
+	{
+		super( String.class, String.class, nDims, "string["+nDims+"]" );
+	}
+
+	public Validator elementValidator()
+	{
+		return get( nDims-1 );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_void.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_void.java
new file mode 100644
index 0000000..3375934
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/Validator_void.java
@@ -0,0 +1,72 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.apache.etch.bindings.java.msg.Validator;
+
+/**
+ * Validator for void.
+ */
+public class Validator_void implements Validator
+{
+	/**
+	 * @param nDims the number of dimensions. 0 for a scalar.
+	 * @return an instance of the validator.
+	 */
+	public static Validator_void get( int nDims )
+    {
+		if (nDims != 0)
+			throw new IllegalArgumentException( "nDims != 0" );
+		
+		if (validator == null)
+			validator = new Validator_void();
+		
+		return validator;
+    }
+	
+	private static Validator_void validator;
+	
+	/**
+	 * Constructs the Validator.
+	 */
+	private Validator_void()
+	{
+		// nothing to do.
+	}
+
+    public Validator elementValidator()
+    {
+	    return null;
+    }
+
+	final public boolean validate( Object value )
+	{
+		return value == null;
+	}
+
+	public Object validateValue( Object value )
+	{
+		if (validate( value ))
+			return value;
+		
+		throw new IllegalArgumentException( "value not appropriate for void: "+value );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/_Etch_AuthException.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/_Etch_AuthException.java
new file mode 100644
index 0000000..5de58c1
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/_Etch_AuthException.java
@@ -0,0 +1,47 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+/**
+ * Exception thrown when messages marked with @Authorize fail.
+ */
+public class _Etch_AuthException extends _Etch_RuntimeException
+{
+	private static final long serialVersionUID = -5541931265968145750L;
+
+	/**
+	 * Constructs the _Etch_AuthException.
+	 */
+	public _Etch_AuthException()
+	{
+		// don't init anything.
+	}
+
+	/**
+	 * Constructs the _Etch_AuthException.
+	 * 
+	 * @param msg a message describing the failure.
+	 */
+	public _Etch_AuthException( String msg )
+	{
+		super( msg );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/_Etch_RuntimeException.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/_Etch_RuntimeException.java
new file mode 100644
index 0000000..c3daf49
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/support/_Etch_RuntimeException.java
@@ -0,0 +1,76 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+/**
+ * A RuntimeException which exposes its msg field. Returned by the stub
+ * to the remote when the stub catches a RuntimeException.
+ * 
+ * Some common runtime exceptions are:
+ * 
+ * {@link ArithmeticException}
+ * {@link ClassCastException}
+ * {@link IllegalArgumentException}
+ * {@link IndexOutOfBoundsException}
+ * {@link NullPointerException}
+ * {@link UnsupportedOperationException}
+ */
+public class _Etch_RuntimeException
+	extends RuntimeException
+{
+	private static final long serialVersionUID = 3051515541923877063L;
+
+	/**
+	 * Constructs the EtchRuntimeException. Don't init anything.
+	 */
+	public _Etch_RuntimeException()
+	{
+		// don't init anything.
+	}
+	
+	/**
+	 * Constructs the EtchRuntimeException.
+	 * @param msg description of the exception that was caught by the stub
+	 * on the remote side.
+	 */
+	public _Etch_RuntimeException( String msg )
+	{
+		this.msg = msg;
+	}
+
+	@Override
+	public String getMessage()
+	{
+		return msg;
+	}
+
+	/**
+	 * Description of the exception that was caught by the stub
+	 * on the remote side.
+	 */
+	public String msg;
+	
+	@Override
+	public String toString()
+	{
+		return "Remote side threw this runtime exception: "+getMessage();
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/ArrayValue.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/ArrayValue.java
new file mode 100644
index 0000000..4631184
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/ArrayValue.java
@@ -0,0 +1,173 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import java.lang.reflect.Array;
+import java.util.Iterator;
+
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.util.ArrayIterator;
+
+
+/**
+ * An array of values, where each value is of arbitrary type
+ * chosen from the basic java types boolean, byte, short, int,
+ * long, float, double, String, an array of those, the extended
+ * types ArrayValue and StructValue, and specific types supported
+ * by ValueFactory.
+ * 
+ * ArrayValue is not protected against concurrent access.
+ */
+public final class ArrayValue implements Iterable<Object>
+{
+	/**
+	 * Constructs the ArrayValue.
+	 * @param array
+	 * @param dim
+	 * @param customStructType
+	 * @param typeCode
+	 */
+	public ArrayValue( Object array, byte typeCode, Type customStructType, int dim )
+	{
+		if (array == null)
+			throw new NullPointerException( "array == null" );
+		
+		if (!array.getClass().isArray())
+			throw new IllegalArgumentException( "!array.getClass().isArray()" );
+		
+		this.array = array;
+		this.typeCode = typeCode;
+		this.customStructType = customStructType;
+		this.dim = dim;
+	}
+	
+	/**
+	 * Constructs an array value with no type info. This is used perhaps
+	 * by extern struct serializers.
+	 * @param array
+	 */
+	public ArrayValue( Object array )
+	{
+		this( array, (byte) 0, null, 0 );
+	}
+	
+	private Object array;
+	
+	private final byte typeCode;
+	
+	private final Type customStructType;
+	
+	private final int dim;
+	
+	/**
+	 * @return the TypeCode for this array value.
+	 * For example, if the array is int[][], then
+	 * the type would be TypeCode.INT4.
+	 */
+	public byte typeCode()
+	{
+		return typeCode;
+	}
+	
+	/**
+	 * @return a struct type if a custom type code.
+	 */
+	public Type customStructType()
+	{
+		return customStructType;
+	}
+	
+	/**
+	 * @return the dimsionality of the array.
+	 * For example, if the array is int[][], the
+	 * dimensionality would be 2.
+	 */
+	public int dim()
+	{
+		return dim;
+	}
+
+	public Iterator<Object> iterator()
+	{
+		return new ArrayIterator( array );
+	}
+
+	/**
+	 * @return the number of elements in the array.
+	 */
+	public int size()
+	{
+		return Array.getLength( array );
+	}
+
+	/**
+	 * @param index
+	 * @return the element at the specified index.
+	 */
+	public Object get( int index )
+	{
+		return Array.get( array, index );
+	}
+
+	/**
+	 * Reallocates the array so that it is only as long as needed.
+	 */
+	public void compact()
+	{
+		if (addIndex == size())
+			return;
+		
+		Object narray = Array.newInstance( array.getClass().getComponentType(), addIndex );
+		System.arraycopy( array, 0, narray, 0, addIndex );
+		array = narray;
+	}
+
+	/**
+	 * Adds the value to the end of the array, making more space
+	 * available if needed.
+	 * @param value
+	 */
+	public void add( Object value )
+	{
+		int n = size();
+		if (addIndex >= n)
+		{
+			if (n == 0)
+				n = 8;
+			else
+				n *= 2;
+			Object narray = Array.newInstance( array.getClass().getComponentType(), n );
+			System.arraycopy( array, 0, narray, 0, addIndex );
+			array = narray;
+		}
+		Array.set( array, addIndex++, value );
+	}
+	
+	private int addIndex;
+
+	/**
+	 * @return the array value.
+	 */
+	public Object getArray()
+	{
+		return array;
+	}
+}
\ No newline at end of file
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/DefaultDeliveryService.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/DefaultDeliveryService.java
new file mode 100644
index 0000000..8ae9929
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/DefaultDeliveryService.java
@@ -0,0 +1,221 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.support.DeliveryService;
+import org.apache.etch.bindings.java.support.Mailbox;
+import org.apache.etch.util.Monitor;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.TimeoutException;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.Who;
+
+
+/**
+ * Default implementation of DeliveryService.
+ */
+public class DefaultDeliveryService implements DeliveryService
+{
+	
+	/**
+	 * Parameter to Globally Disable Timeout.
+	 */
+	public final static String DISABLE_TIMEOUT = "DefaultDeliveryService.disableTimeout";
+	
+	
+	private boolean disableTimeout = false;
+	
+	/**
+	 * @param transport
+	 * @param uri
+	 * @param resources
+	 */
+	public DefaultDeliveryService( MailboxManager transport, String uri,
+		Resources resources )
+	{
+		this( transport, new URL( uri ), resources );
+	}
+
+	/**
+	 * @param transport
+	 * @param uri
+	 * @param resources
+	 */
+	public DefaultDeliveryService( MailboxManager transport, URL uri,
+		Resources resources )
+	{
+		this.transport = transport;
+		transport.setSession( this );
+		disableTimeout = uri.getBooleanTerm( DISABLE_TIMEOUT , false );
+	}
+	
+	private final MailboxManager transport;
+	
+	/**
+	 * @return the transport.
+	 */
+	public MailboxManager getTransport()
+	{
+		return transport;
+	}
+	
+	public SessionMessage getSession()
+	{
+		return session;
+	}
+	
+	public void setSession( SessionMessage session )
+	{
+		if (this.session != null)
+			throw new UnsupportedOperationException( "only one stub for now" );
+		this.session = session;
+	}
+	
+	private SessionMessage session;
+
+	public Object sessionQuery( Object query ) throws Exception
+	{
+		return session.sessionQuery( query );
+	}
+
+	public void sessionControl( Object control, Object value ) throws Exception
+	{
+		session.sessionControl( control, value );
+	}
+
+	public void sessionNotify( Object event ) throws Exception
+	{
+		if (event == UP)
+			status.set( UP );
+		else if (event == DOWN)
+			status.set( DOWN );
+		
+		session.sessionNotify( event );
+	}
+	
+	private final Monitor<String> status = new Monitor<String>( "session status" );
+
+	public boolean sessionMessage( Who sender, Message msg ) throws Exception
+	{
+		return session.sessionMessage( sender, msg );
+	}
+
+	@Override
+	public String toString()
+	{
+		return transport.toString();
+	}
+	
+	private void waitUp( int maxDelay ) throws Exception
+	{
+		status.waitUntilEq( UP, maxDelay );
+	}
+	
+	private void waitDown( int maxDelay ) throws Exception
+	{
+		status.waitUntilEq( DOWN, maxDelay );
+	}
+
+	public void transportMessage( Who recipient, Message msg ) throws Exception
+	{
+		transport.transportMessage( recipient, msg );
+	}
+	
+	public Object transportQuery( Object query ) throws Exception
+	{
+		if (query.getClass() == WaitUp.class)
+		{
+			waitUp( ((WaitUp) query).maxDelay );
+			return null;
+		}
+		else if (query.getClass() == WaitDown.class)
+		{
+			waitDown( ((WaitDown) query).maxDelay );
+			return null;
+		}
+		else
+		{
+			return transport.transportQuery( query );
+		}
+	}
+	
+	public void transportControl( Object control, Object value ) throws Exception
+	{
+		if (control == START_AND_WAIT_UP)
+		{
+			transport.transportControl( START, null );
+			waitUp( (Integer) value );
+		}
+		else if (control == STOP_AND_WAIT_DOWN)
+		{
+			transport.transportControl( STOP, null );
+			waitDown( (Integer) value );
+		}
+		else
+		{
+			transport.transportControl( control, value );
+		}
+	}
+
+	public void transportNotify( Object event ) throws Exception
+	{
+		transport.transportNotify( event );
+	}
+
+	public Mailbox begincall( Message msg )
+	{
+		try
+		{
+			return transport.transportCall( null, msg );
+		}
+		catch ( Exception e )
+		{
+			throw new RuntimeException( "unexpected exception sending message", e );
+		}
+	}
+
+	public Object endcall( Mailbox mb, Type responseType ) throws Exception
+	{
+		try
+		{
+			int timeout = disableTimeout ? 0 : responseType.getTimeout();
+			Mailbox.Element mbe = mb.read( timeout);
+			if (mbe == null)
+				throw new TimeoutException( "timeout waiting for "+responseType );
+			Message rmsg = mbe.msg;
+			rmsg.checkType( responseType );
+			Object r = rmsg.get( responseType.getResponseField() );
+			if (r instanceof Exception)
+			{
+				Exception e = (Exception) r;
+				e.fillInStackTrace();
+				throw e;
+			}
+			return r;
+		}
+		finally
+		{
+			mb.closeRead();
+		}
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/FormatFactory.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/FormatFactory.java
new file mode 100644
index 0000000..022b44d
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/FormatFactory.java
@@ -0,0 +1,117 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.bindings.java.msg.ValueFactory;
+
+
+/**
+ * A factory used to construct tagged data processors for Messagizer.
+ */
+abstract public class FormatFactory
+{
+	/**
+	 * Standard name for etch binary tagged data format.
+	 */
+	public static final String BINARY = "binary";
+	
+	/**
+	 * Standard name for etch xml tagged data format.
+	 */
+	public static final String XML = "xml";
+	
+	/**
+	 * @param vf
+	 * @param uri
+	 * @return the tagged data input with the specified value factory and
+	 * initialized by terms from the uri.
+	 */
+	abstract public TaggedDataInput newTaggedDataInput( ValueFactory vf,
+		String uri );
+
+	/**
+	 * @param vf
+	 * @param uri
+	 * @return the tagged data output with the specified value factory and
+	 * initialized by terms from the uri.
+	 */
+	abstract public TaggedDataOutput newTaggedDataOutput( ValueFactory vf,
+		String uri );
+	
+	private final static Map<String, Object> formatFactories =
+		Collections.synchronizedMap( new HashMap<String, Object>() );
+	
+	/**
+	 * Gets the named format factory.
+	 * @param name the name of a configured format factory.
+	 * @return the named format factory, or null if it isn't defined.
+	 */
+	public static FormatFactory get( String name )
+	{
+		Object factory = formatFactories.get( name );
+		
+		if (factory == null)
+			return null;
+		
+		if (factory instanceof String)
+		{
+			try
+			{
+				Class<?> c = Class.forName( (String) factory );
+				factory = c.newInstance();
+				if (!(factory instanceof FormatFactory))
+					throw new IllegalArgumentException(
+						"instance for format name "+name+" ("+
+						factory+") does not implement FormatFactory" );
+				formatFactories.put( name, factory );
+				return (FormatFactory) factory;
+			}
+			catch ( Exception e )
+			{
+				throw new IllegalArgumentException(
+					"could not create instance of format name "+name, e );
+			}
+		}
+		
+		return (FormatFactory) factory;
+	}
+	
+	/**
+	 * Puts a named format factory.
+	 * @param name the name of this format factory (e.g., "binary").
+	 * @param factory the fully qualified class name or instance
+	 * of the FormatFactory to associate with the name.
+	 */
+	public static void put( String name, Object factory )
+	{
+		formatFactories.put( name, factory );
+	}
+	
+	static
+	{
+		put( BINARY,
+			"org.apache.etch.bindings.java.transport.fmt.binary.BinaryTaggedDataFormatFactory" );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/MailboxManager.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/MailboxManager.java
new file mode 100644
index 0000000..fb3ddfe
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/MailboxManager.java
@@ -0,0 +1,60 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.support.DeliveryService;
+import org.apache.etch.bindings.java.support.Mailbox;
+import org.apache.etch.util.core.Who;
+
+
+/**
+ * Interface to the mailbox manager as needed by {@link DeliveryService} and
+ * {@link Mailbox} implementors.
+ */
+public interface MailboxManager extends SessionMessage, TransportMessage
+{
+	/**
+	 * Sends a message which begins a call after allocating a Mailbox to
+	 * receive any responses.
+	 * @param recipient specifies the recipient when there is the possibility
+	 * of more than one.
+	 * @param msg the message which begins the call.
+	 * @return the mailbox which will receive responses to this call.
+	 * @throws Exception
+	 */
+	public Mailbox transportCall( Who recipient, Message msg ) throws Exception;
+	
+	/**
+	 * Removes the mailbox from the set of mailboxes receiving responses to
+	 * messages.
+	 * @param mb a mailbox as returned by {@link #transportCall(Who, Message)}.
+	 */
+	public void unregister( Mailbox mb );
+
+	/**
+	 * Re-delivers dead letter messages from a closed mailbox.
+	 * @param sender
+	 * @param msg
+	 * @throws Exception
+	 */
+	public void redeliver( Who sender, Message msg ) throws Exception;
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/Messagizer.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/Messagizer.java
new file mode 100644
index 0000000..48c05b6
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/Messagizer.java
@@ -0,0 +1,208 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.SessionPacket;
+import org.apache.etch.util.core.io.Transport;
+import org.apache.etch.util.core.io.TransportPacket;
+
+
+/**
+ * Messagizer is a PacketHandler which accepts packets from
+ * a PacketSource and turns them into messages for delivery
+ * to a MessageHandler. Messagizer is also a MessageSource,
+ * accepting messages and turning them into packets for delivery
+ * to a PacketSource.
+ */
+public final class Messagizer implements SessionPacket, TransportMessage
+{
+	/**
+	 * Name of format name in uri or resources. The value is "Messagizer.format".
+	 * The result of looking up this name should be a String.
+	 * 
+	 * @see #Messagizer(TransportPacket, String, Resources)
+	 */
+	public static final String FORMAT = "Messagizer.format";
+	
+	/**
+	 * Constructs the Messagizer with null handler and tagged data format
+	 * constructed from the format factory.
+	 * @param transport used to deliver packets to the peer
+	 * @param uri the uri being used to configure the transport stack.
+	 * @param resources the associated set of resources for this service.
+	 */
+	public Messagizer( TransportPacket transport, String uri, Resources resources )
+	{
+		this( transport, new URL( uri ), resources );
+	}
+	
+	/**
+	 * Constructs the Messagizer with null handler and tagged data format
+	 * constructed from the format factory.
+	 * @param transport used to deliver packets to the peer
+	 * @param uri the uri being used to configure the transport stack.
+	 * @param resources the associated set of resources for this service.
+	 */
+	public Messagizer( TransportPacket transport, URL uri, Resources resources )
+	{
+		// find the format.
+		
+		String format = uri.getTerm( FORMAT, FormatFactory.BINARY );
+		
+		// find the format factory.
+		
+		FormatFactory ff = FormatFactory.get( format );
+		if (ff == null)
+			throw new IllegalArgumentException(
+				String.format( "format factory is not defined as '%s' in format factories", format ) );
+		
+		// find the value factory.
+		
+		ValueFactory vf = (ValueFactory) resources.get( Transport.VALUE_FACTORY );
+		if (vf == null)
+			throw new IllegalArgumentException(
+				String.format( "value factory is not defined as '%s' in resources", Transport.VALUE_FACTORY ) );
+		
+		// construct the message formatters.
+		
+		this.transport = transport;
+		tdi = ff.newTaggedDataInput( vf, uri.toString() );
+		tdo = ff.newTaggedDataOutput( vf, uri.toString() );
+		
+		transport.setSession( this );
+	}
+	
+	private final TransportPacket transport;
+	
+	private final TaggedDataInput tdi;
+	
+	private final TaggedDataOutput tdo;
+	
+	/**
+	 * @return the transport.
+	 */
+	public TransportPacket getTransport()
+	{
+		return transport;
+	}
+	
+	@Override
+	public String toString()
+	{
+		return String.format( "Messagizer/%s", transport );
+	}
+
+    public void sessionPacket( Who sender, FlexBuffer buf ) throws Exception
+	{
+		// messagize the packet.
+		
+		Message msg = tdi.readMessage( buf );
+//		Log.report( "Messagizer.packet", "who", this, "recv", msg );
+		boolean handled = session.sessionMessage( sender, msg );
+		if (!handled)
+			session.sessionNotify( new UnwantedMessage( sender, msg ) );
+	}
+
+	////////////////////
+	// Message Source //
+	////////////////////
+	
+	public void transportMessage( Who recipient, Message msg ) throws Exception
+	{
+		// packetize the message.
+		
+		synchronized (msgBuf)
+		{
+			try
+			{
+//				Log.report( "Messagizer.packet", "who", this, "send", msg );
+				// assert that msgBuf is reset.
+				// leave space for the packet header
+				msgBuf.skip( transport.headerSize(), true );
+				tdo.writeMessage( msg, msgBuf );
+				msgBuf.setIndex( 0 );
+				transport.transportPacket( recipient, msgBuf );
+			}
+			finally
+			{
+				msgBuf.reset();
+			}
+		}
+	}
+	
+	private final FlexBuffer msgBuf = new FlexBuffer();
+	
+	///////////////////////////
+	// SourceHandler methods //
+	///////////////////////////
+
+	public Object sessionQuery( Object query ) throws Exception
+	{
+		return session.sessionQuery( query );
+	}
+
+	public void sessionControl( Object control, Object value ) throws Exception
+	{
+		session.sessionControl( control, value );
+	}
+
+	public void sessionNotify( Object event ) throws Exception
+	{
+		session.sessionNotify( event );
+	}
+
+	////////////////////
+	// Source methods //
+	////////////////////
+
+	public Object transportQuery( Object query ) throws Exception
+	{
+		return transport.transportQuery( query );
+	}
+
+	public void transportControl( Object control, Object value ) throws Exception
+	{
+		transport.transportControl( control, value );
+	}
+
+	public void transportNotify( Object event ) throws Exception
+	{
+		transport.transportNotify( event );
+	}
+
+	public SessionMessage getSession()
+	{
+		return session;
+	}
+	
+	public void setSession( SessionMessage session )
+	{
+		this.session = session;
+	}
+	
+	private SessionMessage session;
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/PlainMailbox.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/PlainMailbox.java
new file mode 100644
index 0000000..d0f4baf
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/PlainMailbox.java
@@ -0,0 +1,226 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.support.Mailbox;
+import org.apache.etch.util.AlarmListener;
+import org.apache.etch.util.AlarmManager;
+import org.apache.etch.util.CircularQueue;
+import org.apache.etch.util.core.Who;
+
+
+/**
+ * A plain implementation of a mailbox using a fixed size circular queue.
+ */
+public class PlainMailbox implements Mailbox, AlarmListener
+{
+	/**
+	 * Constructs the Mailbox.
+	 *
+	 * @param mailboxManager the mailbox manager to use to unregister this mailbox
+	 * and to deliver undelivered messages.
+	 * @param messageId message id of the message whose reply will come to this
+	 * mailbox.
+	 */
+	public PlainMailbox( MailboxManager mailboxManager, Long messageId )
+	{
+		if (mailboxManager == null)
+			throw new NullPointerException( "mailboxManager == null" );
+		
+		if (messageId == null)
+			throw new NullPointerException( "messageId == null" );
+		
+		this.mailboxManager = mailboxManager;
+		this.messageId = messageId;
+		
+		queue = new CircularQueue<Mailbox.Element>( 1 );
+	}
+	
+	private final MailboxManager mailboxManager;
+	
+	private final Long messageId;
+	
+	private boolean alarmSet;
+	
+	private final CircularQueue<Mailbox.Element> queue;
+
+	/**
+	 * @return the mailboxManager of this mailbox.
+	 */
+	public MailboxManager getMailboxManager()
+	{
+		return mailboxManager;
+	}
+
+	public Long getMessageId()
+	{
+		return messageId;
+	}
+
+	public boolean message( Who sender, Message msg ) throws Exception
+	{
+		boolean ok = queue.put( new Mailbox.Element( sender, msg ), -1 );
+		if (ok)
+			fireNotify();
+		return ok;
+	}
+	
+	private void fireNotify()
+	{
+		Notify n;
+		Object s;
+		boolean c;
+		
+		synchronized (queue)
+		{
+			n = notify;
+			s = state;
+			c = queue.isClosed();
+		}
+		
+		if (n != null)
+			n.mailboxStatus( this, s, c );
+	}
+
+	public Mailbox.Element read() throws InterruptedException
+	{
+		return queue.get();
+	}
+	
+	public Mailbox.Element read( int maxDelay ) throws InterruptedException
+	{
+		return queue.get( maxDelay );
+	}
+	
+	public boolean closeDelivery()
+	{
+		synchronized (queue)
+		{
+			if (queue.isClosed())
+				return false;
+
+			if (alarmSet)
+			{
+				alarmSet = false;
+				AlarmManager.staticRemove( this );
+			}
+			
+			mailboxManager.unregister( this );
+			queue.close();
+		}
+		
+		fireNotify();
+		return true;
+	}
+
+	public boolean closeRead() throws Exception
+	{
+		if (closeDelivery())
+		{
+			Mailbox.Element mbe;
+			while ((mbe = read()) != null)
+				mailboxManager.redeliver( mbe.sender, mbe.msg );
+			return true;
+		}
+		return false;
+	}
+
+	public int wakeup( AlarmManager manager, Object xstate, long due )
+	{
+		closeDelivery();
+		return 0;
+	}
+
+	public void registerNotify( Notify newNotify, Object newState, int maxDelay )
+	{
+		if (newNotify == null)
+			throw new NullPointerException( "newNotify == null" );
+		
+		if (maxDelay < 0)
+			throw new IllegalArgumentException( "maxDelay < 0" );
+		
+		boolean isNotEmptyOrIsClosed;
+		
+		synchronized (queue)
+		{
+			if (notify != null)
+				throw new IllegalStateException( "this.notify != null" );
+			
+			notify = newNotify;
+			state = newState;
+			
+			if (maxDelay > 0)
+			{
+				alarmSet = true;
+				AlarmManager.staticAdd( this, null, maxDelay );
+			}
+			
+			isNotEmptyOrIsClosed = !queue.isEmpty() || queue.isClosed();
+		}
+		
+		if (isNotEmptyOrIsClosed)
+			fireNotify();
+	}
+
+	public void unregisterNotify( Notify oldNotify )
+	{
+		if (oldNotify == null)
+			throw new NullPointerException( "oldNotify == null" );
+		
+		if (notify == null)
+			return;
+		
+		synchronized (queue)
+		{
+			if (oldNotify != notify)
+				throw new IllegalStateException( "oldNotify != this.notify" );
+			
+			if (alarmSet)
+			{
+				alarmSet = false;
+				AlarmManager.staticRemove( this );
+			}
+			
+			notify = null;
+			state = null;
+		}
+	}
+	
+	private Notify notify;
+	
+	private Object state;
+
+	public boolean isEmpty()
+	{
+		return queue.isEmpty();
+	}
+	
+	public boolean isClosed()
+	{
+		return queue.isClosed();
+	}
+
+	public boolean isFull()
+	{
+		return queue.isFull();
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/PlainMailboxManager.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/PlainMailboxManager.java
new file mode 100644
index 0000000..3c39d57
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/PlainMailboxManager.java
@@ -0,0 +1,285 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.support.Mailbox;
+import org.apache.etch.util.IdGenerator;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.Session;
+
+
+/**
+ * MailboxManager is a MessageHandler which accepts packets for
+ * possible delivery to a mailbox, or to another message handler
+ * if an appropriate mailbox cannot be found. MailboxManager is
+ * also a MessageSource, tagging messages with msgids and then
+ * forwarding them to another MessageSource. If requested, a
+ * mailbox is created with a message's msgid and added to the
+ * set of mailboxes waiting for messages.
+ */
+public class PlainMailboxManager implements MailboxManager
+{
+	/**
+	 * @param transport used to deliver messages to our peer.
+	 * @param uri
+	 * @param resources
+	 */
+	public PlainMailboxManager( TransportMessage transport, String uri,
+		Resources resources )
+	{
+		this( transport, new URL( uri ), resources );
+	}
+
+	/**
+	 * @param transport used to deliver messages to our peer.
+	 * @param uri
+	 * @param resources
+	 */
+	public PlainMailboxManager( TransportMessage transport, URL uri,
+		Resources resources )
+	{
+		this.transport = transport;
+		transport.setSession( this );
+	}
+	
+	private final TransportMessage transport;
+	
+	/**
+	 * @return the transport.
+	 */
+	public TransportMessage getTransport()
+	{
+		return transport;
+	}
+	
+	@Override
+	public String toString()
+	{
+		return String.format( "PlainMailboxManager/%s", transport );
+	}
+
+	////////////////////////////
+	// MessageHandler methods //
+	////////////////////////////
+	
+	public boolean sessionMessage( Who sender, Message msg ) throws Exception
+	{
+		//Log.report( "MailboxManager.recv", "msg", msg );
+		Long msgid = msg.getInReplyTo();
+		if (msgid != null)
+		{
+			Mailbox mb = getMailbox( msgid );
+			//Log.report( "MailboxManager.recv", "msg", msg, "mb", mb );
+			if (mb != null)
+			{
+				try
+				{
+					return mb.message( sender, msg );
+				}
+				catch ( InterruptedException e )
+				{
+					// timeout or mailbox closed - fall through
+				}
+			}
+			// no such mailbox - reject
+			return false;
+		}
+		// no msgid - pass off to session
+		return session.sessionMessage( sender, msg );
+	}
+
+	///////////////////////////
+	// MessageSource methods //
+	///////////////////////////
+
+	public void transportMessage( Who recipient, Message msg ) throws Exception
+	{
+		if (msg.getMessageId() != null)
+			throw new IllegalStateException( "message has already been sent" );
+		
+		msg.setMessageId( idGen.next() );
+		
+		//Log.report( "MailboxManager.send", "msg", msg );
+		
+		transport.transportMessage( recipient, msg );
+	}
+
+	public Mailbox transportCall( Who recipient, Message msg ) throws Exception
+	{
+		if (msg.getMessageId() != null)
+			throw new IllegalStateException( "message has already been sent" );
+		
+		if (msg.getInReplyTo() != null)
+			throw new IllegalStateException( "message is marked as a reply" );
+		
+		Long msgid = idGen.next();
+		msg.setMessageId( msgid );
+		
+		Mailbox mb = new PlainMailbox( this, msgid );
+		register( mb );
+		
+		//Log.report( "MailboxManager.send", "msg", msg );
+
+		try
+		{
+			transport.transportMessage( recipient, msg );
+		}
+		catch ( Exception e )
+		{
+			unregister( mb );
+			throw e;
+		}
+		
+		return mb;
+	}
+	
+	private final IdGenerator idGen = new IdGenerator( System.currentTimeMillis(), 37 );
+
+	/////////////////////
+	// Mailbox methods //
+	/////////////////////
+	
+	/**
+	 * Adds a mailbox to the set of mailbox receiving responses
+	 * to messages.
+	 * @param mb
+	 */
+	public void register( Mailbox mb )
+	{
+		Long msgid = mb.getMessageId();
+		synchronized (mailboxes)
+		{
+			if (!up)
+				throw new IllegalStateException( "connection down" );
+			
+			if (mailboxes.containsKey( msgid ))
+				throw new IllegalArgumentException( "dup msgid in mailboxes" );
+			
+			mailboxes.put( msgid, mb );
+		}
+	}
+
+	public void unregister( Mailbox mb )
+	{
+		mailboxes.remove( mb.getMessageId() );
+	}
+	
+	private void unregisterAll()
+	{
+		for (Mailbox mb: mailboxes.values().toArray( new Mailbox[0] ))
+			mb.closeDelivery();
+	}
+	
+	/**
+	 * Returns the mailbox for the specified msgid. This is a testing api.
+	 * @param msgid
+	 * @return the mailbox for the specified msgid.
+	 */
+	public Mailbox getMailbox( Long msgid )
+	{
+		return mailboxes.get( msgid );
+	}
+	
+	private Map<Long, Mailbox> mailboxes = Collections.synchronizedMap(
+		new HashMap<Long, Mailbox>() );
+
+	public void redeliver( Who sender, Message msg ) throws Exception
+	{
+		session.sessionMessage( sender, msg );
+	}
+
+	/**
+	 * @return the number of mailboxes
+	 */
+	public int size()
+	{
+		return mailboxes.size();
+	}
+	
+	///////////////////////////
+	// SourceHandler methods //
+	///////////////////////////
+
+	public Object sessionQuery( Object query ) throws Exception
+	{
+		return session.sessionQuery( query );
+	}
+
+	public void sessionControl( Object control, Object value ) throws Exception
+	{
+		session.sessionControl( control, value );
+	}
+
+	public void sessionNotify( Object event ) throws Exception
+	{
+		if (event == Session.UP)
+		{
+			up = true;
+		}
+		else if (event == Session.DOWN)
+		{
+			up = false;
+			unregisterAll();
+		}
+		
+		session.sessionNotify( event );
+	}
+	
+	private boolean up;
+
+	////////////////////
+	// Source methods //
+	////////////////////
+
+	public Object transportQuery( Object query ) throws Exception
+	{
+		return transport.transportQuery( query );
+	}
+
+	public void transportControl( Object control, Object value ) throws Exception
+	{
+		transport.transportControl( control, value );
+	}
+
+	public void transportNotify( Object event ) throws Exception
+	{
+		transport.transportNotify( event );
+	}
+
+	public SessionMessage getSession()
+	{
+		return session;
+	}
+	
+	public void setSession( SessionMessage session )
+	{
+		this.session = session;
+	}
+	
+	private SessionMessage session;
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/SessionMessage.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/SessionMessage.java
new file mode 100644
index 0000000..85bc1d4
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/SessionMessage.java
@@ -0,0 +1,42 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.Session;
+
+
+/**
+ * Interface used to deliver messages to the session from the transport.
+ */
+public interface SessionMessage extends Session
+{
+	/**
+	 * Delivers data to the session from the transport.
+	 * @param sender the sender of the message, for transports which allow
+	 * multiple senders. This is who to return any response to.
+	 * @param msg a Message.
+	 * @return true if the message was consumed, false otherwise.
+	 * @throws Exception
+	 */
+	public boolean sessionMessage( Who sender, Message msg ) throws Exception;
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/TaggedDataInput.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/TaggedDataInput.java
new file mode 100644
index 0000000..9098483
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/TaggedDataInput.java
@@ -0,0 +1,41 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import java.io.IOException;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.util.FlexBuffer;
+
+
+/**
+ * A TaggedDataInput reads type tagged values from an input buf.
+ */
+public interface TaggedDataInput
+{
+	/**
+	 * Reads a message from the buf.
+	 * @param buf the flex buffer containing the message.
+	 * @return a message read from the buf.
+	 * @throws IOException
+	 */
+	public Message readMessage( FlexBuffer buf ) throws IOException;
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/TaggedDataOutput.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/TaggedDataOutput.java
new file mode 100644
index 0000000..d22f516
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/TaggedDataOutput.java
@@ -0,0 +1,41 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import java.io.IOException;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.util.FlexBuffer;
+
+
+/**
+ * A TaggedDataOutput writes type tagged data values to an output buf.
+ */
+public interface TaggedDataOutput
+{
+	/**
+	 * Writes the message to the buf.
+	 * @param msg the message to be written.
+	 * @param buf the buffer to write to.
+	 * @throws IOException
+	 */
+	public void writeMessage( Message msg, FlexBuffer buf ) throws IOException;
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/Tcp2TransportFactory.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/Tcp2TransportFactory.java
new file mode 100644
index 0000000..0d3e97c
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/Tcp2TransportFactory.java
@@ -0,0 +1,191 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import java.nio.channels.SocketChannel;
+
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.bindings.java.support.TransportFactory;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.io.Packetizer;
+import org.apache.etch.util.core.io.SessionListener;
+import org.apache.etch.util.core.io.Transport;
+import org.apache.etch.util.core.io.TransportData;
+import org.apache.etch.util.core.io.TransportPacket;
+import org.apache.etch.util.core.nio.Tcp2Connection;
+import org.apache.etch.util.core.nio.Tcp2Listener;
+
+
+/**
+ * Selector based transport factory for tcp or tls connections.
+ * 
+ * TransportFactory.define( "tcp2", "org.apache.etch.bindings.java.transport.Tcp2TransportFactory" );
+ */
+public class Tcp2TransportFactory extends TransportFactory
+{
+	/**
+	 * Constructs a TcpTransportFactory which delivers TcpConnection.
+	 */
+	public Tcp2TransportFactory()
+	{
+		this( false );
+	}
+	
+	/**
+	 * Constructs a TcpTransportFactory which delivers TcpConnection or a
+	 * TlsConnection depending upon the isSecure parameter.
+	 * @param isSecure true if TlsConnection is desired, false otherwise.
+	 */
+	public Tcp2TransportFactory( boolean isSecure )
+	{
+		if (isSecure)
+			throw new UnsupportedOperationException( "isSecure" );
+		// this.isSecure = isSecure;
+	}
+	
+	// private final boolean isSecure;
+	
+	// private final static String CONNECTION = "Tcp2TransportFactory.connection";
+	
+	@Override
+	public TransportMessage newTransport( String uri, Resources resources )
+		throws Exception
+	{
+		URL u = new URL( uri );
+		
+		TransportData c = new Tcp2Connection( u, resources );
+		
+		TransportPacket p = new Packetizer( c, u, resources );
+		
+		TransportMessage m = new Messagizer( p, u, resources );
+		
+		m = addFilters( m, u, resources );
+		
+		ValueFactory vf = (ValueFactory) resources.get( Transport.VALUE_FACTORY );
+		vf.lockDynamicTypes();
+		
+		return m;
+	}
+
+	@Override
+	public Transport<ServerFactory> newListener( final String uri,
+		final Resources resources ) throws Exception
+	{
+		URL u = new URL( uri );
+		
+		Transport<SessionListener<SocketChannel>> l = new Tcp2Listener( u,
+			resources );
+		
+		return new MySessionListener( l, uri, resources );
+	}
+	
+	private class MySessionListener implements Transport<ServerFactory>,
+		SessionListener<SocketChannel>
+	{
+		/**
+		 * @param transport
+		 * @param uri
+		 * @param resources
+		 */
+		public MySessionListener(
+			Transport<SessionListener<SocketChannel>> transport, String uri,
+			Resources resources )
+		{
+			this.transport = transport;
+			this.uri = uri;
+			this.resources = resources;
+			
+			transport.setSession( this );
+		}
+		
+		private final Transport<SessionListener<SocketChannel>> transport;
+		
+		private final String uri;
+		
+		private final Resources resources;
+
+		public ServerFactory getSession()
+		{
+			return session;
+		}
+
+		public void setSession( ServerFactory session )
+		{
+			this.session = session;
+		}
+		
+		private ServerFactory session;
+		
+		@Override
+		public String toString()
+		{
+			return "Tcp2TransportFactory.MySessionListener/"+transport;
+		}
+
+		public Object transportQuery( Object query ) throws Exception
+		{
+			return transport.transportQuery( query );
+		}
+
+		public void transportControl( Object control, Object value )
+			throws Exception
+		{
+			transport.transportControl( control, value );
+		}
+
+		public void transportNotify( Object event ) throws Exception
+		{
+			transport.transportNotify( event );
+		}
+
+		public void sessionAccepted( SocketChannel connection )
+			throws Exception
+		{
+			Resources r = new Resources( resources );
+			r.put( "connection", connection );
+			
+			ValueFactory vf = session.newValueFactory( uri );
+			r.put( Transport.VALUE_FACTORY, vf );
+			
+			TransportMessage t = newTransport( uri, r );
+			
+			session.newServer( t, uri, r );
+		}
+
+		public Object sessionQuery( Object query ) throws Exception
+		{
+			return session.sessionQuery( query );
+		}
+
+		public void sessionControl( Object control, Object value )
+			throws Exception
+		{
+			session.sessionControl( control, value );
+		}
+
+		public void sessionNotify( Object event ) throws Exception
+		{
+			session.sessionNotify( event );
+		}
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/TcpTransportFactory.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/TcpTransportFactory.java
new file mode 100644
index 0000000..8ce7416
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/TcpTransportFactory.java
@@ -0,0 +1,200 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import java.net.Socket;
+
+import javax.net.ssl.SSLSocket;
+
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.bindings.java.support.TransportFactory;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.io.Packetizer;
+import org.apache.etch.util.core.io.SessionListener;
+import org.apache.etch.util.core.io.TcpConnection;
+import org.apache.etch.util.core.io.TcpListener;
+import org.apache.etch.util.core.io.TlsConnection;
+import org.apache.etch.util.core.io.TlsListener;
+import org.apache.etch.util.core.io.Transport;
+import org.apache.etch.util.core.io.TransportData;
+import org.apache.etch.util.core.io.TransportPacket;
+
+
+/**
+ * Transport factory for tcp or tls connections.
+ */
+public class TcpTransportFactory extends TransportFactory
+{
+	/**
+	 * Constructs a TcpTransportFactory which delivers TcpConnection.
+	 */
+	public TcpTransportFactory()
+	{
+		this( false );
+	}
+	
+	/**
+	 * Constructs a TcpTransportFactory which delivers TcpConnection or a
+	 * TlsConnection depending upon the isSecure parameter.
+	 * @param isSecure true if TlsConnection is desired, false otherwise.
+	 */
+	public TcpTransportFactory( boolean isSecure )
+	{
+		this.isSecure = isSecure;
+	}
+	
+	private final boolean isSecure;
+	
+	private final static String SOCKET = "TcpTransportFactory.socket";
+	
+	@Override
+	public TransportMessage newTransport( String uri,
+		Resources resources ) throws Exception
+	{
+		URL u = new URL( uri );
+		
+		Object socket = resources.get( SOCKET );
+		
+		TransportData c = null;
+		
+		if (isSecure)
+			c = new TlsConnection( (SSLSocket) socket, u, resources );
+		else
+			c = new TcpConnection( (Socket) socket, u, resources );
+		
+		TransportPacket p = new Packetizer( c, u, resources );
+		
+		TransportMessage m = new Messagizer( p, u, resources );
+		
+		m = addFilters( m, u, resources );
+		
+		ValueFactory vf = (ValueFactory) resources.get( Transport.VALUE_FACTORY );
+		vf.lockDynamicTypes();
+		
+		return m;
+	}
+
+	@Override
+	public Transport<ServerFactory> newListener( final String uri,
+		final Resources resources ) throws Exception
+	{
+		URL u = new URL( uri );
+		
+		Transport<SessionListener<Socket>> l;
+
+		if (isSecure)
+			l = new TlsListener( u, resources );
+		else
+			l = new TcpListener( u, resources );
+		
+		return new MySessionListener( l, uri, resources );
+	}
+	
+	private class MySessionListener implements Transport<ServerFactory>, SessionListener<Socket>
+	{
+		/**
+		 * @param transport
+		 * @param uri
+		 * @param resources
+		 */
+		public MySessionListener( Transport<SessionListener<Socket>> transport,
+			String uri, Resources resources )
+		{
+			this.transport = transport;
+			this.uri = uri;
+			this.resources = resources;
+			
+			transport.setSession( this );
+		}
+		
+		private final Transport<SessionListener<Socket>> transport;
+		
+		private final String uri;
+		
+		private final Resources resources;
+
+		public ServerFactory getSession()
+		{
+			return session;
+		}
+
+		public void setSession( ServerFactory session )
+		{
+			this.session = session;
+		}
+		
+		private ServerFactory session;
+		
+		@Override
+		public String toString()
+		{
+			return "TcpTransportFactory.MySessionListener/"+transport;
+		}
+
+		public Object transportQuery( Object query ) throws Exception
+		{
+			return transport.transportQuery( query );
+		}
+
+		public void transportControl( Object control, Object value )
+			throws Exception
+		{
+			transport.transportControl( control, value );
+		}
+
+		public void transportNotify( Object event ) throws Exception
+		{
+			transport.transportNotify( event );
+		}
+
+		public void sessionAccepted( Socket socket )
+			throws Exception
+		{
+			Resources r = new Resources( resources );
+			r.put( SOCKET, socket );
+			
+			ValueFactory vf = session.newValueFactory( uri );
+			r.put( Transport.VALUE_FACTORY, vf );
+			
+			TransportMessage t = newTransport( uri, r );
+			
+			session.newServer( t, uri, r );
+		}
+
+		public Object sessionQuery( Object query ) throws Exception
+		{
+			return session.sessionQuery( query );
+		}
+
+		public void sessionControl( Object control, Object value )
+			throws Exception
+		{
+			session.sessionControl( control, value );
+		}
+
+		public void sessionNotify( Object event ) throws Exception
+		{
+			session.sessionNotify( event );
+		}
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/TransportMessage.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/TransportMessage.java
new file mode 100644
index 0000000..07f5e28
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/TransportMessage.java
@@ -0,0 +1,41 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.Transport;
+
+
+/**
+ * Interface used to deliver messages to the transport from the session.
+ */
+public interface TransportMessage extends Transport<SessionMessage>
+{
+	/**
+	 * Delivers the data to the transport.
+	 * @param recipient specifies the recipient when there is the possibility
+	 * of more than one.
+	 * @param msg the Message.
+	 * @throws Exception
+	 */
+	public void transportMessage( Who recipient, Message msg ) throws Exception;
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/UnwantedMessage.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/UnwantedMessage.java
new file mode 100644
index 0000000..0383c95
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/UnwantedMessage.java
@@ -0,0 +1,54 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.util.core.Who;
+
+
+/**
+ * Event class used with sessionNotify to report unwanted messages.
+ */
+public class UnwantedMessage
+{
+	/**
+	 * Constructs the UnwantedMessage.
+	 * @param sender
+	 * @param msg
+	 */
+	public UnwantedMessage( Who sender, Message msg )
+	{
+		this.sender = sender;
+		this.msg = msg;
+	}
+	
+	/** the sender of this unwanted message. */
+	public final Who sender;
+	
+	/** the unwanted message. */
+	public final Message msg;
+	
+	@Override
+	public String toString()
+	{
+		return String.format( "Unwanted message from %s: %s", sender, msg );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/filters/AbstractMessageFilter.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/filters/AbstractMessageFilter.java
new file mode 100644
index 0000000..80bb30f
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/filters/AbstractMessageFilter.java
@@ -0,0 +1,145 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.filters;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.transport.SessionMessage;
+import org.apache.etch.bindings.java.transport.TransportMessage;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.Session;
+
+
+/**
+ * AbstractMessageFilter is a useful base class used to implement message filters.
+ */
+abstract public class AbstractMessageFilter implements TransportMessage, SessionMessage
+{
+	/**
+	 * Constructs the AbstractMessageFilter.
+	 * @param transport
+	 * @param uri
+	 * @param resources
+	 */
+	protected AbstractMessageFilter( TransportMessage transport, URL uri,
+		Resources resources )
+	{
+		this.transport = transport;
+		transport.setSession( this );
+	}
+
+	/**
+	 * Our transport.
+	 */
+	protected final TransportMessage transport;
+	
+	@Override
+	abstract public String toString();
+
+	public void transportMessage( Who recipient, Message msg ) throws Exception
+	{
+		transport.transportMessage( recipient, msg );
+	}
+
+	public SessionMessage getSession()
+	{
+		return session;
+	}
+
+	public void setSession( SessionMessage session )
+	{
+		this.session = session;
+	}
+
+	/**
+	 * Our session
+	 */
+	protected SessionMessage session;
+
+	public Object transportQuery( Object query ) throws Exception
+	{
+		return transport.transportQuery( query );
+	}
+
+	public void transportControl( Object control, Object value )
+		throws Exception
+	{
+		transport.transportControl( control, value );
+	}
+
+	public void transportNotify( Object event ) throws Exception
+	{
+		transport.transportNotify( event );
+	}
+
+	public boolean sessionMessage( Who sender, Message msg ) throws Exception
+	{
+		return session.sessionMessage( sender, msg );
+	}
+
+	public Object sessionQuery( Object query ) throws Exception
+	{
+		return session.sessionQuery( query );
+	}
+
+	public void sessionControl( Object control, Object value ) throws Exception
+	{
+		session.sessionControl( control, value );
+	}
+
+	public void sessionNotify( Object event ) throws Exception
+	{
+		if (event == Session.UP)
+			if (!sessionUp())
+				return;
+
+		if (event == Session.DOWN)
+			if (!sessionDown())
+				return;
+
+		session.sessionNotify( event );
+	}
+
+	/**
+	 * Tells the filter that the session is up.
+	 * @return true if the event should be passed on to our session, false
+	 * if it should be swallowed.
+	 * @throws Exception
+	 */
+	protected boolean sessionUp() throws Exception
+	{
+		// nothing to do.
+		return true;
+	}
+
+	/**
+	 * Tells the filter that the session is down.
+	 * @return true if the event should be passed on to our session, false
+	 * if it should be swallowed.
+	 * @throws Exception
+	 */
+	protected boolean sessionDown() throws Exception
+	{
+		// nothing to do.
+		return true;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/filters/KeepAlive.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/filters/KeepAlive.java
new file mode 100644
index 0000000..cc0d436
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/filters/KeepAlive.java
@@ -0,0 +1,349 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.filters;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Validator_int;
+import org.apache.etch.bindings.java.transport.TransportMessage;
+import org.apache.etch.util.AlarmListener;
+import org.apache.etch.util.AlarmManager;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.Timer;
+import org.apache.etch.util.Todo;
+import org.apache.etch.util.TodoManager;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.Transport;
+
+
+/**
+ * KeepAlive is a message filter which periodically sends messages to the server
+ * from a client to verify that the connection is still alive. Both sides
+ * periodically check for the messages from the other side, noting when they
+ * arrive and how long since the last one has arrived. If it has been too long
+ * since a message arrived from the other side, either side will reset the
+ * connection.
+ * 
+ * Two parameters control KeepAlive activity: delay and count. Delay is the
+ * number of seconds between sending / checking. Count is the number of delay
+ * intervals with no keep alive request or response before the connection is
+ * reset.
+ * 
+ * KeepAlive is added to the transport stack (generally first) like this:
+ * 
+ * tcp://host:port?filter=KeepAlive&KeepAlive.delay=15&KeepAlive.count=4
+ * 
+ * The default values for delay and count are shown, 15 seconds and 4 messages
+ * missed, respectively. If you like the defaults, you don't need to specify
+ * delay and / or count.
+ * 
+ * Using the above defaults, the client will send the server a keep alive
+ * request every 15 seconds. The client also sends its delay value and count to
+ * the server. When the server receives a keep alive request, it resets its
+ * delay and count values to those of the client, updates the last message time,
+ * and then sends a keep alive response to the client. When the client receives
+ * the keep alive response, it updates its last message time.
+ * 
+ * Both client and server wake up every 15 seconds and check the last message
+ * time. If it is more than 60 seconds in the past (count * delay), then the
+ * connection is reset.
+ */
+public class KeepAlive extends AbstractMessageFilter implements AlarmListener
+{
+	/** Time in seconds between sending message and checking for response.
+	 * Default is 15 seconds. */
+	public final static String DELAY = "KeepAlive.delay";
+	
+	/** Count of how many DELAY intervals can be missed before the connection
+	 * is reset. Default is 4. */
+	public final static String COUNT = "KeepAlive.count";
+	
+	/**
+	 * @param transport
+	 * @param uri
+	 * @param resources
+	 * @throws Exception
+	 */
+	public KeepAlive( TransportMessage transport, URL uri, Resources resources )
+		throws Exception
+	{
+		super( transport, uri, resources );
+		
+		delay = uri.getIntegerTerm( DELAY, 15 );
+		if (delay <= 0)
+			throw new IllegalArgumentException( "delay <= 0" );
+		
+		count = uri.getIntegerTerm( COUNT, 4 );
+		if (count <= 0)
+			throw new IllegalArgumentException( "count <= 0" );
+		
+		server = (Boolean) transport.transportQuery( Transport.IS_SERVER );
+		
+//		Log.report( "KeepAliveInstalled",
+//			"delay", delay, "count", count, "server", server );
+		
+		vf = (ValueFactory) resources.get( Transport.VALUE_FACTORY );
+
+		mf_delay = new Field( "delay" );
+		mf_count = new Field( "count" );
+		
+		mt_request = new Type( "_Etch_KeepAliveReq" );
+		mt_request.putValidator( mf_delay, Validator_int.get( 0 ) );
+		mt_request.putValidator( mf_count, Validator_int.get( 0 ) );
+		vf.addType( mt_request );
+
+		mt_response = new Type( "_Etch_KeepAliveResp" );
+		vf.addType( mt_response );
+		
+		mt_request.setResult( mt_response );
+	}
+	
+	private int delay;
+	
+	private int count;
+	
+	private final boolean server;
+	
+	private final ValueFactory vf;
+	
+	private final Field mf_delay;
+	
+	private final Field mf_count;
+	
+	private final Type mt_request;
+	
+	private final Type mt_response;
+	
+	@Override
+	public String toString()
+	{
+		return "KeepAlive/"+transport;
+	}
+	
+	/**
+	 * @return the server operating mode.
+	 */
+	public boolean getServer()
+	{
+		return server;
+	}
+	
+	@Override
+	public boolean sessionMessage( Who sender, Message msg ) throws Exception
+	{
+		if (msg.isType( mt_request ) )
+		{
+			handleRequest( msg );
+			return true;
+		}
+		
+		if (msg.isType( mt_response ))
+		{
+			handleResponse( msg );
+			return true;
+		}
+		
+		return super.sessionMessage( sender, msg );
+	}
+
+	@Override
+	protected boolean sessionUp()
+	{
+//		Log.report( "KeepAliveSessionUp", "server", server );
+		up = true;
+		AlarmManager.staticAdd( this, null, delay*1000 );
+		tickle();
+		return true;
+	}
+	
+	@Override
+	protected boolean sessionDown()
+	{
+//		Log.report( "KeepAliveSessionDown", "server", server );
+		up = false;
+		AlarmManager.staticRemove( this );
+		return true;
+	}
+	
+	private boolean up;
+	
+	private void handleRequest( Message msg )
+	{
+		if (!server)
+		{
+			// we're a client that got a request, likely we're talking to a
+			// server that is confused.
+			return;
+		}
+		
+//		Log.report( "GotKeepAliveReq", "msg", msg );
+		
+		Number d = (Number) msg.get( mf_delay );
+		if (d != null && d.intValue() > 0)
+		{
+//			Log.report( "KeepAliveResetDelay", "delay", d );
+			delay = d.intValue();
+		}
+		
+		Number c = (Number) msg.get( mf_count );
+		if (c != null && c.intValue() > 0)
+		{
+//			Log.report( "KeepAliveResetCount", "count", c );
+			count = c.intValue();
+		}
+		
+		tickle();
+		
+		sendKeepAliveResp( msg );
+	}
+
+	private void handleResponse( Message msg )
+	{
+		if (server)
+		{
+			// we're a server that got a response, which means either we sent
+			// a request (but we shouldn't do that if we're a server) or the
+			// client is confused.
+			return;
+		}
+		
+//		Log.report( "GotKeepAliveResp", "msg", msg );
+		
+		tickle();
+	}
+	
+	private void tickle()
+	{
+		lastTickle = Timer.getNanos();
+	}
+	
+	private long lastTickle;
+	
+	private void checkTickle()
+	{
+		long ms = Timer.getMillisSince( lastTickle );
+//		Log.report( "KeepAliveIdle", "ms", ms, "server", server );
+		if (ms >= count * delay * 1000)
+		{
+			try
+			{
+//				Log.report( "KeepAliveReset", "server", server );
+				session.sessionNotify( "KeepAlive resetting dead connection" );
+				transport.transportControl( Transport.RESET, 0 );
+			}
+			catch ( Exception e )
+			{
+				reportError( e );
+			}
+		}
+	}
+	
+	private void reportError( Exception e )
+	{
+		try
+		{
+			session.sessionNotify( e );
+		}
+		catch ( Exception e1 )
+		{
+			// what else can you do?
+			e1.printStackTrace();
+		}
+	}
+	
+	private void sendKeepAliveReq()
+	{
+		Message msg = new Message( mt_request, vf );
+		msg.put( mf_delay, delay );
+		msg.put( mf_count, count );
+		try
+		{
+//			Log.report( "SendKeepAliveReq", "msg", msg );
+			transport.transportMessage( null, msg );
+		}
+		catch ( Exception e )
+		{
+			reportError( e );
+		}
+	}
+	
+	private void sendKeepAliveResp( Message msg )
+	{
+		Message rmsg = msg.reply();
+		try
+		{
+//			Log.report( "SendKeepAliveResp", "rmsg", rmsg );
+			transport.transportMessage( null, rmsg );
+		}
+		catch ( Exception e )
+		{
+			reportError( e );
+		}
+	}
+
+	public int wakeup( AlarmManager manager, Object state, long due )
+	{
+//		Log.report( "KeepAliveWakeup", "server", server );
+		
+		if (!up)
+			return 0;
+		
+		if (!server)
+		{
+			// use a Todo so as to not unnecessarily block AlarmManager.
+			TodoManager.addTodo( new Todo()
+			{
+				public void doit( TodoManager mgr ) throws Exception
+				{
+					sendKeepAliveReq();
+				}
+
+				public void exception( TodoManager mgr, Exception e )
+				{
+					reportError( e );
+				}
+			} );
+		}
+		
+		checkTickle();
+		
+		return delay * 1000;
+	}
+
+	/**
+	 * @return the configured delay.
+	 */
+	public int getDelay()
+	{
+		return delay;
+	}
+
+	/**
+	 * @return the configured count.
+	 */
+	public int getCount()
+	{
+		return count;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/filters/Logger.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/filters/Logger.java
new file mode 100644
index 0000000..ac79f5a
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/filters/Logger.java
@@ -0,0 +1,204 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.filters;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.transport.TransportMessage;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.Who;
+
+
+/**
+ * A Message Filter which logs the messages seen to a file.
+ */
+@SuppressWarnings("all")
+public class Logger extends AbstractMessageFilter
+{
+
+	private BufferedWriter writer;
+
+	private static String FILE_PATH = "Logger.filePath";
+
+	private String fileName = null;
+	
+	private String testRenamedFileName = null;
+
+	private DateFormat df =  new SimpleDateFormat( "HH:mm:ss.SSS" );
+
+	private String newLine = System.getProperty( "line.separator" );
+	
+	private SimpleDateFormat fileNameFormat = new SimpleDateFormat(
+	"yyyy.MM.dd.HH.mm.ss" );
+	
+	public static boolean testFlag = false;
+
+	enum Direction
+	{
+		UP, DOWN
+	}
+
+	public Logger( TransportMessage transport, URL uri, Resources resources )
+	throws Exception
+	{
+		super( transport, uri, resources );
+
+		initializeLogger(uri);
+	}
+	
+	private void initializeLogger(URL uri) throws Exception {
+		
+		fileName = uri.getTerm( FILE_PATH );
+		if (fileName == null)
+		{
+			// use default name
+			fileName = "Log.txt";
+		}
+		
+		if (!testFlag)
+		{
+			File f = new File( fileName );
+			if (f.exists())
+			{
+				/*
+				 * String name = f.getName().substring( 0, f.getName().indexOf(
+				 * "." ) ); String newFileName = f.getParent() +
+				 * File.separatorChar + name + fileNameFormat.format( new Date() ) +
+				 * ".txt";
+				 */
+				String newFileName = generateNewFileName( f.getName(), f
+					.getParent() );
+				boolean status = f.renameTo( new File( newFileName ) );
+			}
+			writer = new BufferedWriter( new FileWriter( f, true ) );
+		}
+		else {
+			testRenamedFileName = generateNewFileName(fileName,null);
+		}
+	
+	}
+	
+	private String generateNewFileName(String fileName, String pathName) throws
+		Exception
+	{
+		if (pathName == null)
+			pathName="";
+		String name = fileName.substring( 0,
+			fileName.indexOf( "." ) );
+		String newFileName = pathName + File.separatorChar + name
+		+ fileNameFormat.format( new Date() ) + ".txt";
+		return newFileName;
+	}
+
+	@Override
+	public String toString()
+	{
+		return "Logger/" + transport;
+	}
+
+	@Override
+	public boolean sessionMessage( Who sender, Message msg ) throws Exception
+	{
+		// System.out.println("Direction: UP, Message: " + msg.toString());
+		writeToFile( Direction.UP, sender, msg.toString() );
+		return super.sessionMessage( sender, msg );
+	}
+
+	@Override
+	public void transportMessage( Who recipient, Message msg ) throws Exception
+	{
+		// System.out.println("Direction: DOWN, Message: " + msg.toString());
+		writeToFile( Direction.DOWN, recipient, msg.toString() );
+		super.transportMessage( recipient, msg );
+	}
+
+	@Override
+	protected boolean sessionUp() throws Exception
+	{
+		writeToFile( Direction.UP, null, transport.toString() );
+		return true;
+	}
+
+	@Override
+	protected boolean sessionDown() throws Exception
+	{
+		writeToFile( Direction.DOWN, null, transport.toString() );
+		// writer.close();
+		return true;
+	}
+
+	public void writeToFile( Direction direction, Who msgOrigin, String msg )
+	throws Exception
+	{
+		if (writer == null)
+			return;
+		
+		try
+		{
+			synchronized (writer)
+			{
+				writer.write( df.format( new Date() ) );
+				writer.write( ": " );
+				writer.write( convertDirToString( direction ) );
+				writer.write( ": " );
+				if (msgOrigin != null)
+				{
+					writer.write( msgOrigin.toString() );
+					writer.write( ": " );
+				}
+				writer.write( msg );
+				writer.write( newLine );
+				writer.flush();
+			}
+		}
+		catch ( Exception e )
+		{
+			writer.close();
+			throw e;
+		}
+	}
+
+	private String convertDirToString( Direction dir )
+	{
+		if (dir.ordinal() == Direction.DOWN.ordinal())
+		{
+			return "Outgoing";
+		}
+		return "Incoming";
+	}
+
+	public String getFileName()
+	{
+		return fileName;
+	}
+
+	public String getTestRenamedFileName()
+	{
+		return testRenamedFileName;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/filters/PwAuth.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/filters/PwAuth.java
new file mode 100644
index 0000000..2e11d78
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/filters/PwAuth.java
@@ -0,0 +1,383 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.filters;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Validator_boolean;
+import org.apache.etch.bindings.java.support.Validator_string;
+import org.apache.etch.bindings.java.transport.TransportMessage;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.Transport;
+
+
+/**
+ * PwAuth is a message filter which watches for Session.UP and attempts to
+ * authenticate the user by sending a message to the server with the name and
+ * password in it. If the server responds, the session is notified with the
+ * user name. If the server responds negatively, the session is notified of the
+ * failure (using a PwAuthFail event). A transport control may also be sent to
+ * force a login or logout or to set the name or password. The name and password
+ * are initialized from the uri, or prompted for if not specified.
+ */
+public class PwAuth extends AbstractMessageFilter
+{
+	/**
+	 * client sessionQuery: return user name to use for authentication.
+	 * transportQuery: return the current user name (on server it has been validated).
+	 * client transportControl: set user name to use for authentication.
+	 */
+	public static final String USER = "PwAuth.user";
+
+	/**
+	 * client sessionQuery: return password to use for authentication.
+	 * transportQuery: return the current password (on server it has been validated).
+	 * client transportControl: set password to use for authentication.
+	 */
+	public static final String PASSWORD = "PwAuth.password";
+
+	/**
+	 * client transportControl: send authentication request
+	 */
+	private static final String AUTHENTICATE = "PwAuth.authenticate";
+	
+	/**
+	 * @param transport
+	 * @param uri
+	 * @param resources
+	 * @throws Exception
+	 */
+	public PwAuth( TransportMessage transport, URL uri, Resources resources )
+		throws Exception
+	{
+		super( transport, uri, resources );
+		server = (Boolean) transport.transportQuery( Transport.IS_SERVER );
+		
+		if (!server)
+		{
+			user = uri.getUser();
+			password = uri.getPassword();
+		}
+		
+//		Log.report( "KeepAliveInstalled",
+//			"delay", delay, "count", count, "server", server );
+		
+		vf = (ValueFactory) resources.get( Transport.VALUE_FACTORY );
+
+		mt_request = new Type( "_Etch_PwAuthReq" );
+		mt_response = new Type( "_Etch_PwAuthResp" );
+		
+		vf.addType( mt_request );
+		vf.addType( mt_response );
+		
+		mf_user = new Field( "user" );
+		mf_password = new Field( "password" );
+		mf_ok = new Field( "ok" );
+		mf_status = new Field( "status" );
+		
+		mt_request.putValidator( mf_user, Validator_string.get( 0 ) );
+		mt_request.putValidator( mf_password, Validator_string.get( 0 ) );
+		mt_request.setResult( mt_response );
+		mt_request.lock();
+		
+		mt_response.putValidator( mf_ok, Validator_boolean.get( 0 ) );
+		mt_response.putValidator( mf_status, Validator_string.get( 0 ) );
+		mt_response.lock();
+	}
+	
+	private String user;
+	
+	private String password;
+	
+	private final boolean server;
+	
+	private final ValueFactory vf;
+	
+	private final Field mf_user;
+	
+	private final Field mf_password;
+	
+	private final Field mf_ok;
+	
+	private final Field mf_status;
+	
+	private final Type mt_request;
+	
+	private final Type mt_response;
+	
+	@Override
+	public String toString()
+	{
+		return "PwAuth/"+transport;
+	}
+	
+	/**
+	 * @return the server operating mode.
+	 */
+	public boolean getServer()
+	{
+		return server;
+	}
+	
+	@Override
+	public boolean sessionMessage( Who sender, Message msg ) throws Exception
+	{
+		if (msg.isType( mt_request ) )
+		{
+			handlePwAuthReq( sender, msg );
+			return true;
+		}
+		
+		if (msg.isType( mt_response ))
+		{
+			handlePwAuthResp( sender, msg );
+			return true;
+		}
+		
+		return super.sessionMessage( sender, msg );
+	}
+
+	@Override
+	protected boolean sessionUp() throws Exception
+	{
+		if (!server)
+		{
+			// client: send authentication request.
+			sendPwAuthReq();
+		}
+		
+		return true;
+	}
+
+	@Override
+	protected boolean sessionDown() throws Exception
+	{
+		if (server)
+		{
+			// make sure that server session's idea of user is cleared.
+			sessionNotifyUser( null, null );
+		}
+		
+		return true;
+	}
+
+	private void sendPwAuthReq() throws Exception
+	{
+		if (user == null)
+		{
+			user = (String) session.sessionQuery( USER );
+			if (user == null)
+				throw new IllegalStateException( "PwAuth: user == null" );
+		}
+		
+		if (password == null)
+		{
+			password = (String) session.sessionQuery( PASSWORD );
+			if (password == null)
+				throw new IllegalStateException( "PwAuth: password == null" );
+		}
+		
+		Message msg = new Message( mt_request, vf );
+		msg.put( mf_user, user );
+		msg.put( mf_password, password );
+		transport.transportMessage( null, msg );
+	}
+	
+	private void handlePwAuthReq( Who sender, Message msg ) throws Exception
+	{
+		if (!server)
+		{
+			// we're a client that got a request, likely we're talking to a
+			// server that is confused.
+			return;
+		}
+		
+		Log.report( "GotPwAuthReq", "sender", sender, "msg", msg );
+		
+		String u = (String) msg.get( mf_user );
+		String p = (String) msg.get( mf_password );
+		
+		try
+		{
+			OkStatus as = (OkStatus) sessionQuery( new UserPassword( u, p ) );
+			
+			if (as.ok)
+				sessionNotifyUser( u, p );
+			else
+				sessionNotifyUser( null, null );
+			
+			sendPwAuthResp( sender, msg, as.ok, as.status );
+		}
+		catch ( Exception e )
+		{
+			sessionNotifyUser( null, null );
+			sendPwAuthResp( sender, msg, false, e.toString() );
+			throw e;
+		}
+	}
+	
+	private void sendPwAuthResp( Who recipient, Message msg, boolean result, String status )
+		throws Exception
+	{
+		Message rmsg = msg.reply();
+		rmsg.put( mf_ok, result );
+		rmsg.put( mf_status, status );
+		transport.transportMessage( recipient, rmsg );
+	}
+
+	private void handlePwAuthResp( Who sender, Message msg ) throws Exception
+	{
+		if (server)
+		{
+			// we're a server that got a response, likely we're talking to a
+			// client that is confused.
+			return;
+		}
+		
+		Log.report( "GotPwAuthResp", "sender", sender, "msg", msg );
+		
+		boolean result = (Boolean) msg.get( mf_ok );
+		String status = (String) msg.get( mf_status );
+		
+		session.sessionNotify( new OkStatus( result, status ) );
+	}
+	
+	@Override
+	public Object transportQuery( Object query ) throws Exception
+	{
+		if (query == USER)
+			return user;
+		
+		if (query == PASSWORD)
+			return password;
+		
+		return super.transportQuery( query );
+	}
+	
+	@Override
+	public void transportControl( Object control, Object value )
+		throws Exception
+	{
+		if (control == USER)
+		{
+			checkNotServer();
+			user = (String) value;
+			return;
+		}
+		
+		if (control == PASSWORD)
+		{
+			checkNotServer();
+			password = (String) value;
+			return;
+		}
+		
+		if (control == AUTHENTICATE)
+		{
+			checkNotServer();
+			sendPwAuthReq();
+			return;
+		}
+		
+		super.transportControl( control, value );
+	}
+
+	private void checkNotServer()
+	{
+		if (server)
+			throw new IllegalStateException( "control not permitted by server" );
+	}
+	
+	@SuppressWarnings("hiding")
+	private void sessionNotifyUser( String user, String password )
+		throws Exception
+	{
+		this.user = user;
+		this.password = password;
+		session.sessionNotify( new UserPassword( user, password ) );
+	}
+
+	/**
+	 * Server session query to get AuthOkStatus, also server session event
+	 * to report changes in authentication status.
+	 */
+	public static class UserPassword
+	{
+		/**
+		 * Constructs the CheckAuth.
+		 *
+		 * @param user name to check.
+		 * @param password of the user.
+		 */
+		public UserPassword( String user, String password )
+		{
+			this.user = user;
+			this.password = password;
+		}
+		
+		@Override
+		public String toString()
+		{
+			return String.format( "AuthUserPassword( %s )", user );
+		}
+		
+		/** The user name to check */
+		public final String user;
+		
+		/** The password of the user */
+		public final String password;
+	}
+	
+	/**
+	 * Server session query response to AuthUserPassword.
+	 */
+	public static class OkStatus
+	{
+		/**
+		 * Constructs the AuthOkStatus.
+		 *
+		 * @param ok true if user / password valid.
+		 * @param status message related to ok.
+		 */
+		public OkStatus( boolean ok, String status )
+		{
+			this.ok = ok;
+			this.status = status;
+		}
+		
+		@Override
+		public String toString()
+		{
+			return String.format( "AuthOkStatus( %s, %s )", ok, status );
+		}
+		
+		/** true if the user / password matched */
+		public final boolean ok;
+		
+		/** message related to ok */
+		public final String status;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/TaggedData.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/TaggedData.java
new file mode 100644
index 0000000..b6610bc
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/TaggedData.java
@@ -0,0 +1,218 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.fmt;
+
+import java.lang.reflect.Array;
+
+import org.apache.etch.bindings.java.msg.ComboValidator;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Validator_StructValue;
+import org.apache.etch.bindings.java.transport.ArrayValue;
+
+
+/**
+ * Common interface for various types of tagged data input and output.
+ */
+abstract public class TaggedData
+{
+	/**
+	 * Constructs the TaggedData.
+	 *
+	 * @param vf
+	 */
+	public TaggedData( ValueFactory vf )
+	{
+		this.vf = vf;
+	}
+	
+	/**
+	 * The value factory to use for tagged input and output.
+	 */
+	protected final ValueFactory vf;
+
+	/**
+	 * @return the value factory to use for tagged input and output.
+	 */
+	public ValueFactory getValueFactory()
+	{
+		return vf;
+	}
+
+	/**
+	 * @param value
+	 * @param v
+	 * @return an ArrayValue which models the given array.
+	 */
+	@SuppressWarnings("deprecation")
+	protected ArrayValue toArrayValue( Object value, Validator v )
+	{
+		Class<?> c = value.getClass();
+//		System.out.printf( "toArrayValue: class is %s\n", c );
+		int dim = 0;
+		while (c.isArray())
+		{
+			dim++;
+			c = c.getComponentType();
+		}
+//		System.out.printf( "toArrayValue: base class is %s dim %d\n", c, dim );
+		
+		// now we want the type code for c, and if the type code is custom,
+		// we'll also want the struct type code.
+		
+		byte typeCode = getNativeTypeCode( c );
+		
+		Type customStructType;
+		if (typeCode == TypeCode.CUSTOM || typeCode == TypeCode.STRUCT)
+		{
+			customStructType = getCustomStructType( c );
+			
+			if (customStructType == null && c == StructValue.class)
+			{
+				Validator_StructValue x = findStructValueValidator( v );
+				if (x != null)
+					customStructType = x.getType();
+			}
+			
+			if (customStructType == null )
+				throw new IllegalArgumentException( "customStructType == null" );
+		}
+		else
+			customStructType = null;
+
+//		System.out.printf( "toArrayValue: type %d customStructType %d dim %d\n", type, customStructType, dim );
+		return new ArrayValue( value, typeCode, customStructType, dim );
+	}
+	
+	private Validator_StructValue findStructValueValidator( Validator v )
+	{
+		if (v instanceof Validator_StructValue)
+			return (Validator_StructValue) v;
+		
+		if (v instanceof ComboValidator)
+		{
+			ComboValidator x = (ComboValidator) v;
+			Validator_StructValue y = findStructValueValidator( x.a() );
+			
+			if (y != null)
+				return y;
+			
+			return findStructValueValidator( x.b() );
+		}
+		
+		return null;
+	}
+
+	/**
+	 * @param av
+	 * @return a native array converted from an array value.
+	 */
+	protected Object fromArrayValue( ArrayValue av )
+	{
+		return av.getArray();
+	}
+	
+	/**
+	 * @param typeCode
+	 * @param customStructType
+	 * @param dim
+	 * @param length
+	 * @return the allocated array value.
+	 */
+	protected Object allocArrayValue( byte typeCode, Type customStructType,
+		int dim, int length )
+	{
+		Class<?> clss = getComponentType( typeCode, customStructType, dim-1 );
+		
+		if (clss == null)
+			throw new IllegalArgumentException( String.format(
+				"could not get array for %s, %s, %d",
+				typeCode, customStructType, dim-1 ) );
+
+		return Array.newInstance( clss, length );
+	}
+	
+	@SuppressWarnings("deprecation")
+	private Class<?> getComponentType( byte typeCode, Type customStructType,
+		int dim )
+	{
+		Class<?> c;
+		if (typeCode == TypeCode.CUSTOM || typeCode == TypeCode.STRUCT)
+		{
+			c = customStructType.getComponentType();
+			if (c == null)
+				c = StructValue.class;
+		}
+		else
+		{
+			c = getNativeType( typeCode );
+		}
+		
+//		System.out.printf( "getComponentType class %s\n", c );
+		
+		if (c == null)
+			return null;
+		
+		if (dim == 0)
+			return c;
+		
+		// TODO is there a better way to get the class of a multi-dimensional array?
+		int[] dims = new int[dim];
+		Object o = Array.newInstance( c, dims );
+//		System.out.printf( "object = %s\n", o );
+		c = o.getClass();
+//		System.out.printf( "class = %s\n", c );
+		return c;
+	}
+
+	/**
+	 * @param value
+	 * @return return a type code for the specified value.
+	 */
+	abstract public byte checkValue( Object value );
+	
+	/**
+	 * Returns the type code for the specified class. This
+	 * is needed when we have an array and we have determine
+	 * the base type and now we're fixing to serialize it.
+	 * We use the base type code to reconstitute it on the
+	 * other side. So we don't return a perfect code the way
+	 * checkValue does, but rather just something that let's
+	 * us recreate the appropriate array type on import.
+	 * @param c
+	 * @return a type code for the specified class.
+	 */
+	abstract public byte getNativeTypeCode( Class<?> c );
+	
+	/**
+	 * @param c
+	 * @return a struct type for the specified custom class.
+	 */
+	abstract public Type getCustomStructType( Class<?> c );
+
+	/**
+	 * @param type
+	 * @return the class for a specified (native) type code.
+	 */
+	abstract public Class<?> getNativeType( byte type );
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/TypeCode.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/TypeCode.java
new file mode 100644
index 0000000..21483bd
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/TypeCode.java
@@ -0,0 +1,199 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.fmt;
+
+/**
+ * Values denoting types of encoded values. There are two value ranges:
+ * 
+ * -128 to -65: codes for defined types.
+ * -64 to 127: tiny integer values.
+ * 
+ * Tiny integers are completely encoded within the type byte.
+ */
+public interface TypeCode
+{
+	/**
+	 * A code denoting a null value.
+	 */
+	public byte NULL = -128;
+	
+	/**
+	 * A code denoting no value, which is different than NULL. For
+	 * example, an array is a sequence of values (some of which may
+	 * be NULL), terminated by a NONE.
+	 */
+	public byte NONE = -127;
+
+	//////////////////////////////////////////////////
+	// scalar values (but, also see tiny int below) //
+	//////////////////////////////////////////////////
+	
+	/**
+	 * A code denoting a false boolean value.
+	 */
+	public byte BOOLEAN_FALSE = -126;
+	
+	/**
+	 * A code denoting a true boolean value.
+	 */
+	public byte BOOLEAN_TRUE = -125;
+	
+	/**
+	 * A code denoting a signed byte.
+	 */
+	public byte BYTE = -124;
+	
+	/**
+	 * A code denoting a two byte signed short, msb first.
+	 */
+	public byte SHORT = -123;
+	
+	/**
+	 * A code denoting a four byte signed integer, msb first.
+	 */
+	public byte INT = -122;
+	
+	/**
+	 * A code denoting an eight byte signed long, msb first.
+	 */
+	public byte LONG = -121;
+	
+	/**
+	 * A code denoting a four byte ieee floating format number (single,
+	 * written as an INT).
+	 */
+	public byte FLOAT = -120;
+	
+	/**
+	 * A code denoting an eight byte ieee floating format number (double,
+	 * written as a LONG).
+	 */
+	public byte DOUBLE = -119;
+
+	////////////
+	// arrays //
+	////////////
+	
+	// BOOLS, SHORTS, INTS, LONGS, FLOATS, and DOUBLES are
+	// reserved for future use.
+
+//	/**
+//	 * A code denoting an array of booleans.
+//	 */
+//	public byte BOOLS = -118;
+	
+	/**
+	 * A code denoting an array of bytes.
+	 */
+	public byte BYTES = -117;
+
+//	/**
+//	 * A code denoting an array of shorts.
+//	 */
+//	public byte SHORTS = -116;
+
+//	/**
+//	 * A code denoting an array of ints.
+//	 */
+//	public byte INTS = -115;
+
+//	/**
+//	 * A code denoting an array of longs.
+//	 */
+//	public byte LONGS = -114;
+
+//	/**
+//	 * A code denoting an array of ieee format singles.
+//	 */
+//	public byte FLOATS = -113;
+
+//	/**
+//	 * A code denoting an array of ieee format doubles.
+//	 */
+//	public byte DOUBLES = -112;
+	
+	/**
+	 * A code denoting a sequence of values.
+	 */
+	public byte ARRAY = -111;
+	
+	/////////////
+	// strings //
+	/////////////
+	
+	/**
+	 * A code denoting an empty string.
+	 */
+	public byte EMPTY_STRING = -110;
+	
+	/**
+	 * A code denoting a utf-8 encoded string.
+	 */
+	public byte STRING = -109;
+
+	/////////////////////
+	// structured data //
+	/////////////////////
+	
+	/**
+	 * A code denoting a custom value (struct, exception, enum, extern)
+	 * from a value factory. An associated value identifies the specific
+	 * type. The format on the wire of STRUCT and CUSTOM are the same.
+	 * Emit CUSTOM instead of STRUCT, and accept STRUCT as if it were
+	 * CUSTOM.
+	 */
+	@Deprecated
+	public byte STRUCT = -108;
+	
+	/**
+	 * A code denoting a custom value (struct, exception, enum, extern)
+	 * from a value factory. An associated value identifies the specific
+	 * type. The format on the wire of STRUCT and CUSTOM are the same.
+	 * Emit CUSTOM instead of STRUCT, and accept STRUCT as if it were
+	 * CUSTOM.
+	 */
+	public byte CUSTOM = -107;
+
+	//////////
+	// misc //
+	//////////
+	
+	/**
+	 * A code denoting that any value is ok (as long as we know how
+	 * to serialize it). Dynamic methods should be applied to determine
+	 * the type. This type never appears on the wire.
+	 */
+	public byte ANY = -106;
+
+	///////////////////
+	// tiny integers //
+	///////////////////
+	
+	/**
+	 * Minimum "tiny" integer.
+	 */
+	public byte MIN_TINY_INT = -64;
+	
+	/**
+	 * Maximum "tiny" integer.
+	 */
+	public byte MAX_TINY_INT = 127;
+}
\ No newline at end of file
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/binary/BinaryTaggedData.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/binary/BinaryTaggedData.java
new file mode 100644
index 0000000..56746e7
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/binary/BinaryTaggedData.java
@@ -0,0 +1,236 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.fmt.binary;
+
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.transport.fmt.TaggedData;
+import org.apache.etch.bindings.java.transport.fmt.TypeCode;
+
+/**
+ * Common elements for binary tagged data input and output.
+ */
+public class BinaryTaggedData extends TaggedData
+{
+	/**
+	 * Sentinel which marks the end of a struct or array item list
+	 * in a binary input or output stream.
+	 */
+	public static final Object NONE = new Object()
+	{
+		@Override
+		public String toString()
+		{
+			return "NONE";
+		}
+	};
+	
+	/**
+	 * This is the current version of the protocol.
+	 */
+	public final static byte VERSION = 3;
+
+	/**
+	 * Constructs the BinaryTaggedData.
+	 *
+	 * @param vf
+	 */
+	public BinaryTaggedData( ValueFactory vf )
+	{
+		super( vf );
+	}
+
+	@Override
+	public byte checkValue( final Object value )
+	{
+		if (value == null)
+			return TypeCode.NULL;
+		
+		if (value == NONE)
+			return TypeCode.NONE;
+		
+		final Class<?> c = value.getClass();
+		
+		if (c == Boolean.class)
+			return (Boolean) value ? TypeCode.BOOLEAN_TRUE : TypeCode.BOOLEAN_FALSE;
+		
+		if (value instanceof Number)
+		{
+			if (c == Byte.class)
+				return checkByte( (Byte) value );
+			
+			if (c == Short.class)
+				return checkShort( (Short) value );
+				
+			if (c == Integer.class)
+				return checkInteger( (Integer) value );
+			
+			if (c == Long.class)
+				return checkLong( (Long) value );
+			
+			if (c == Float.class)
+				return TypeCode.FLOAT;
+			
+			if (c == Double.class)
+				return TypeCode.DOUBLE;
+			
+			return TypeCode.CUSTOM;
+		}
+		
+		if (c == String.class)
+		{
+			String s = (String) value;
+			
+			if (s.length() == 0)
+				return TypeCode.EMPTY_STRING;
+			
+			return TypeCode.STRING;
+		}
+		
+		if (c == StructValue.class)
+			return TypeCode.CUSTOM;
+		
+		if (c.isArray())
+		{
+//			if (c == boolean[].class) return TypeCode.BOOLS;
+			if (c == byte[].class) return TypeCode.BYTES;
+//			if (c == short[].class) return TypeCode.SHORTS;
+//			if (c == int[].class) return TypeCode.INTS;
+//			if (c == long[].class) return TypeCode.LONGS;
+//			if (c == float[].class) return TypeCode.FLOATS;
+//			if (c == double[].class) return TypeCode.DOUBLES;
+			return TypeCode.ARRAY;
+		}
+		
+		return TypeCode.CUSTOM;
+	}
+
+	@Override
+	public byte getNativeTypeCode( Class<?> c )
+	{
+		if (c == boolean.class)
+			return TypeCode.BOOLEAN_TRUE;
+		
+		if (c == byte.class)
+			return TypeCode.BYTE;
+		
+		if (c == short.class)
+			return TypeCode.SHORT;
+			
+		if (c == int.class)
+			return TypeCode.INT;
+		
+		if (c == long.class)
+			return TypeCode.LONG;
+		
+		if (c == float.class)
+			return TypeCode.FLOAT;
+		
+		if (c == double.class)
+			return TypeCode.DOUBLE;
+		
+		if (c == String.class)
+			return TypeCode.STRING;
+		
+		if (c == Object.class)
+			return TypeCode.ANY;
+		
+		return TypeCode.CUSTOM;
+	}
+
+	@Override
+	public Type getCustomStructType( Class<?> c )
+	{
+		return vf.getCustomStructType( c );
+	}
+
+	@Override
+	public Class<?> getNativeType( byte type )
+	{
+		switch (type)
+		{
+			case TypeCode.BOOLEAN_TRUE:
+			case TypeCode.BOOLEAN_FALSE:
+				return boolean.class;
+			
+			case TypeCode.BYTE:
+				return byte.class;
+			
+			case TypeCode.SHORT:
+				return short.class;
+			
+			case TypeCode.INT:
+				return int.class;
+			
+			case TypeCode.LONG:
+				return long.class;
+			
+			case TypeCode.FLOAT:
+				return float.class;
+			
+			case TypeCode.DOUBLE:
+				return double.class;
+			
+			case TypeCode.EMPTY_STRING:
+			case TypeCode.STRING:
+				return String.class;
+				
+			case TypeCode.ANY:
+				return Object.class;
+			
+			default:
+				throw new IllegalArgumentException( "unsupported native type "+type );
+		}
+	}
+
+	private static byte checkByte( byte v )
+	{
+		if (v >= TypeCode.MIN_TINY_INT && v <= TypeCode.MAX_TINY_INT)
+			return v;
+		
+		return TypeCode.BYTE;
+	}
+	
+	private static byte checkShort( short v )
+	{
+		if (v >= Byte.MIN_VALUE && v <= Byte.MAX_VALUE)
+			return checkByte( (byte) v );
+		
+		return TypeCode.SHORT;
+	}
+
+	private static byte checkInteger( int v )
+	{
+		if (v >= Short.MIN_VALUE && v <= Short.MAX_VALUE)
+			return checkShort( (short) v );
+		
+		return TypeCode.INT;
+	}
+
+	private static byte checkLong( long v )
+	{
+		if (v >= Integer.MIN_VALUE && v <= Integer.MAX_VALUE)
+			return checkInteger( (int) v );
+		
+		return TypeCode.LONG;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/binary/BinaryTaggedDataFormatFactory.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/binary/BinaryTaggedDataFormatFactory.java
new file mode 100644
index 0000000..6b97840
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/binary/BinaryTaggedDataFormatFactory.java
@@ -0,0 +1,44 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.fmt.binary;
+
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.transport.FormatFactory;
+import org.apache.etch.bindings.java.transport.TaggedDataInput;
+import org.apache.etch.bindings.java.transport.TaggedDataOutput;
+
+/**
+ * Format factory for binary tagged data.
+ */
+public class BinaryTaggedDataFormatFactory extends FormatFactory
+{
+	@Override
+	public TaggedDataInput newTaggedDataInput( ValueFactory vf, String uri )
+	{
+		return new BinaryTaggedDataInput( vf, uri );
+	}
+
+	@Override
+	public TaggedDataOutput newTaggedDataOutput( ValueFactory vf, String uri )
+	{
+		return new BinaryTaggedDataOutput( vf, uri );
+	}
+}
\ No newline at end of file
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/binary/BinaryTaggedDataInput.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/binary/BinaryTaggedDataInput.java
new file mode 100644
index 0000000..45237fb
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/binary/BinaryTaggedDataInput.java
@@ -0,0 +1,402 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.fmt.binary;
+
+import java.io.IOException;
+
+import org.apache.etch.bindings.java.msg.ComboValidator;
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Validator_int;
+import org.apache.etch.bindings.java.support.Validator_object;
+import org.apache.etch.bindings.java.support.Validator_string;
+import org.apache.etch.bindings.java.transport.ArrayValue;
+import org.apache.etch.bindings.java.transport.TaggedDataInput;
+import org.apache.etch.bindings.java.transport.fmt.TypeCode;
+import org.apache.etch.util.Assertion;
+import org.apache.etch.util.FlexBuffer;
+
+
+/**
+ * BinaryTaggedDataInput has methods to support reading tagged
+ * values from an input buffer.
+ */
+final public class BinaryTaggedDataInput extends BinaryTaggedData
+	implements TaggedDataInput
+{
+	/**
+	 * Constructs the BinaryTaggedDataInput with a null buffer.
+	 * 
+	 * @param vf the value factory for the service.
+	 * @param uri the uri used to construct the transport stack.
+	 */
+	public BinaryTaggedDataInput( ValueFactory vf, String uri )
+	{
+		super( vf );
+		// don't have anything to do with uri yet.
+	}
+
+	private FlexBuffer buf;
+	
+	private int lengthBudget;
+
+	/////////////////////////////
+	// TaggedDataInput methods //
+	/////////////////////////////
+	
+	public Message readMessage( FlexBuffer buf ) throws IOException
+	{
+		this.buf = buf;
+		
+		// lengthBudget is how many array elements total are reasonable to
+		// allocate while parsing this message. the largest value comes as each
+		// byte of the incoming message turned into an array element. the total
+		// will always be lower than this as often it takes multiple bytes to
+		// make a single array element. so, each time we make an array, we
+		// deduct the specified length from lengthBudget. if the result is
+		// negative, then either the incoming message is misformed or someone is
+		// trying to spoof us.
+		
+		lengthBudget = buf.avail();
+		
+		try
+		{
+			Message msg = startMessage();
+			readKeysAndValues( msg );
+			endMessage( msg );
+			return msg;
+		}
+		finally
+		{
+			this.buf = null;
+			lengthBudget = 0;
+		}
+	}
+
+	private StructValue readStruct() throws IOException
+	{
+		StructValue sv = startStruct();
+		readKeysAndValues( sv );
+		endStruct( sv );
+		return sv;
+	}
+	
+	private ArrayValue readArray( Validator v ) throws IOException
+	{
+		ArrayValue av = startArray();
+		readValues( av, v );
+		endArray( av );
+		return av;
+	}
+
+	private void readKeysAndValues( StructValue sv )
+		throws IOException
+	{
+		Type t = sv.type();
+		while (true)
+		{
+			Field key = readField( t );
+			if (key == null)
+				break;
+			
+			Validator v = t.getValidator( key );
+			if (v != null)
+			{
+				sv.put( key, readValue( v ) );
+			}
+			else
+			{
+				// read the value but ignore it.
+				Object obj = readValue( Validator_object.get( 0 ) );
+				if (false)
+					sv.put( key, obj );
+			}
+		}
+	}
+
+	private void readValues( ArrayValue av, Validator v ) throws IOException
+	{
+		Validator ev = v.elementValidator();
+		while (true)
+		{
+			Object value = readValue( ev, true );
+			if (value == NONE)
+				break;
+			
+			av.add( value );
+		}
+	}
+
+	////////////////////////
+	// Main input methods //
+	////////////////////////
+
+	private Message startMessage() throws IOException
+	{
+		byte version = buf.getByte();
+		
+		if (version != VERSION)
+			throw new IOException(
+				String.format(
+					"binary tagged data version mismatch: got %d expected %d",
+					version, VERSION ) );
+		
+		Type t = readType();
+		int length = readLength();
+		
+		return new Message( t, vf, length );
+	}
+
+	private void endMessage( Message msg )
+	{
+		// nothing to do, readKeysAndValues swallowed the NONE.
+	}
+
+	private StructValue startStruct() throws IOException
+	{
+		Type t = readType();
+		int length = readLength();
+		
+		return new StructValue( t, vf, length );
+	}
+
+	private void endStruct( StructValue struct )
+	{
+		// nothing to do, readKeysAndValues swallowed the NONE.
+	}
+
+	@SuppressWarnings("deprecation")
+	private ArrayValue startArray() throws IOException
+	{
+		byte type = buf.getByte();
+		
+		Type customStructType;
+		if (type == TypeCode.CUSTOM || type == TypeCode.STRUCT)
+			customStructType = readType();
+		else
+			customStructType = null;
+		
+		int dim = readIntegerValue();
+		if (dim <= 0 || dim > Validator.MAX_NDIMS)
+			throw new IllegalArgumentException(
+				"dim <= 0 || dim > Validator.MAX_NDIMS" );
+		
+		int length = readLength();
+		
+		Object array = allocArrayValue( type, customStructType, dim, length );
+		
+		return new ArrayValue( array, type, customStructType, dim );
+	}
+
+	private void endArray( ArrayValue array )
+	{
+		array.compact();
+	}
+	
+	private Type readType() throws IOException
+	{
+		Object obj = readValue( intOrStrValidator, false );
+		
+		if (obj instanceof Integer)
+		{
+			Integer id = (Integer) obj;
+			Type type = vf.getType( id );
+			
+			if (type == null)
+				type = new Type( id, id.toString() );
+			
+			return type;
+		}
+		
+		Assertion.check( obj instanceof String, "obj instanceof String" );
+		String name = (String) obj;
+		Type type = vf.getType( name );
+		
+		if (type == null)
+			type = new Type( name );
+		
+		return type;
+	}
+
+	private Field readField( Type type ) throws IOException
+	{
+		Object obj = readValue( intOrStrValidator, true );
+		
+		if (obj == NONE)
+			return null;
+		
+		if (obj instanceof Integer)
+		{
+			Integer id = (Integer) obj;
+			Field field = type.getField( id );
+			
+			if (field == null)
+				field = new Field( id, id.toString() );
+			
+			return field;
+		}
+		
+		Assertion.check( obj instanceof String, "obj instanceof String" );
+		String name = (String) obj;
+		Field field = type.getField( name );
+		
+		if (field == null)
+			field = new Field( name );
+		
+		return field;
+	}
+	
+	private final Validator intOrStrValidator =
+		new ComboValidator( Validator_int.get( 0 ), Validator_string.get( 0 ) );
+	
+	private int readLength() throws IOException
+	{
+		int length = readIntegerValue();
+		
+		if (length < 0 || length > lengthBudget)
+			throw new IllegalArgumentException(
+				"length < 0 || length > lengthBudget" );
+		
+		lengthBudget -= length;
+		
+		return length;
+	}
+	
+	private Integer readIntegerValue() throws IOException
+	{
+		return (Integer) readValue( intValidator );
+	}
+	
+	private final Validator intValidator = Validator_int.get( 0 );
+
+	///////////////////////////
+	// LOCAL UTILITY METHODS //
+	///////////////////////////
+	
+	private Object validateValue( Validator v, Object value )
+	{
+		// v == null more or less implies that a field is not known
+		// for a type. thus we don't care about the field value as
+		// we are going to ignore it. therefore, return null.
+		if (v == null)
+			return null;
+		
+		if (value == null)
+			return null;
+		
+		return v.validateValue( value );
+	}
+	
+	private Object validateValue( Validator v, boolean noneOk, Object value )
+	{
+		if (noneOk && value == NONE)
+			return value;
+		
+		return validateValue( v, value );
+	}
+	
+	private Object readValue( Validator v ) throws IOException
+	{
+		return readValue( v, false );
+	}
+	
+	@SuppressWarnings("deprecation")
+	private Object readValue( Validator v, boolean noneOk ) throws IOException
+	{
+		byte type = buf.getByte();
+		
+		switch (type)
+		{
+			case TypeCode.NULL:
+				return validateValue( v, null );
+			
+			case TypeCode.NONE:
+				return validateValue( v, noneOk, NONE );
+			
+			case TypeCode.BOOLEAN_FALSE:
+				return validateValue( v, Boolean.FALSE );
+			
+			case TypeCode.BOOLEAN_TRUE:
+				return validateValue( v, Boolean.TRUE );
+			
+			case TypeCode.BYTE:
+				return validateValue( v, buf.getByte() );
+			
+			case TypeCode.SHORT:
+				return validateValue( v, buf.getShort() );
+			
+			case TypeCode.INT:
+				return validateValue( v, buf.getInt() );
+			
+			case TypeCode.LONG:
+				return validateValue( v, buf.getLong() );
+			
+			case TypeCode.FLOAT:
+				return validateValue( v, buf.getFloat() );
+			
+			case TypeCode.DOUBLE:
+				return validateValue( v, buf.getDouble() );
+				
+			case TypeCode.BYTES:
+				return validateValue( v, readBytes() );
+
+//			reserved for future use:
+//			case TypeCode.BOOLS:
+//			case TypeCode.SHORTS:
+//			case TypeCode.INTS:
+//			case TypeCode.LONGS:
+//			case TypeCode.FLOATS:
+//			case TypeCode.DOUBLES:
+//				throw new UnsupportedOperationException( "unsupported type code "+type );
+				
+			case TypeCode.ARRAY:
+				return validateValue( v, fromArrayValue( readArray( v ) ) );
+			
+			case TypeCode.EMPTY_STRING:
+				return validateValue( v, "" );
+			
+			case TypeCode.STRING:
+				return validateValue( v, new String( readBytes(), vf.getStringEncoding() ) );
+			
+			case TypeCode.STRUCT:
+			case TypeCode.CUSTOM:
+				return validateValue( v, vf.importCustomValue( readStruct() ) );
+			
+			default:
+				if (type >= TypeCode.MIN_TINY_INT && type <= TypeCode.MAX_TINY_INT)
+					return validateValue( v, type );
+			
+				throw new UnsupportedOperationException( "unsupported type code "+type );
+		}
+	}
+	
+	private byte[] readBytes() throws IOException
+	{
+		int length = readLength();
+		byte[] b = new byte[length];
+		buf.getFully( b );
+		return b;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/binary/BinaryTaggedDataOutput.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/binary/BinaryTaggedDataOutput.java
new file mode 100644
index 0000000..cee858d
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/binary/BinaryTaggedDataOutput.java
@@ -0,0 +1,330 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.fmt.binary;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.msg.Validator.Level;
+import org.apache.etch.bindings.java.support.Validator_int;
+import org.apache.etch.bindings.java.support.Validator_string;
+import org.apache.etch.bindings.java.transport.ArrayValue;
+import org.apache.etch.bindings.java.transport.TaggedDataOutput;
+import org.apache.etch.bindings.java.transport.fmt.TypeCode;
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.URL;
+
+
+/**
+ * An implementation of TaggedDataOutput which uses a binary encoding.
+ */
+final public class BinaryTaggedDataOutput extends BinaryTaggedData
+	implements TaggedDataOutput
+{
+	/**
+	 * Name of uri parameter which controls whether we write ints or strings
+	 * for types and fields.
+	 */
+	public static final String STRING_TYPE_AND_FIELD =
+		"BinaryTaggedDataOutput.stringTypeAndField";
+
+	/**
+	 * Constructs the BinaryTaggedDataOutput.
+	 * 
+	 * @param vf the value factory for the service.
+	 * @param uri the uri used to construct the transport stack.
+	 */
+	public BinaryTaggedDataOutput( ValueFactory vf, String uri )
+	{
+		super( vf );
+		level = vf.getLevel();
+		URL u = new URL( uri );
+		stringTypeAndField = u.getBooleanTerm( STRING_TYPE_AND_FIELD, false );
+	}
+
+	private final Level level;
+	
+	private final boolean stringTypeAndField;
+
+	//////////////////////////////
+	// TaggedDataOutput methods //
+	//////////////////////////////
+
+	public void writeMessage( Message msg, FlexBuffer buf ) throws IOException
+	{
+		try
+		{
+			this.buf = buf;
+			startMessage( msg );
+			writeKeysAndValues( msg );
+			endMessage( msg );
+		}
+		finally
+		{
+			this.buf = null;
+		}
+	}
+
+	private FlexBuffer buf;
+
+	private void writeStruct( StructValue sv ) throws IOException
+	{
+		startStruct( sv );
+		writeKeysAndValues( sv );
+		endStruct( sv );
+	}
+
+	private void writeArray( ArrayValue av, Validator v ) throws IOException
+	{
+		startArray( av );
+		writeValues( av, v );
+		endArray( av );
+	}
+
+	private void writeKeysAndValues( StructValue sv ) throws IOException
+	{
+		Type t = sv.type();
+		for (Map.Entry<Field, Object> me: sv)
+		{
+			Field f = me.getKey();
+			writeField( f );
+			writeValue( t.getValidator( f ), me.getValue() );
+		}
+	}
+
+	private void writeValues( ArrayValue av, Validator v )
+		throws IOException
+	{
+		Validator ev = v.elementValidator();
+		for (Object value: av)
+			writeValue( ev, value );
+	}
+	
+	/////////////////////////
+	// Main output methods //
+	/////////////////////////
+
+	private void startMessage( Message msg ) throws IOException
+	{
+		// since message is top-level, no type code is written to
+		// indicate a message is starting. we do write a version
+		// number to indicate this version of the binary tagged
+		// data output format.
+		buf.putByte( VERSION );
+		startStruct( msg );
+	}
+
+	private void endMessage( Message msg ) throws IOException
+	{
+		endStruct( msg );
+	}
+
+	private void startStruct( StructValue struct ) throws IOException
+	{
+		// the caller has already written a type code to indicate a
+		// struct is starting. this code is shared by startMessage().
+		writeType( struct.type() );
+		writeIntValue( struct.size() );
+	}
+
+	private void endStruct( StructValue struct ) throws IOException
+	{
+		// this code is shared by endMessage.
+		writeNoneValue();
+	}
+
+	private void startArray( ArrayValue array ) throws IOException
+	{
+		// the caller has already written a type code to indicate an
+		// array is starting.
+		byte type = array.typeCode();
+		buf.putByte( type );
+		if (type == TypeCode.CUSTOM)
+			writeType( array.customStructType() );
+		writeIntValue( array.dim() );
+		writeIntValue( array.size() );
+	}
+
+	private void endArray( ArrayValue array ) throws IOException
+	{
+		writeNoneValue();
+	}
+	
+	private void writeType( Type type ) throws IOException
+	{
+		if (stringTypeAndField)
+			writeStringValue( type.getName() );
+		else
+			writeIntValue( type.getId() );
+	}
+	
+	private void writeField( Field field ) throws IOException
+	{
+		if (stringTypeAndField)
+			writeStringValue( field.getName() );
+		else
+			writeIntValue( field.getId() );
+	}
+
+	private void writeIntValue( Integer value ) throws IOException
+	{
+		writeValue( intValidator, value );
+	}
+	
+	private final Validator intValidator = Validator_int.get( 0 );
+	
+	private void writeStringValue( String value ) throws IOException
+	{
+		writeValue( stringValidator, value );
+	}
+	
+	private final Validator stringValidator = Validator_string.get( 0 );
+	
+	private void writeNoneValue() throws IOException
+	{
+		writeValue( noneValidator, NONE );
+	}
+	
+	private final Validator noneValidator = Validator_none.get();
+
+	///////////////////////////
+	// LOCAL UTILITY METHODS //
+	///////////////////////////
+
+	/**
+	 * @param v the validator for this value, or none if there
+	 * or none if there isn't one.
+	 * @param value
+	 * @throws IOException
+	 */
+	private void writeValue( Validator v, Object value ) throws IOException
+	{
+//		System.out.printf( "writeValue %s: %s\n", value, v );
+		
+		byte typeCode = checkValue( value );
+		
+		if (level != Level.NONE && value != null)
+		{
+		    if (level == Level.FULL && v == null)
+		    	throw new IllegalArgumentException(
+		    		"validator missing" );
+				
+			if (v != null && !v.validate( value ))
+				throw new IllegalArgumentException( String.format(
+					"validator %s failed for value %s",
+		    		v, value ) );
+		}
+		
+		buf.putByte( typeCode );
+
+		switch (typeCode)
+		{
+			case TypeCode.NULL:
+			case TypeCode.NONE:
+			case TypeCode.BOOLEAN_FALSE:
+			case TypeCode.BOOLEAN_TRUE:
+			case TypeCode.EMPTY_STRING:
+				return;
+			
+			case TypeCode.BYTE:
+				buf.putByte( ((Number) value).byteValue() );
+				return;
+			
+			case TypeCode.SHORT:
+				buf.putShort( ((Number) value).shortValue() );
+				return;
+			
+			case TypeCode.INT:
+				buf.putInt( ((Number) value).intValue() );
+				return;
+			
+			case TypeCode.LONG:
+				buf.putLong( ((Number) value).longValue() );
+				return;
+			
+			case TypeCode.FLOAT:
+				buf.putFloat( ((Number) value).floatValue() );
+				return;
+			
+			case TypeCode.DOUBLE:
+				buf.putDouble( ((Number) value).doubleValue() );
+				return;
+			
+			case TypeCode.BYTES:
+				writeBytes( (byte[]) value );
+				return;
+
+//			reserved for future use:
+//			case TypeCode.BOOLS:
+//			case TypeCode.SHORTS:
+//			case TypeCode.INTS:
+//			case TypeCode.LONGS:
+//			case TypeCode.FLOATS:
+//			case TypeCode.DOUBLES:
+//				throw new UnsupportedOperationException( "unsupported type code "+type );
+			
+			case TypeCode.ARRAY:
+				writeArray( toArrayValue( value, v ), v );
+				return;
+			
+			case TypeCode.STRING:
+				writeBytes( ((String) value).getBytes( vf.getStringEncoding() ) );
+				return;
+			
+			case TypeCode.CUSTOM:
+			{
+				StructValue struct = vf.exportCustomValue( value );
+				
+				if (struct == null)
+					throw new UnsupportedOperationException( "unsupported type "+value.getClass() );
+				
+				writeStruct( struct );
+				return;
+			}
+			
+			default:
+				// type is either "tiny" integer or unused...
+				
+				if (typeCode >= TypeCode.MIN_TINY_INT && typeCode <= TypeCode.MAX_TINY_INT)
+					return;
+			
+				throw new UnsupportedOperationException( "unsupported type code "+typeCode );
+		}
+	}
+
+	/**
+	 * Writes a value (signed or unsigned) to the output stream.
+	 * @param value the value to write to the output stream.
+	 * @throws IOException if there is a problem with the output stream.
+	 */
+	private void writeBytes( byte[] value ) throws IOException
+	{
+		int n = value.length;
+		writeIntValue( n );
+		buf.put( value, 0, n );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/binary/Validator_none.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/binary/Validator_none.java
new file mode 100644
index 0000000..dd63f65
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/binary/Validator_none.java
@@ -0,0 +1,69 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.fmt.binary;
+
+import org.apache.etch.bindings.java.msg.Validator;
+
+/**
+ * A validator for the special end of list marker,
+ * {@link BinaryTaggedData#NONE}.
+ */
+public class Validator_none implements Validator
+{
+	/**
+	 * @return the validator for BinaryTaggedData.NONE.
+	 */
+	public static Validator_none get()
+    {
+		if (validator == null)
+			validator = new Validator_none();
+	    
+		return validator;
+    }
+	
+	private static Validator_none validator;
+	
+	/**
+	 * Constructs the validator.
+	 */
+	public Validator_none()
+    {
+	    // nothing to do.
+    }
+
+    public Validator elementValidator()
+    {
+		throw new IllegalArgumentException( "not an array" );
+    }
+	
+	final public boolean validate( Object value )
+	{
+	    return value == BinaryTaggedData.NONE;
+	}
+
+	public Object validateValue( Object value )
+	{
+		if (validate( value ))
+			return value;
+		
+		throw new IllegalArgumentException( "value not appropriate for none: "+value );
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/xml/XmlTaggedData.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/xml/XmlTaggedData.java
new file mode 100644
index 0000000..1a21ca5
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/xml/XmlTaggedData.java
@@ -0,0 +1,127 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.fmt.xml;
+
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.transport.ArrayValue;
+import org.apache.etch.bindings.java.transport.fmt.TaggedData;
+import org.apache.etch.bindings.java.transport.fmt.TypeCode;
+
+/**
+ * XML tagged data implementation.
+ */
+public class XmlTaggedData extends TaggedData
+{
+	/**
+	 * @param vf
+	 */
+	public XmlTaggedData( ValueFactory vf )
+	{
+		super( vf );
+	}
+	
+	@Override
+	public byte checkValue( Object value )
+	{
+		if (value == null)
+			return TypeCode.NULL;
+		
+		Class<?> clss = value.getClass();
+		
+		if (value instanceof Number)
+		{
+			if (clss == Byte.class)
+				return TypeCode.BYTE;
+			
+			if (clss == Short.class)
+				return TypeCode.SHORT;
+				
+			if (clss == Integer.class)
+				return TypeCode.INT;
+			
+			if (clss == Long.class)
+				return TypeCode.LONG;
+			
+			if (clss == Float.class)
+				return TypeCode.FLOAT;
+				
+			if (clss == Double.class)
+				return TypeCode.DOUBLE;
+		}
+		else if (clss == String.class)
+		{
+			String s = (String) value;
+			
+			if (s.length() == 0)
+				return TypeCode.EMPTY_STRING;
+			
+			return TypeCode.STRING;
+		}
+		else if (clss == Boolean.class)
+		{
+			if ((Boolean) value)
+				return TypeCode.BOOLEAN_TRUE;
+			
+			return TypeCode.BOOLEAN_FALSE;
+		}
+		else if (clss == StructValue.class)
+		{
+			return TypeCode.CUSTOM;
+		}
+		else if (clss == ArrayValue.class)
+		{
+			return TypeCode.ARRAY;
+		}
+		else if (clss == byte[].class)
+		{
+			return TypeCode.BYTES;
+		}
+		else if (clss.isArray())
+		{
+			return TypeCode.ARRAY;
+		}
+		
+		return TypeCode.CUSTOM;
+	}
+
+	@Override
+	public Type getCustomStructType( Class<?> c )
+	{
+		// TODO implement getCustomStructType function
+		return null;
+	}
+
+	@Override
+	public Class<?> getNativeType( byte type )
+	{
+		// TODO implement getNativeType function
+		return null;
+	}
+
+	@Override
+	public byte getNativeTypeCode( Class<?> c )
+	{
+		// TODO implement getNativeTypeCode function
+		return 0;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/xml/XmlTaggedDataInput.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/xml/XmlTaggedDataInput.java
new file mode 100644
index 0000000..403fc10
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/xml/XmlTaggedDataInput.java
@@ -0,0 +1,294 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.fmt.xml;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.Iterator;
+import java.util.Stack;
+import java.util.StringTokenizer;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.transport.ArrayValue;
+import org.apache.etch.bindings.java.transport.TaggedDataInput;
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.core.xml.XmlParser;
+import org.apache.etch.util.core.xml.XmlParser.CdataElement;
+import org.apache.etch.util.core.xml.XmlParser.Element;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+
+
+/**
+ * XmlTaggedDataInput has methods to support reading xml data from an
+ * input stream.
+ */
+@SuppressWarnings("all")
+final public class XmlTaggedDataInput extends XmlTaggedData
+	implements TaggedDataInput, XmlTags
+{
+	/**
+	 * Constructs the XmlTaggedDataInput.
+	 * @param vf the value factory
+	 * @param rdr the reader
+	 */
+	public XmlTaggedDataInput( ValueFactory vf, Reader rdr )
+	{
+		super( vf );
+		this.rdr = rdr;
+	}
+	
+	private Reader rdr;
+	
+	/**
+	 * @param rdr
+	 */
+	public void setReader( Reader rdr )
+	{
+		this.rdr = rdr;
+	}
+	
+	private final Stack<TagElement> stack = new Stack<TagElement>();
+	
+	private final Stack<Iterator<Element>> elementList = new Stack<Iterator<Element>>();
+
+	public Message startMessage() throws IOException
+	{
+		stack.clear();
+		
+		TagElement te = new XmlParser().parseOne( rdr, null, MESSAGE_TAG );
+		stack.push( te );
+		elementList.push( te.getChildren() );
+		
+		Integer id = te.getIntAttr( null, STRUCT_TYPE_ATTR );
+		Type type = vf.getType( id );
+		return new Message( type, vf );
+	}
+
+	public void endMessage( Message msg )
+	{
+		elementList.pop();
+		if (!elementList.isEmpty())
+			throw new IllegalStateException( "!elementList.isEmpty()" );
+		
+		stack.pop();
+		if (!stack.isEmpty())
+			throw new IllegalStateException( "!stack.isEmpty()" );
+			
+	}
+
+	public StructValue startStruct()
+	{
+		TagElement te = stack.peek();
+		elementList.push( te.getChildren() );
+		
+		Integer id = te.getIntAttr( null, STRUCT_TYPE_ATTR );
+		Type type = vf.getType( id );
+		return new StructValue( type, vf );
+	}
+
+	public boolean readStructElement( StructElement se ) throws IOException
+	{
+		TagElement te = readNextTagElement();
+		if (te == null)
+			return false;
+		
+		Type t = null; // TODO this needs to come from somewhere.
+		Integer id = te.getIntAttr( null, KEY_ATTR );
+		se.key = t.getField( id );
+		
+		stack.push( te );
+		se.value = intReadValue();
+		stack.pop();
+		
+		return true;
+	}
+	
+	public static class StructElement
+	{
+		public Field key;
+		public Object value;
+	}
+
+	public void endStruct( StructValue struct )
+	{
+		elementList.pop();
+	}
+
+	public ArrayValue startArray()
+	{
+		TagElement te = stack.peek();
+		elementList.push( te.getChildren() );
+		return new ArrayValue( null );
+	}
+	
+	public static class ArrayElement
+	{
+		public Object value;
+	}
+
+	public boolean readArrayElement( ArrayElement ae ) throws IOException
+	{
+		TagElement te = readNextTagElement();
+		if (te == null)
+			return false;
+		
+		stack.push( te );
+		ae.value = intReadValue();
+		stack.pop();
+		
+		return true;
+	}
+
+	public void endArray( ArrayValue array )
+	{
+		elementList.pop();
+	}
+
+	public void close() throws IOException
+	{
+		rdr.close();
+	}
+	
+	private TagElement readNextTagElement() throws IOException
+	{
+		if (!elementList.peek().hasNext())
+			return null;
+		
+		Element e = elementList.peek().next();
+		while (!(e instanceof TagElement))
+		{
+			CdataElement ce = (CdataElement) e;
+			String s = ce.getCdata();
+			if (s.trim().length() != 0)
+				throw new IOException( "unexpected cdata in element: "+s );
+			
+			if (!elementList.peek().hasNext())
+				return null;
+			
+			e = elementList.peek().next();
+		}
+		
+		return (TagElement) e;
+	}
+	
+	private Object intReadValue() throws IOException
+	{
+		TagElement te = stack.peek();
+		System.out.printf( "readValue: %s\n", te );
+		String type = te.getAttr( null, ELEMENT_TYPE_ATTR );
+		
+		if (type.equals( NULL_TYPE ))
+			return null;
+		
+		if (type.equals( BOOLEAN_TYPE ))
+			return new Boolean( te.getCdataValue() );
+		
+		if (type.equals( INTEGER_TYPE ))
+			return new Integer( te.getCdataValue() );
+		
+		if (type.equals( LONG_TYPE ))
+			return new Long( te.getCdataValue() );
+		
+		if (type.equals( FLOAT_TYPE ))
+			return new Float( te.getCdataValue() );
+		
+		if (type.equals( DOUBLE_TYPE ))
+			return new Double( te.getCdataValue() );
+
+		if (type.equals( BYTES_TYPE ))
+			return string2bytes( te.getCdataValue() );
+		
+		if (type.equals( STRING_TYPE ))
+			return te.getCdataValue();
+		
+		if (type.equals( ARRAY_TYPE ))
+			return readArray(null);
+		
+		if (type.equals( STRUCT_TYPE ))
+			return readStruct();
+		
+		if (type.equals( CUSTOM_TYPE ))
+			return vf.importCustomValue( readStruct() );
+		
+		throw new UnsupportedOperationException( "unsupported type code "+type );
+	}
+	
+	private byte[] string2bytes( String s )
+	{
+		// TODO byte encoding could be base64 or something else more efficient.
+
+		ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		
+		StringTokenizer st = new StringTokenizer( s, " \t\r\n" );
+		while (st.hasMoreTokens())
+			baos.write( (byte) Integer.parseInt( st.nextToken(), 16 ) );
+		
+		return baos.toByteArray();
+	}
+
+	/**
+	 * @param vf the value factory.
+	 * @param s the message text.
+	 * @return the message read from the string.
+	 * @throws IOException
+	 */
+	public static Message readMessage( ValueFactory vf, String s )
+		throws IOException
+	{
+		return readMessage( vf, new StringReader( s ) );
+	}
+	
+	/**
+	 * @param vf the value factory.
+	 * @param rdr the source of message text.
+	 * @return the message read from the reader.
+	 * @throws IOException
+	 */
+	public static Message readMessage( ValueFactory vf, Reader rdr ) throws IOException
+	{
+		return new XmlTaggedDataInput( vf, rdr ).readMessage( null );
+	}
+	
+	public Message readMessage( FlexBuffer buf ) throws IOException
+	{
+		// TODO implement readMessage function
+		return null;
+	}
+
+	public StructValue readStruct() throws IOException
+	{
+		// TODO implement readStruct function
+		return null;
+	}
+
+	public ArrayValue readArray(Validator v) throws IOException
+	{
+		// TODO implement readArray function
+		return null;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/xml/XmlTaggedDataOutput.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/xml/XmlTaggedDataOutput.java
new file mode 100644
index 0000000..0617a30
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/xml/XmlTaggedDataOutput.java
@@ -0,0 +1,272 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.fmt.xml;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Stack;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.transport.ArrayValue;
+import org.apache.etch.bindings.java.transport.TaggedDataOutput;
+import org.apache.etch.bindings.java.transport.fmt.TypeCode;
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.core.xml.XmlParser.DefaultTagElement;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+
+
+/**
+ * Description of TaggedDataOutputStream.
+ */
+@SuppressWarnings("all")
+final public class XmlTaggedDataOutput extends XmlTaggedData
+	implements TaggedDataOutput, XmlTags
+{
+	/**
+	 * Constructs the TaggedDataOutputStream.
+	 *
+	 * @param wtr
+	 * @param vf
+	 */
+	public XmlTaggedDataOutput( Writer wtr, ValueFactory vf )
+	{
+		super( vf );
+		this.wtr = wtr;
+	}
+	
+	private final Writer wtr;
+	
+	private final Stack<TagElement> stack = new Stack<TagElement>();
+
+	public void startMessage( Message msg )
+	{
+		stack.clear();
+		TagElement te = new DefaultTagElement( MESSAGE_TAG );
+		te.setAttr( null, STRUCT_TYPE_ATTR, msg.type().getId() );
+		stack.push( te );
+	}
+
+	public void endMessage( Message msg ) throws IOException
+	{
+		TagElement te = stack.pop();
+		if (!stack.isEmpty())
+			throw new IOException( "stack sequence error: "+stack );
+		te.toString( wtr );
+	}
+
+	public void startStruct( StructValue struct )
+	{
+		// the caller has already created an element tag for us.
+		TagElement te = stack.peek();
+		te.setAttr( null, STRUCT_TYPE_ATTR, struct.type().getId() );
+	}
+
+	public void endStruct( StructValue struct )
+	{
+		// stack.pop();
+	}
+
+	public void startArray( ArrayValue array )
+	{
+		// the caller has already created an element tag for us.
+		// TagElement te = stack.peek();
+	}
+
+	public void endArray( ArrayValue array )
+	{
+		// stack.pop();
+	}
+
+	public void writeStructElement( Field key, Object value ) throws IOException
+	{
+		TagElement te = stack.peek().addTag( ELEMENT_TAG );
+		te.setAttr( null, KEY_ATTR, key.getId() );
+		stack.push( te );
+		writeValue( value );
+		stack.pop();
+	}
+
+	public void writeArrayElement( Object value ) throws IOException
+	{
+		TagElement te = stack.peek().addTag( ELEMENT_TAG );
+		stack.push( te );
+		writeValue( value );
+		stack.pop();
+	}
+	
+	public void close() throws IOException
+	{
+		wtr.close();
+	}
+	
+	@SuppressWarnings("deprecation")
+	private void writeValue( Object value ) throws IOException
+	{
+		// the caller has already created an element for us.
+		
+		TagElement te = stack.peek();
+		
+		int type = checkValue( value );
+		
+		switch (type)
+		{
+			case TypeCode.NULL:
+			{
+				te.setAttr( null, ELEMENT_TYPE_ATTR, NULL_TYPE );
+				break;
+			}
+			
+			case TypeCode.BOOLEAN_FALSE:
+			case TypeCode.BOOLEAN_TRUE:
+			{
+				te.setAttr( null, ELEMENT_TYPE_ATTR, BOOLEAN_TYPE );
+				te.addCdata( value.toString() );
+				break;
+			}
+			
+			case TypeCode.BYTE:
+			case TypeCode.SHORT:
+			case TypeCode.INT:
+			{
+				te.setAttr( null, ELEMENT_TYPE_ATTR, INTEGER_TYPE );
+				te.addCdata( value.toString() );
+				break;
+			}
+			
+			case TypeCode.LONG:
+			{
+				te.setAttr( null, ELEMENT_TYPE_ATTR, LONG_TYPE );
+				te.addCdata( value.toString() );
+				break;
+			}
+			
+			case TypeCode.FLOAT:
+			{
+				te.setAttr( null, ELEMENT_TYPE_ATTR, FLOAT_TYPE );
+				te.addCdata( value.toString() );
+				break;
+			}
+			
+			case TypeCode.DOUBLE:
+			{
+				te.setAttr( null, ELEMENT_TYPE_ATTR, DOUBLE_TYPE );
+				te.addCdata( value.toString() );
+				break;
+			}
+			
+			case TypeCode.BYTES:
+			{
+				byte[] b = (byte[]) value;
+				te.setAttr( null, ELEMENT_TYPE_ATTR, BYTES_TYPE );
+				te.addCdata( bytes2string( b ) );
+				break;
+			}
+			
+			case TypeCode.EMPTY_STRING:
+			case TypeCode.STRING:
+			{
+				String s = (String) value;
+				te.setAttr( null, ELEMENT_TYPE_ATTR, STRING_TYPE );
+				te.addCdata( s );
+				break;
+			}
+			
+			case TypeCode.ARRAY:
+				te.setAttr( null, ELEMENT_TYPE_ATTR, ARRAY_TYPE );
+				if (value instanceof ArrayValue)
+					writeArray( (ArrayValue) value, null );
+				else
+					writeArray( toArrayValue( value, null ), null );
+				break;
+				
+			case TypeCode.STRUCT:
+			case TypeCode.CUSTOM:
+			{
+				StructValue struct = vf.exportCustomValue( value );
+				
+				if (struct == null)
+					throw new UnsupportedOperationException( "unsupported type "+value.getClass() );
+				
+				te.setAttr( null, ELEMENT_TYPE_ATTR, CUSTOM_TYPE );
+				writeStruct( struct );
+				break;
+			}
+			
+			default:
+				throw new IllegalArgumentException( "unsupported type code "+type );
+		}
+	}
+
+	private String bytes2string( byte[] buf )
+	{
+		StringBuffer sb = new StringBuffer();
+		for (byte b: buf)
+		{
+			if (sb.length() > 0)
+				sb.append( ' ' );
+			sb.append( Integer.toString( b, 16 ) );
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * @param msg
+	 * @param vf
+	 * @return the xml of the specified message.
+	 * @throws IOException
+	 */
+	public static String getXml( Message msg, ValueFactory vf ) throws IOException
+	{
+		StringWriter sw = new StringWriter();
+		TaggedDataOutput tdo = new XmlTaggedDataOutput( sw, vf );
+		tdo.writeMessage( msg, null );
+		return sw.toString();
+	}
+
+	public void setBuffer( FlexBuffer msgBuf )
+	{
+		// TODO implement setBuffer function
+		
+	}
+
+	public void writeMessage( Message msg, FlexBuffer buf ) throws IOException
+	{
+		// TODO implement writeMessage function
+		
+	}
+
+	private void writeStruct( StructValue sv ) throws IOException
+	{
+		// TODO implement writeStruct function
+		
+	}
+
+	private void writeArray( ArrayValue av, Validator v ) throws IOException
+	{
+		// TODO implement writeArray function
+		
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/xml/XmlTags.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/xml/XmlTags.java
new file mode 100644
index 0000000..8ae2fd3
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/transport/fmt/xml/XmlTags.java
@@ -0,0 +1,130 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.fmt.xml;
+
+/**
+ * The tag names, etc., used by the demonstration xml message formatter.
+ */
+public interface XmlTags
+{
+	// tags
+	
+	/**
+	 * The tag of a message. A message tag has the attributes and
+	 * elements of a struct element.
+	 */
+	public String MESSAGE_TAG = "m";
+
+	/**
+	 * The tag of an element. An element is an item nested within an
+	 * message, struct, array, or custom type. An element has a data
+	 * type attribute. If the element is contained within a message,
+	 * struct, or custom element, it has a key attribute. If the
+	 * element is a struct or custom element, it has a struct type
+	 * attribute.
+	 */
+	public String ELEMENT_TAG = "e";
+	
+	// attributes
+
+	/**
+	 * The integer type of the message.
+	 */
+	public String STRUCT_TYPE_ATTR = "t";
+
+	/**
+	 * The type of the element.
+	 */
+	public String ELEMENT_TYPE_ATTR = "d";
+
+	/**
+	 * The integer key of an element within a message or struct element.
+	 */
+	public String KEY_ATTR = "k";
+	
+	// types
+
+	/**
+	 * The element represents the null value.
+	 */
+	public String NULL_TYPE = "n";
+
+	/**
+	 * The element represents a boolean value, with cdata true or false.
+	 */
+	public String BOOLEAN_TYPE = "b";
+
+	/**
+	 * The element represents an integral type (32-bit signed). Cdata is
+	 * the string format of the value.
+	 */
+	public String INTEGER_TYPE = "i";
+
+	/**
+	 * The element represents an integral type (64-bit signed). Cdata is
+	 * the string format of the value.
+	 */
+	public String LONG_TYPE = "l";
+
+	/**
+	 * The element represents a floating type (32-bit signed). Cdata is
+	 * the string format of the value.
+	 */
+	public String FLOAT_TYPE = "f";
+
+	/**
+	 * The element represents an floating type (64-bit signed). Cdata is
+	 * the string format of the value.
+	 */
+	public String DOUBLE_TYPE = "d";
+
+	/**
+	 * The element represents a byte array type. Cdata is a space-separated
+	 * list of hex values (00-ff).
+	 */
+	public String BYTES_TYPE = "y";
+
+	/**
+	 * The element represents a string type. Cdata is the character data
+	 * of the string.
+	 */
+	public String STRING_TYPE = "s";
+	
+	/**
+	 * The element represents a struct type. A struct has child elements
+	 * with key attributes which represent the key / value pairs of the
+	 * struct. The keys are integers.
+	 */
+	public String STRUCT_TYPE = "x";
+
+	/**
+	 * The element represents an array type. An array has an ordered
+	 * sequence of child elements.
+	 */
+	public String ARRAY_TYPE = "a";
+
+	/**
+	 * The element represents a custom data type. It has a code which
+	 * identifies the type and has one or more child elements which
+	 * represent the internal state of the data type.
+	 */
+	public String CUSTOM_TYPE = "c";
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/DateSerializer.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/DateSerializer.java
new file mode 100644
index 0000000..453f2a8
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/DateSerializer.java
@@ -0,0 +1,82 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.util;
+
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.Validator_long;
+
+
+/**
+ * An etch serializer for Date.
+ */
+public class DateSerializer implements ImportExportHelper
+{
+	private final static String FIELD_NAME = "dateTime";
+
+	/**
+	 * Defines custom fields in the value factory so that the importer
+	 * can find them.
+	 * @param type
+	 * @param class2type
+	 */
+	public static void init( Type type, Class2TypeMap class2type )
+	{
+		Field field = type.getField( FIELD_NAME );
+		class2type.put( Date.class, type );
+		type.setComponentType( Date.class );
+		type.setImportExportHelper( new DateSerializer( type, field ) );
+		type.putValidator( field, Validator_long.get( 0 ) );
+		type.lock();
+	}
+
+	/**
+	 * @param type
+	 * @param field
+	 */
+	public DateSerializer( Type type, Field field )
+	{
+		this.type = type;
+		this.field = field;
+	}
+	
+	private final Type type;
+	
+	private final Field field;
+
+	public Object importValue( StructValue struct )
+	{
+		return new Date( (Long) struct.get( field ) );
+	}
+
+	public StructValue exportValue( ValueFactory vf, Object value )
+	{
+		StructValue struct = new StructValue( type, vf );
+		struct.put( field, ((Date) value).getTime() );
+		return struct;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/ListSerializer.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/ListSerializer.java
new file mode 100644
index 0000000..be2ba66
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/ListSerializer.java
@@ -0,0 +1,96 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.Validator_object;
+
+
+/**
+ * Serializer for generic List<Object>.
+ */
+public class ListSerializer implements ImportExportHelper
+{
+	private final static String FIELD_NAME = "values";
+
+	/**
+	 * Defines custom fields in the value factory so that the importer
+	 * can find them.
+	 * @param type
+	 * @param class2type
+	 */
+	public static void init( Type type, Class2TypeMap class2type )
+    {
+		Field field = type.getField( FIELD_NAME );
+		class2type.put( ArrayList.class, type );
+		type.setComponentType( List.class );
+		type.setImportExportHelper( new ListSerializer( type, field ) );
+		type.putValidator( field, Validator_object.get( 1 ) );
+		type.lock();
+    }
+
+	/**
+	 * @param type
+	 * @param field
+	 */
+	public ListSerializer( Type type, Field field )
+	{
+		this.type = type;
+		this.field = field;
+	}
+	
+	private final Type type;
+	
+	private final Field field;
+	
+	public Object importValue( StructValue struct )
+	{
+		struct.checkType( type );
+		Object[] values = (Object[]) struct.get( field );
+		
+		List<Object> list = new ArrayList<Object>( values.length );
+		for( Object value: values)
+			list.add( value );
+		
+		return list;
+	}
+
+	@SuppressWarnings("unchecked")
+	public StructValue exportValue( ValueFactory vf, Object value )
+	{
+		List<Object> list = (List<Object>) value;
+		
+		Object[] values = new Object[list.size()];
+		list.toArray( values );
+		
+		StructValue struct = new StructValue( type, vf );
+		struct.put( field, values );
+		return struct;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/MapSerializer.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/MapSerializer.java
new file mode 100644
index 0000000..cd45ffe
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/MapSerializer.java
@@ -0,0 +1,112 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.Validator_object;
+
+
+/**
+ * Serializer for generic Map<Object, Object>.
+ */
+public class MapSerializer implements ImportExportHelper
+{
+	private final static String FIELD_NAME = "keysAndValues";
+
+	/**
+	 * Defines custom fields in the value factory so that the importer
+	 * can find them.
+	 * @param type
+	 * @param class2type
+	 */
+	public static void init( Type type, Class2TypeMap class2type )
+    {
+		Field field = type.getField( FIELD_NAME );
+		
+		// quick lookup to serialize this class.
+		class2type.put( HashMap.class, type );
+		
+		// type for arrays.
+		type.setComponentType( Map.class );
+		
+		type.setImportExportHelper( new MapSerializer( type, field ) );
+		type.putValidator( field, Validator_object.get( 1 ) );
+		type.lock();
+    }
+
+	/**
+	 * @param type
+	 * @param field
+	 */
+	public MapSerializer( Type type, Field field )
+	{
+		this.type = type;
+		this.field = field;
+	}
+	
+	private final Type type;
+	
+	private final Field field;
+	
+	public Object importValue( StructValue struct )
+	{
+		struct.checkType( type );
+		Object[] keysAndValues = (Object[]) struct.get( field );
+		int n = keysAndValues.length;
+		
+		Map<Object, Object> map = new HashMap<Object, Object>( (n*2+2)/3, 0.75f ); // (n/2)*4/3
+		int index = 0;
+		while (index < n)
+		{
+			Object key = keysAndValues[index++];
+			Object value = keysAndValues[index++];
+			map.put( key, value );
+		}
+		
+		return map;
+	}
+
+	@SuppressWarnings("unchecked")
+	public StructValue exportValue( ValueFactory vf, Object value )
+	{
+		Map<Object, Object> map = (Map<Object, Object>) value;
+		
+		Object[] keysAndValues = new Object[map.size()*2];
+		int index = 0;
+		for (java.util.Map.Entry<Object, Object> me: map.entrySet())
+		{
+			keysAndValues[index++] = me.getKey();
+			keysAndValues[index++] = me.getValue();
+		}
+		
+		StructValue struct = new StructValue( type, vf );
+		struct.put( field, keysAndValues );
+		return struct;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/SetSerializer.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/SetSerializer.java
new file mode 100644
index 0000000..438bebc
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/SetSerializer.java
@@ -0,0 +1,98 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.util;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.Validator_object;
+
+
+/**
+ * Serializer for generic Set<Object>.
+ */
+public class SetSerializer implements ImportExportHelper
+{
+	private final static String FIELD_NAME = "keys";
+
+	/**
+	 * Defines custom fields in the value factory so that the importer
+	 * can find them.
+	 * @param type
+	 * @param class2type
+	 */
+	public static void init( Type type, Class2TypeMap class2type )
+    {
+		Field field = type.getField( FIELD_NAME );
+		
+		class2type.put( HashSet.class, type );
+		type.setComponentType( Set.class );
+		
+		type.setImportExportHelper( new SetSerializer( type, field ) );
+		type.putValidator( field, Validator_object.get( 1 ) );
+		type.lock();
+    }
+
+	/**
+	 * @param type
+	 * @param field
+	 */
+	public SetSerializer( Type type, Field field )
+	{
+		this.type = type;
+		this.field = field;
+	}
+	
+	private final Type type;
+	
+	private final Field field;
+	
+	public Object importValue( StructValue struct )
+	{
+		struct.checkType( type );
+		Object[] keys = (Object[]) struct.get( field );
+		
+		Set<Object> set = new HashSet<Object>( (keys.length*4+2)/3, .75f );
+		for (Object key: keys)
+			set.add( key );
+		
+		return set;
+	}
+
+	@SuppressWarnings("unchecked")
+	public StructValue exportValue( ValueFactory vf, Object value )
+	{
+		Set<Object> set = (Set<Object>) value;
+		
+		Object[] keys = new Object[set.size()];
+		set.toArray( keys );
+		
+		StructValue struct = new StructValue( type, vf );
+		struct.put( field, keys );
+		return struct;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/StrIntHashMap.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/StrIntHashMap.java
new file mode 100644
index 0000000..9b4310e
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/StrIntHashMap.java
@@ -0,0 +1,48 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.util;
+
+import java.util.HashMap;
+
+/**
+ * A HashMap which is from String to Integer.
+ */
+public class StrIntHashMap extends HashMap<String, Integer>
+{
+	private static final long serialVersionUID = -9162231227512652630L;
+
+	/**
+	 * Constructs a StrIntHashMap initialized from another.
+	 * @param other
+	 */
+	public StrIntHashMap( StrIntHashMap other )
+	{
+		super( other );
+	}
+	
+	/**
+	 * Constructs a StrIntHashMap.
+	 */
+	public StrIntHashMap()
+	{
+		// nothing to do.
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/StrIntHashMapSerializer.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/StrIntHashMapSerializer.java
new file mode 100644
index 0000000..ca42d79
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/StrIntHashMapSerializer.java
@@ -0,0 +1,104 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.util;
+
+import java.util.Map;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.Validator_object;
+
+
+/**
+ * An etch serializer for StrIntHashMap.
+ */
+public class StrIntHashMapSerializer implements ImportExportHelper
+{
+	private final static String FIELD_NAME = "keysAndValues";
+
+	/**
+	 * Defines custom fields in the value factory so that the importer
+	 * can find them.
+	 * @param type
+	 * @param class2type
+	 */
+	public static void init( Type type, Class2TypeMap class2type )
+    {
+		Field field = type.getField( FIELD_NAME );
+		class2type.put( StrIntHashMap.class, type );
+		type.setComponentType( StrIntHashMap.class );
+		type.setImportExportHelper( new StrIntHashMapSerializer( type, field ) );
+		type.putValidator( field, Validator_object.get( 1 ) );
+		type.lock();
+    }
+
+	/**
+	 * @param type
+	 * @param field
+	 */
+	public StrIntHashMapSerializer( Type type, Field field )
+	{
+		this.type = type;
+		this.field = field;
+	}
+	
+	private final Type type;
+	
+	private final Field field;
+	
+	public Object importValue( StructValue struct )
+	{
+		StrIntHashMap map = new StrIntHashMap();
+		
+		Object[] keysAndValues = (Object[]) struct.get( field );
+		int n = keysAndValues.length;
+		int index = 0;
+		while (index < n)
+		{
+			String key = (String) keysAndValues[index++];
+			Integer value = (Integer) keysAndValues[index++];
+			map.put( key, value );
+		}
+		
+		return map;
+	}
+
+	public StructValue exportValue( ValueFactory vf, Object value )
+	{
+		StrIntHashMap map = (StrIntHashMap) value;
+		
+		Object[] keysAndValues = new Object[map.size()*2];
+		int index = 0;
+		for (Map.Entry<String, Integer> me: map.entrySet())
+		{
+			keysAndValues[index++] = me.getKey();
+			keysAndValues[index++] = me.getValue();
+		}
+		
+		StructValue struct = new StructValue( type, vf );
+		struct.put( field, keysAndValues );
+		return struct;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/StrStrHashMap.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/StrStrHashMap.java
new file mode 100644
index 0000000..c96bb8c
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/StrStrHashMap.java
@@ -0,0 +1,55 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.util;
+
+import java.util.HashMap;
+
+/**
+ * A HashMap which is from String to String.
+ * 
+ * To use StrStrHashMap in an etch service, define an extern type and prefix
+ * it with this annotation:
+ * 
+ * @Extern( java, "org.apache.etch.bindings.java.util.StrStrHashMap", "",
+ *   "org.apache.etch.bindings.java.util.StrStrHashMapSerializer", "" )
+ * extern StrStrHashMap
+ */
+public class StrStrHashMap extends HashMap<String, String>
+{
+	private static final long serialVersionUID = 6910845292628589771L;
+
+	/**
+	 * Constructs a StrStrHashMap initialized from another.
+	 * @param other
+	 */
+	public StrStrHashMap( StrStrHashMap other )
+	{
+		super( other );
+	}
+	
+	/**
+	 * Constructs a StrStrHashMap.
+	 */
+	public StrStrHashMap()
+	{
+		// nothing to do.
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/StrStrHashMapSerializer.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/StrStrHashMapSerializer.java
new file mode 100644
index 0000000..a364ee9
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/StrStrHashMapSerializer.java
@@ -0,0 +1,104 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.util;
+
+import java.util.Map;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.Validator_object;
+
+
+/**
+ * An etch serializer for StrStrHashMap.
+ */
+public class StrStrHashMapSerializer implements ImportExportHelper
+{
+	private final static String FIELD_NAME = "keysAndValues";
+
+	/**
+	 * Defines custom fields in the value factory so that the importer
+	 * can find them.
+	 * @param type
+	 * @param class2type
+	 */
+	public static void init( Type type, Class2TypeMap class2type )
+    {
+		Field field = type.getField( FIELD_NAME );
+		class2type.put( StrStrHashMap.class, type );
+		type.setComponentType( StrStrHashMap.class );
+		type.setImportExportHelper( new StrStrHashMapSerializer( type, field ) );
+		type.putValidator( field, Validator_object.get( 1 ) );
+		type.lock();
+    }
+
+	/**
+	 * @param type
+	 * @param field
+	 */
+	public StrStrHashMapSerializer( Type type, Field field )
+	{
+		this.type = type;
+		this.field = field;
+	}
+	
+	private final Type type;
+	
+	private final Field field;
+	
+	public Object importValue( StructValue struct )
+	{
+		StrStrHashMap map = new StrStrHashMap();
+		
+		Object[] keysAndValues = (Object[]) struct.get( field );
+		int n = keysAndValues.length;
+		int index = 0;
+		while (index < n)
+		{
+			String key = (String) keysAndValues[index++];
+			String value = (String) keysAndValues[index++];
+			map.put( key, value );
+		}
+		
+		return map;
+	}
+
+	public StructValue exportValue( ValueFactory vf, Object value )
+	{
+		StrStrHashMap map = (StrStrHashMap) value;
+		
+		Object[] keysAndValues = new Object[map.size()*2];
+		int index = 0;
+		for (Map.Entry<String, String> me: map.entrySet())
+		{
+			keysAndValues[index++] = me.getKey();
+			keysAndValues[index++] = me.getValue();
+		}
+		
+		StructValue struct = new StructValue( type, vf );
+		struct.put( field, keysAndValues );
+		return struct;
+	}
+}
diff --git a/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/URLSerializer.java b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/URLSerializer.java
new file mode 100644
index 0000000..d356773
--- /dev/null
+++ b/binding-java/runtime/src/main/java/org/apache/etch/bindings/java/util/URLSerializer.java
@@ -0,0 +1,81 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.util;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.Validator_string;
+import org.apache.etch.util.URL;
+
+
+/**
+ * An etch serializer for URL.
+ */
+public class URLSerializer implements ImportExportHelper
+{
+	private final static String FIELD_NAME = "urlStr";
+
+	/**
+	 * Defines custom fields in the value factory so that the importer
+	 * can find them.
+	 * @param type
+	 * @param class2type
+	 */
+	public static void init( Type type, Class2TypeMap class2type )
+	{
+		Field field = type.getField( FIELD_NAME );
+		class2type.put( URL.class, type );
+		type.setComponentType( URL.class );
+		type.setImportExportHelper( new URLSerializer( type, field ) );
+		type.putValidator( field, Validator_string.get( 0 ) );
+		type.lock();
+	}
+
+	/**
+	 * @param type
+	 * @param field
+	 */
+	public URLSerializer( Type type, Field field )
+	{
+		this.type = type;
+		this.field = field;
+	}
+	
+	private final Type type;
+	
+	private final Field field;
+
+	public Object importValue( StructValue struct )
+	{
+		return new URL( (String) struct.get( field ) );
+	}
+
+	public StructValue exportValue( ValueFactory vf, Object value )
+	{
+		StructValue struct = new StructValue( type, vf );
+		struct.put( field, ((URL) value).toString() );
+		return struct;
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestComboValidator.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestComboValidator.java
new file mode 100644
index 0000000..920b243
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestComboValidator.java
@@ -0,0 +1,155 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+
+import org.apache.etch.bindings.java.support.Validator_boolean;
+import org.apache.etch.bindings.java.support.Validator_int;
+import org.junit.Test;
+
+
+/** Test ComboValidator */
+public class TestComboValidator
+{
+	/** @throws Exception */
+	@Test
+	public void test() throws Exception
+	{
+		test( 0, "(int[0] OR boolean[0])", true, 123456789012L );
+		test( 0, "(int[0] OR boolean[0])", false, -123456789012L );
+// TODO		test( 0, "(int[0] OR boolean[0])", TypeCode.BYTE1, 0, (long) 3 );
+		test( 0, "(int[0] OR boolean[0])", 1, (float) 4 );
+		test( 0, "(int[0] OR boolean[0])", -1, (double) 5 );
+		test( 0, "(int[0] OR boolean[0])", 127, "abc" );
+		test( 0, "(int[0] OR boolean[0])", -128, new Object() );
+		test( 0, "(int[0] OR boolean[0])", 32767, new int[] {} );
+		test( 0, "(int[0] OR boolean[0])", -32768, new boolean[] {} );
+		test( 0, "(int[0] OR boolean[0])", 1000000000, new Date() );
+		test( 0, "(int[0] OR boolean[0])", -1000000000, int.class );
+		test( 1, "(int[1] OR boolean[1])", new int[] {}, 0 );
+		test( 1, "(int[1] OR boolean[1])", new boolean[] {}, true );
+	}
+	
+	private void test( int n, String s, Object good, Object bad )
+	{
+		Validator_int v1 = Validator_int.get( n );
+		Validator_boolean v2 = Validator_boolean.get( n );
+		ComboValidator v = new ComboValidator( v1, v2 );
+		
+		assertEquals( s, v.toString() );
+		assertTrue( v.validate( good ) );
+		assertFalse( v.validate( bad ) );
+		if (n > 0)
+		{
+			v.elementValidator();
+		}
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void test2() throws Exception
+	{
+		Validator v1 = Validator_int.get( 1 );
+		Validator v2 = Validator_boolean.get( 0 );
+		Validator v = new ComboValidator( v1, v2 );
+
+		assertTrue( v.validate( new int[] {} ) );
+		assertTrue( v.validate( true ) );
+		assertTrue( v.validate( false ) );
+		assertFalse( v.validate( 0 ) );
+		
+		v = v.elementValidator();
+
+		assertFalse( v.validate( new int[] {} ) );
+		assertFalse( v.validate( true ) );
+		assertFalse( v.validate( false ) );
+		assertTrue( v.validate( 0 ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void test3() throws Exception
+	{
+		Validator v1 = Validator_boolean.get( 0 );
+		Validator v2 = Validator_int.get( 1 );
+		Validator v = new ComboValidator( v1, v2 );
+
+		assertTrue( v.validate( new int[] {} ) );
+		assertTrue( v.validate( true ) );
+		assertTrue( v.validate( false ) );
+		assertFalse( v.validate( 0 ) );
+		
+		v = v.elementValidator();
+
+		assertFalse( v.validate( new int[] {} ) );
+		assertFalse( v.validate( true ) );
+		assertFalse( v.validate( false ) );
+		assertTrue( v.validate( 0 ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void test4() throws Exception
+	{
+		Validator v1 = Validator_boolean.get( 0 );
+		Validator v2 = Validator_int.get( 1 );
+		Validator v = new ComboValidator( v1, v2 );
+
+		assertTrue( v.validate( new int[] {} ) );
+		assertTrue( v.validate( true ) );
+		assertTrue( v.validate( false ) );
+		assertFalse( v.validate( 0 ) );
+		
+		v = v.elementValidator();
+
+		assertFalse( v.validate( new int[] {} ) );
+		assertFalse( v.validate( true ) );
+		assertFalse( v.validate( false ) );
+		assertTrue( v.validate( 0 ) );
+		
+		v = v.elementValidator();
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void test5() throws Exception
+	{
+		Validator v1 = Validator_boolean.get( 1 );
+		Validator v2 = Validator_int.get( 1 );
+		Validator v = new ComboValidator( v1, v2 );
+
+		assertTrue( v.validate( new boolean[] {} ) );
+		assertTrue( v.validate( new int[] {} ) );
+		
+		v = v.elementValidator();
+
+		assertTrue( v.validate( true ) );
+		assertTrue( v.validate( false ) );
+		assertTrue( v.validate( 0 ) );
+		
+		v = v.elementValidator();
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestField.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestField.java
new file mode 100644
index 0000000..2e67923
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestField.java
@@ -0,0 +1,63 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.etch.util.Hash;
+import org.junit.Test;
+
+
+/** Test of Field */
+public class TestField
+{
+	/** */
+	@Test
+	public void fieldIntegerString()
+	{
+		testMf( 1, "one" );
+		testMf( 2, "two" );
+		testMf( 3, "three" );
+	}
+
+	/** */
+	@Test
+	public void fieldString()
+	{
+		testMf( "one" );
+		testMf( "two" );
+		testMf( "three" );
+	}
+
+	private void testMf( int id, String name )
+	{
+		Field mf = new Field( id, name );
+		assertEquals( id, mf.getId() );
+		assertEquals( name, mf.getName() );
+	}
+
+	private void testMf( String name )
+	{
+		Field mf = new Field( name );
+		assertEquals( Hash.hash( name ), mf.getId() );
+		assertEquals( name, mf.getName() );
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestFieldMap.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestFieldMap.java
new file mode 100644
index 0000000..e603d1e
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestFieldMap.java
@@ -0,0 +1,40 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+/**
+ * Test of FieldMap.
+ */
+public class TestFieldMap
+{
+	/** @throws Exception */
+	@Test
+	public void makeNew() throws Exception
+	{
+		FieldMap fm = new FieldMap();
+		Field f = fm.makeNew( "fred" );
+		assertEquals( new Field("fred"), f );
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestIdName.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestIdName.java
new file mode 100644
index 0000000..2aca1fe
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestIdName.java
@@ -0,0 +1,111 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.etch.util.Hash;
+import org.junit.Test;
+
+
+/** */
+public class TestIdName
+{
+	/** */
+	@Test
+	public void getId()
+	{
+		assertEquals( 1, new IdName( 1, "foo" ).getId() );
+		assertEquals( 1, new IdName( 1, "bar" ).getId() );
+		assertEquals( 2, new IdName( 2, "foo" ).getId() );
+		assertEquals( 2, new IdName( 2, "bar" ).getId() );
+	}
+
+	/** */
+	@Test
+	public void getName()
+	{
+		assertEquals( "foo", new IdName( 1, "foo" ).getName() );
+		assertEquals( "bar", new IdName( 1, "bar" ).getName() );
+		assertEquals( "foo", new IdName( 2, "foo" ).getName() );
+		assertEquals( "bar", new IdName( 2, "bar" ).getName() );
+	}
+
+	/** */
+	@Test
+	public void xtoString()
+	{
+		assertEquals( "foo(1)", new IdName( 1, "foo" ).toString() );
+		assertEquals( "bar(1)", new IdName( 1, "bar" ).toString() );
+		assertEquals( "foo(2)", new IdName( 2, "foo" ).toString() );
+		assertEquals( "bar(2)", new IdName( 2, "bar" ).toString() );
+	}
+
+	/** */
+	@Test
+	public void equalsObject()
+	{
+		assertTrue( new IdName( 1, "foo" ).equals( new IdName( 1, "foo" ) ) );
+		assertTrue( new IdName( 1, "bar" ).equals( new IdName( 1, "bar" ) ) );
+		assertTrue( new IdName( 2, "foo" ).equals( new IdName( 2, "foo" ) ) );
+		assertTrue( new IdName( 2, "bar" ).equals( new IdName( 2, "bar" ) ) );
+		
+		assertFalse( new IdName( 1, "foo" ).equals( new IdName( 2, "foo" ) ) ); // id changed
+		assertFalse( new IdName( 1, "foo" ).equals( new IdName( 1, "bar" ) ) ); // name changed
+		assertFalse( new IdName( 1, "foo" ).equals( new IdName( 2, "bar" ) ) ); // id and name changed
+		
+		assertFalse( new IdName( 1, "foo" ).equals( null ) );
+		assertFalse( new IdName( 1, "foo" ).equals( 1 ) );
+		assertFalse( new IdName( 1, "foo" ).equals( true ) );
+		assertFalse( new IdName( 1, "foo" ) {}.equals( new IdName( 1, "foo" ) {} ) ); // different subclasses
+	}
+
+	/** */
+	@Test
+	public void hashCodeObject()
+	{
+		// you cannot really predict when hashCode will not be equal. the
+		// rule is that it must be equal when the objects compare equal.
+		assertEquals( new IdName( 1, "foo" ).hashCode(), new IdName( 1, "foo" ).hashCode() );
+		assertEquals( new IdName( 2, "foo" ).hashCode(), new IdName( 2, "foo" ).hashCode() );
+		assertEquals( new IdName( 1, "bar" ).hashCode(), new IdName( 1, "bar" ).hashCode() );
+		assertEquals( new IdName( 2, "bar" ).hashCode(), new IdName( 2, "bar" ).hashCode() );
+	}
+
+	/** */
+	@Test
+	public void hash()
+	{
+		assertEquals( 5381, Hash.hash( "" ) );
+		assertEquals( 352988316, Hash.hash( "a" ) );
+		assertEquals( 1511848646, Hash.hash( "ab" ) );
+		assertEquals( 669497117, Hash.hash( "abc" ) );
+		assertEquals( -1994190713, Hash.hash( "abcd" ) );
+		assertEquals( -802680418, Hash.hash( "abcde" ) );
+		assertEquals( 1266308680, Hash.hash( "abcdef" ) );
+		assertEquals( -379372513, Hash.hash( "abcdefg" ) );
+		assertEquals( -1416967159, Hash.hash( "abcdefgh" ) );
+		assertEquals( 53556896, Hash.hash( "abcdefghi" ) );
+		assertEquals( -4427318, Hash.hash( "abcdefghij" ) );
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestIdNameMap.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestIdNameMap.java
new file mode 100644
index 0000000..b6ee824
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestIdNameMap.java
@@ -0,0 +1,203 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/** */
+public class TestIdNameMap
+{
+	/** */
+	@Before
+	public void init()
+	{
+		map = new IdNameMap<IdName>()
+		{
+			@Override
+			public IdName makeNew( String name )
+			{
+				return new IdName( name );
+			}
+		};
+		
+		a = map.add( new IdName( 1, "a" ) );
+		b = map.add( new IdName( 2, "b" ) );
+	}
+	
+	private IdNameMap<IdName> map;
+	
+	private IdName a;
+	
+	private IdName b;
+
+	/** @throws Exception */
+	@Test
+	public void check_a() throws Exception
+	{
+		assertEquals( 2, map.size() );
+		check( "a", 1, a );
+		assertEquals( 2, map.size() );
+	}
+	
+	private void check( String name, int id, IdName idName )
+	{
+		IdName x = map.get( id );
+		assertNotNull( x );
+		assertSame( idName, x );
+		assertEquals( id, x.getId() );
+		assertEquals( name, x.getName() );
+		
+		x = map.get( name );
+		assertNotNull( x );
+		assertSame( idName, x );
+		assertEquals( id, x.getId() );
+		assertEquals( name, x.getName() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void check_b() throws Exception
+	{
+		assertEquals( 2, map.size() );
+		check( "b", 2, b );
+		assertEquals( 2, map.size() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void get_3() throws Exception
+	{
+		assertEquals( 2, map.size() );
+		IdName x = map.get( 3 );
+		assertNull( x );
+		assertEquals( 2, map.size() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void get_3_locked() throws Exception
+	{
+		assertEquals( 2, map.size() );
+		map.lock();
+		IdName x = map.get( 3 );
+		assertNull( x );
+		assertEquals( 2, map.size() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void get_c() throws Exception
+	{
+		assertEquals( 2, map.size() );
+		IdName c = map.get( "c" );
+		check( "c", 352988318, c );
+		assertEquals( 3, map.size() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void get_d_locked() throws Exception
+	{
+		assertEquals( 2, map.size() );
+		map.lock();
+		IdName d = map.get( "d" );
+		assertNull( d );
+		assertEquals( 2, map.size() );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void add_3_c_locked() throws Exception
+	{
+		assertEquals( 2, map.size() );
+		map.lock();
+		map.add( new IdName( 3, "c" ) );
+		assertEquals( 2, map.size() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected=IllegalArgumentException.class )
+	public void add_id_coll() throws Exception
+	{
+		assertEquals( 2, map.size() );
+		map.add( new IdName( 1, "c" ) );
+		assertEquals( 2, map.size() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected=IllegalArgumentException.class )
+	public void add_name_coll() throws Exception
+	{
+		assertEquals( 2, map.size() );
+		map.add( new IdName( 3, "a" ) );
+		assertEquals( 2, map.size() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected=IllegalArgumentException.class )
+	public void add_id_name_coll() throws Exception
+	{
+		assertEquals( 2, map.size() );
+		map.add( new IdName( 1, "a" ) );
+		assertEquals( 2, map.size() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void values1() throws Exception
+	{
+		Set<IdName> actual = map.values();
+		assertEquals( 2, actual.size() );
+		Set<IdName> expected = new HashSet<IdName>();
+		expected.add( new IdName( 1, "a" ) );
+		expected.add( new IdName( 2, "b" ) );
+		assertEquals( expected, actual );
+		
+		map.get( "c" );
+		
+		actual = map.values();
+		assertEquals( 3, actual.size() );
+		expected = new HashSet<IdName>();
+		expected.add( new IdName( 1, "a" ) );
+		expected.add( new IdName( 2, "b" ) );
+		expected.add( new IdName( "c" ) );
+		assertEquals( expected, actual );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void values2() throws Exception
+	{
+		// code in value factory depends upon the fact that the
+		// set returned from values is a copy.
+		assertNotSame( map.values(), map.values() );
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestMessage.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestMessage.java
new file mode 100644
index 0000000..78e1053
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestMessage.java
@@ -0,0 +1,171 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import org.apache.etch.bindings.java.support.DummyValueFactory;
+import org.apache.etch.bindings.java.support.Validator_int;
+import org.apache.etch.bindings.java.support.Validator_long;
+import org.junit.Test;
+
+
+/**
+ * Tests Message.
+ */
+public class TestMessage
+{
+	private final MyValueFactory vf = new MyValueFactory();
+	private final Type mt1 = new Type( 1, "mt" );
+	private final Type rmt = new Type( 2, "rmt" );
+	private final Field mf1 = new Field( 3, "x" );
+	private final Field mf2 = new Field( 4, "y" );
+	
+	{
+		mt1.putValidator( mf1, Validator_int.get( 0 ) );
+		mt1.putValidator( mf2, Validator_int.get( 0 ) );
+		mt1.putValidator( vf.mf_messageId, Validator_long.get( 0 ) );
+		
+		rmt.putValidator( vf.mf_messageId, Validator_long.get( 0 ) );
+		rmt.putValidator( vf.mf_inReplyTo, Validator_long.get( 0 ) );
+	}
+	
+	/** */
+	@Test
+	public void getVf()
+	{
+		Message msg = new Message( mt1, vf );
+		assertSame( vf, msg.vf() );
+	}
+
+	/** */
+	@Test
+	public void reply()
+	{
+		Message msg = new Message( mt1, vf );
+		msg.setMessageId( 12345L );
+
+		Message rmsg = msg.reply( rmt );
+		assertSame( rmt, rmsg.type() );
+		assertSame( vf, rmsg.vf() );
+		assertEquals( 12345L, rmsg.getInReplyTo() );
+	}
+
+	/** */
+	@Test
+	public void getMessageId()
+	{
+		Message msg = new Message( mt1, vf );
+		assertNull( msg.getMessageId() );
+		msg.setMessageId( 234L );
+		assertEquals( 234L, msg.getMessageId() );
+	}
+
+	/** */
+	@Test
+	public void setMessageId()
+	{
+		Message msg = new Message( mt1, vf );
+		assertNull( msg.getMessageId() );
+		msg.setMessageId( 234L );
+		assertEquals( 234L, msg.getMessageId() );
+		msg.setMessageId( 345L );
+		assertEquals( 345L, msg.getMessageId() );
+	}
+
+	/** */
+	@Test
+	public void getInReplyTo()
+	{
+		Message msg = new Message( rmt, vf );
+		assertNull( msg.getInReplyTo() );
+		msg.setInReplyTo( 234L );
+		assertEquals( 234L, msg.getInReplyTo() );
+	}
+
+	/** */
+	@Test
+	public void setInReplyTo()
+	{
+		Message msg = new Message( rmt, vf );
+		assertNull( msg.getInReplyTo() );
+		msg.setInReplyTo( 234L );
+		assertEquals( 234L, msg.getInReplyTo() );
+		msg.setInReplyTo( 345L );
+		assertEquals( 345L, msg.getInReplyTo() );
+	}
+
+	/** */
+	static class MyValueFactory extends DummyValueFactory
+	{
+		///////////////
+		// MESSAGEID //
+		///////////////
+		
+		@Override
+		public Long getMessageId( Message msg )
+		{
+			return (Long) msg.get( mf_messageId );
+		}
+
+		@Override
+		public void setMessageId( Message msg, Long msgid )
+		{
+			msg.put( mf_messageId, msgid );
+		}
+
+		@Override
+		public Field get_mf__messageId()
+		{
+			return mf_messageId;
+		}
+
+		/** */
+		public final Field mf_messageId = new Field( "_messageId" );
+
+		///////////////
+		// INREPLYTO //
+		///////////////
+		
+		@Override
+		public Long getInReplyTo( Message msg )
+		{
+			return (Long) msg.get( mf_inReplyTo );
+		}
+
+		@Override
+		public void setInReplyTo( Message msg, Long msgid )
+		{
+			msg.put( mf_inReplyTo, msgid );
+		}
+
+		@Override
+		public Field get_mf__inReplyTo()
+		{
+			return mf_inReplyTo;
+		}
+
+		/** */
+		public final Field mf_inReplyTo = new Field( "_inReplyTo" );
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestStructValue.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestStructValue.java
new file mode 100644
index 0000000..b09992b
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestStructValue.java
@@ -0,0 +1,363 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.etch.bindings.java.support.DummyValueFactory;
+import org.apache.etch.bindings.java.support.Validator_boolean;
+import org.apache.etch.bindings.java.support.Validator_int;
+import org.apache.etch.bindings.java.support.Validator_string;
+import org.junit.Test;
+
+
+/** Tests StructValue */
+public class TestStructValue
+{
+	private final ValueFactory vf = new DummyValueFactory();
+	
+	private Type mt1 = new Type( "one" );
+	private Type mt2 = new Type( "two" );
+	private Field mf1 = new Field( "f1" );
+	private Field mf2 = new Field( "f2" );
+	private Field mf3 = new Field( "f3" );
+	private Field mf4 = new Field( "f4" );
+	private Field mf5 = new Field( "f5" );
+	private Field mf6 = new Field( "f6" );
+
+	{
+		mt1.putValidator( mf1, Validator_boolean.get( 0 ) );
+		mt1.putValidator( mf2, Validator_boolean.get( 1 ) );
+		mt1.putValidator( mf3, Validator_int.get( 0 ) );
+		mt1.putValidator( mf4, Validator_int.get( 1 ) );
+		mt1.putValidator( mf5, Validator_string.get( 0 ) );
+		mt1.putValidator( mf6, Validator_string.get( 1 ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test2str() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		assertEquals( "one(785945377): {}", sv.toString() );
+
+		sv = new StructValue( mt2, vf );
+		assertEquals( "two(827843303): {}", sv.toString() );
+
+		sv = new StructValue( mt1, vf );
+		sv.put( mf1, true );
+		assertEquals( "one(785945377): {f1(1512176592)=true}", sv.toString() );
+
+		sv = new StructValue( mt1, vf );
+		sv.put( mf3, 23 );
+		assertEquals( "one(785945377): {f3(1512176594)=23}", sv.toString() );
+
+		sv = new StructValue( mt1, vf );
+		sv.put( mf1, false );
+		sv.put( mf3, 74 );
+		assertTrue("one(785945377): {f1(1512176592)=false, f3(1512176594)=74}".equals(sv.toString()) ||
+			"one(785945377): {f3(1512176594)=74, f1(1512176592)=false}".equals(sv.toString()));
+	}
+
+	/** */
+	@Test
+	public void getType()
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		assertSame( mt1, sv.type() );
+
+		sv = new StructValue( mt2, vf );
+		assertSame( mt2, sv.type() );
+	}
+
+	/** */
+	@Test
+	public void isType()
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		assertTrue( sv.isType( mt1 ) );
+		assertFalse( sv.isType( mt2 ) );
+
+		sv = new StructValue( mt2, vf );
+		assertTrue( sv.isType( mt2 ) );
+		assertFalse( sv.isType( mt1 ) );
+	}
+
+	/** */
+	@Test
+	public void checkType1()
+	{
+		new StructValue( mt1, vf ).checkType( mt1 );
+		new StructValue( mt2, vf ).checkType( mt2 );
+	}
+
+	/** */
+	@Test( expected = IllegalArgumentException.class )
+	public void checkType2()
+	{
+		new StructValue( mt1, vf ).checkType( mt2 );
+	}
+
+	/** */
+	@Test( expected = IllegalArgumentException.class )
+	public void checkType()
+	{
+		new StructValue( mt2, vf ).checkType( mt1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		assertTrue( sv.isEmpty() );
+		assertEquals( 0, sv.size() );
+		assertNull( sv.get( mf1 ) );
+
+		sv.put( mf1, true );
+		assertFalse( sv.isEmpty() );
+		assertEquals( 1, sv.size() );
+		assertEquals( true, sv.get( mf1 ) );
+
+		sv.put( mf1, false );
+		assertFalse( sv.isEmpty() );
+		assertEquals( 1, sv.size() );
+		assertEquals( false, sv.get( mf1 ) );
+
+		sv.put( mf1, null );
+		assertTrue( sv.isEmpty() );
+		assertEquals( 0, sv.size() );
+		assertNull( sv.get( mf1 ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void remove() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		assertTrue( sv.isEmpty() );
+		assertEquals( 0, sv.size() );
+		assertNull( sv.get( mf1 ) );
+
+		sv.remove( mf1 );
+		assertTrue( sv.isEmpty() );
+		assertEquals( 0, sv.size() );
+		assertNull( sv.get( mf1 ) );
+
+		sv.put( mf1, true );
+		assertFalse( sv.isEmpty() );
+		assertEquals( 1, sv.size() );
+		assertEquals( true, sv.get( mf1 ) );
+
+		sv.remove( mf1 );
+		assertTrue( sv.isEmpty() );
+		assertEquals( 0, sv.size() );
+		assertNull( sv.get( mf1 ) );
+
+		sv.remove( mf1 );
+		assertTrue( sv.isEmpty() );
+		assertEquals( 0, sv.size() );
+		assertNull( sv.get( mf1 ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void put1() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		sv.put( mf1, false );
+		sv.put( mf2, new boolean[] { true, false } );
+		sv.put( mf3, 1 );
+		sv.put( mf4, new int[] { 1, 2 } );
+		sv.put( mf5, "a" );
+		sv.put( mf6, new String[] { "a", "b" } );
+		assertEquals( 6, sv.size() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void put2() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		sv.put( mf1, null );
+		sv.put( mf2, null );
+		sv.put( mf3, null );
+		sv.put( mf4, null );
+		sv.put( mf5, null );
+		sv.put( mf6, null );
+		assertEquals( 0, sv.size() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void put3() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		sv.put( mf1, false );
+		sv.put( mf2, new boolean[] { true, false } );
+		sv.put( mf3, 1 );
+		sv.put( mf4, new int[] { 1, 2 } );
+		sv.put( mf5, "a" );
+		sv.put( mf6, new String[] { "a", "b" } );
+		assertEquals( 6, sv.size() );
+
+		// now "remove" them all
+
+		sv.put( mf1, null );
+		sv.put( mf2, null );
+		sv.put( mf3, null );
+		sv.put( mf4, null );
+		sv.put( mf5, null );
+		sv.put( mf6, null );
+		assertEquals( 0, sv.size() );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put5() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		sv.put( mf1, (byte) 1 ); // wrong type
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put6() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		sv.put( mf1, (short) 1 ); // wrong type
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put7() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		sv.put( mf1, 1 ); // wrong type
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put8() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		sv.put( mf1, (long) 1 ); // wrong type
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put9() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		sv.put( mf1, (float) 1.2 ); // wrong type
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put10() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		sv.put( mf1, 1.2 ); // wrong type
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put11() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		sv.put( mf1, "a" ); // wrong type
+	}
+
+	/** @throws Exception */
+	@Test
+	public void put12() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		sv.put( mf2, null );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void put13() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		sv.put( mf2, new boolean[] {} );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put14() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		sv.put( mf2, true );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put15() throws Exception
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		sv.put( mf2, new boolean[][] {} );
+	}
+
+	/** */
+	@Test
+	public void iterator()
+	{
+		StructValue sv = new StructValue( mt1, vf );
+		assertFalse( sv.iterator().hasNext() );
+
+		sv.put( mf1, true );
+
+		Iterator<Map.Entry<Field, Object>> i = sv.iterator();
+		assertTrue( i.hasNext() );
+		Map.Entry<Field, Object> me = i.next();
+		assertSame( mf1, me.getKey() );
+		assertEquals( true, me.getValue() );
+		assertFalse( i.hasNext() );
+
+		Map<Field, Object> vals = new HashMap<Field, Object>();
+		vals.put( mf1, true );
+		vals.put( mf3, 2 );
+		vals.put( mf5, "a" );
+
+		sv.put( mf3, 2 );
+		sv.put( mf5, "a" );
+
+		i = sv.iterator();
+		while (i.hasNext())
+		{
+			me = i.next();
+			Field key = me.getKey();
+			assertTrue( vals.containsKey( key ) );
+			assertEquals( vals.remove( key ), me.getValue() );
+		}
+		assertTrue( vals.isEmpty() );
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestType.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestType.java
new file mode 100644
index 0000000..d1b26e0
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestType.java
@@ -0,0 +1,104 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import org.apache.etch.bindings.java.support.Validator_int;
+import org.apache.etch.util.Hash;
+import org.junit.Test;
+
+
+/** */
+public class TestType
+{
+	/** */
+	@Test
+	public void typeIntegerString()
+	{
+		testMt( 1, "one" );
+		testMt( 2, "two" );
+		testMt( 3, "three" );
+	}
+
+	/** */
+	@Test
+	public void typeString()
+	{
+		testMt( "one" );
+		testMt( "two" );
+		testMt( "three" );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void testGetValidator() throws Exception
+	{
+		Type t = new Type( "t" );
+		Field f = new Field( "f" );
+		Field g = new Field( "g" );
+		Validator v = Validator_int.get( 0 );
+		
+		t.putValidator( f, v );
+		
+		assertSame( v, t.getValidator( f ) );
+		assertNull( t.getValidator( g ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void testPutValidatorNull() throws Exception
+	{
+		Type t = new Type( "t" );
+		Field f = new Field( "f" );
+		Validator v = Validator_int.get( 0 );
+
+		assertNull( t.getValidator( f ) );
+		
+		t.putValidator( f, null );
+		assertNull( t.getValidator( f ) );
+		
+		t.putValidator( f, v );
+		assertSame( v, t.getValidator( f ) );
+		
+		t.putValidator( f, v );
+		assertSame( ComboValidator.class, t.getValidator( f ).getClass() );
+		
+		t.clearValidator( f );
+		assertNull( t.getValidator( f ) );
+	}
+
+	private void testMt( int id, String name )
+	{
+		Type mt = new Type( id, name );
+		assertEquals( id, mt.getId() );
+		assertEquals( name, mt.getName() );
+	}
+
+	private void testMt( String name )
+	{
+		Type mt = new Type( name );
+		assertEquals( Hash.hash( name ), mt.getId() );
+		assertEquals( name, mt.getName() );
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestTypeMap.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestTypeMap.java
new file mode 100644
index 0000000..1ebd6ff
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/msg/TestTypeMap.java
@@ -0,0 +1,40 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.msg;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+/**
+ * Test of TypeMap.
+ */
+public class TestTypeMap
+{
+	/** @throws Exception */
+	@Test
+	public void makeNew() throws Exception
+	{
+		TypeMap tm = new TypeMap();
+		Type t = tm.makeNew( "mary" );
+		assertEquals( new Type( "mary" ), t );
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestAuthExceptionSerializer.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestAuthExceptionSerializer.java
new file mode 100644
index 0000000..4bed250
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestAuthExceptionSerializer.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of AuthExceptionSerializer
+ */
+public class TestAuthExceptionSerializer
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some unit tests for AuthExceptionSerializer.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestClass2TypeMap.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestClass2TypeMap.java
new file mode 100644
index 0000000..d98a82c
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestClass2TypeMap.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of Class2TypeMap
+ */
+public class TestClass2TypeMap
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some unit tests for TestClass2Type.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestDefaultServerFactory.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestDefaultServerFactory.java
new file mode 100644
index 0000000..0804ac5
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestDefaultServerFactory.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of DefaultServerFactory
+ */
+public class TestDefaultServerFactory
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some unit tests for DefaultServerFactory.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestDefaultValueFactory.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestDefaultValueFactory.java
new file mode 100644
index 0000000..58af578
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestDefaultValueFactory.java
@@ -0,0 +1,445 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.TypeMap;
+import org.junit.Test;
+
+
+/** Test DefaultValueFactory */
+public class TestDefaultValueFactory
+{
+	private MyValueFactory vf = new MyValueFactory( "tcp:" );
+	
+	/** @throws Exception */
+	@Test
+	public void testTypes() throws Exception
+	{
+		Set<Type> eTypes = mkTypeSet(
+			vf.getType( "_Etch_RuntimeException" ),
+			vf.getType( "_Etch_List" ),
+			vf.getType( "_Etch_Map" ),
+			vf.getType( "_Etch_Set" ),
+			vf.getType( "_Etch_Datetime" ),
+			vf.getType( "_Etch_AuthException" ),
+			vf.getType( "_exception" ),
+			MyValueFactory._mt_x,
+			MyValueFactory._mt_y
+		);
+		
+		assertEquals( eTypes, vf.getTypes() );
+		
+		for (Type t: eTypes)
+			testType( t );
+	}
+	
+	private Set<Type> mkTypeSet( Type ... types )
+	{
+		Set<Type> set = new HashSet<Type>();
+		for (Type t: types)
+			set.add( t );
+		return set;
+	}
+	
+	private void testType( Type type )
+	{
+		assertSame( type, vf.getType( type.getId() ) );
+		assertSame( type, vf.getType( type.getName() ) );
+	}
+	
+	private Set<Field> mkFieldSet( Field ... fields )
+	{
+		Set<Field> set = new HashSet<Field>();
+		for (Field f: fields )
+			set.add( f );
+		return set;
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void test_Etch_RuntimeException_fields() throws Exception
+	{
+		testTypeFields(
+			vf.getType( "_Etch_RuntimeException" ),
+			DefaultValueFactory._mf_msg
+		);
+		
+		testTypeField(
+			vf.getType( "_Etch_RuntimeException" ),
+			DefaultValueFactory._mf_msg,
+			"abc"
+		);
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void test_Etch_RuntimeException_msg_badValue() throws Exception
+	{
+		testTypeField(
+			vf.getType( "_Etch_RuntimeException" ),
+			DefaultValueFactory._mf_msg,
+			123
+		);
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void test_Etch_RuntimeException_badField() throws Exception
+	{
+		testTypeField(
+			vf.getType( "_Etch_RuntimeException" ),
+			MyValueFactory._mf_a,
+			"abc"
+		);
+	}
+	
+	private void testTypeField( Type type, Field field, Object value )
+	{
+		Message msg = new Message( type, vf );
+		msg.put( field, value );
+	}
+	
+	private void testTypeFields( Type type, Field ... fields )
+	{
+		Set<Field> aFields = type.getFields();
+		Set<Field> eFields = mkFieldSet( fields );
+		assertEquals( eFields, aFields );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void test_Etch_AuthException_fields() throws Exception
+	{
+		testTypeFields(
+			vf.getType( "_Etch_AuthException" ),
+			DefaultValueFactory._mf_msg
+		);
+		
+		testTypeField(
+			vf.getType( "_Etch_AuthException" ),
+			DefaultValueFactory._mf_msg,
+			"abc"
+		);
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void test_Etch_AuthException_msg_badValue() throws Exception
+	{
+		testTypeField(
+			vf.getType( "_Etch_AuthException" ),
+			DefaultValueFactory._mf_msg,
+			123
+		);
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void test_exception_fields() throws Exception
+	{
+		testTypeFields(
+			vf.getType( "_exception" ),
+			DefaultValueFactory._mf_result,
+			DefaultValueFactory._mf__messageId,
+			DefaultValueFactory._mf__inReplyTo
+		);
+		
+		testTypeField(
+			vf.getType( "_exception" ),
+			DefaultValueFactory._mf_result,
+			new RuntimeException()
+		);
+		
+		testTypeField(
+			vf.getType( "_exception" ),
+			DefaultValueFactory._mf__messageId,
+			123L
+		);
+		
+		testTypeField(
+			vf.getType( "_exception" ),
+			DefaultValueFactory._mf__inReplyTo,
+			123L
+		);
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void test_exception_result_badValue() throws Exception
+	{
+		testTypeField(
+			vf.getType( "_exception" ),
+			DefaultValueFactory._mf_result,
+			123
+		);
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void test_exception_messageId_badValue() throws Exception
+	{
+		testTypeField(
+			vf.getType( "_exception" ),
+			DefaultValueFactory._mf__messageId,
+			true
+		);
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void test_exception_inReplyTo_badValue() throws Exception
+	{
+		testTypeField(
+			vf.getType( "_exception" ),
+			DefaultValueFactory._mf__inReplyTo,
+			"abc"
+		);
+	}
+
+	/** @throws Exception */
+	@Test
+	public void getType_locked() throws Exception
+	{
+		assertNotNull( vf.getType( "x" ) );
+		assertNotNull( vf.getType( "y" ) );
+		assertNotNull( vf.getType( "a" ) );
+		vf.lockDynamicTypes();
+		assertNull( vf.getType( "b" ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void getField_locked() throws Exception
+	{
+		Type type = new Type( "blah" );
+		assertNotNull( type.getField( "a" ) );
+		assertNotNull( type.getField( "b" ) );
+		type.lock();
+		assertNotNull( type.getField( "a" ) );
+		assertNotNull( type.getField( "b" ) );
+		assertNull( type.getField( "x" ) );
+		assertNull( type.getField( "y" ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void getField_id_messageId() throws Exception
+	{
+		assertEquals( "_messageId", DefaultValueFactory._mf__messageId.getName() );
+		assertEquals( 1661383784, DefaultValueFactory._mf__messageId.getId() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void getField_id_inReplyTo() throws Exception
+	{
+		assertEquals( "_inReplyTo", DefaultValueFactory._mf__inReplyTo.getName() );
+		assertEquals( -307705434, DefaultValueFactory._mf__inReplyTo.getId() );
+	}
+
+	/////////////////////
+	// STRING ENCODING //
+	/////////////////////
+	
+	/** @throws Exception */
+	@Test
+	public void getStringEncoding() throws Exception
+	{
+		String enc = vf.getStringEncoding();
+		String s = new String( new byte[] { 'a', 'b', 'c' }, enc );
+		assertEquals( "abc", s );
+	}
+
+	////////////////
+	// MESSAGE ID //
+	////////////////
+	
+	/** @throws Exception */
+	@Test
+	public void messageId() throws Exception
+	{
+		Type mt_foo = new Type( "foo" );
+		mt_foo.putValidator( DefaultValueFactory._mf__messageId, Validator_long.get( 0 ) );
+		
+		Message msg = new Message( mt_foo, vf );
+		
+		assertNull( vf.getMessageId( msg ) );
+		
+		vf.setMessageId( msg, 234L );
+		
+		Long msgid = vf.getMessageId( msg );
+		assertNotNull( msgid );
+		assertEquals( 234L, msgid );
+		
+		vf.setMessageId( msg, null );
+		
+		assertNull( vf.getMessageId( msg ) );
+	}
+
+	/////////////////
+	// IN REPLY TO //
+	/////////////////
+	
+	/** @throws Exception */
+	@Test
+	public void inReplyTo() throws Exception
+	{
+		Type mt_foo = new Type( "foo" );
+		mt_foo.putValidator( DefaultValueFactory._mf__inReplyTo, Validator_long.get( 0 ) );
+		
+		Message msg = new Message( mt_foo, vf );
+		
+		assertNull( vf.getInReplyTo( msg ) );
+		
+		vf.setInReplyTo( msg, 234L );
+		
+		Long msgid = vf.getInReplyTo( msg );
+		assertNotNull( msgid );
+		assertEquals( 234L, msgid );
+		
+		vf.setInReplyTo( msg, null );
+		
+		assertNull( vf.getInReplyTo( msg ) );
+	}
+
+	//////////////////////
+	// VALUE CONVERSION //
+	//////////////////////
+	
+	/** @throws Exception */
+	@Test
+	public void exportCustomValue_RuntimeException() throws Exception
+	{
+		Exception value = new NullPointerException();
+		StructValue sv = vf.exportCustomValue( value );
+		sv.checkType( vf.getType( "_Etch_RuntimeException" ) );
+		assertEquals( 1, sv.size() );
+		assertEquals( "java.lang.NullPointerException",
+			sv.get( DefaultValueFactory._mf_msg ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void exportCustomValue_RuntimeException_msg() throws Exception
+	{
+		Exception value = new NullPointerException( "foo != null" );
+		StructValue sv = vf.exportCustomValue( value );
+		sv.checkType( vf.getType( "_Etch_RuntimeException" ) );
+		assertEquals( 1, sv.size() );
+		assertEquals( "java.lang.NullPointerException: foo != null",
+			sv.get( DefaultValueFactory._mf_msg ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void exportCustomValue_Object() throws Exception
+	{
+		Object value = new Object();
+		assertNull( vf.exportCustomValue( value ) );
+		// cannot export unsupported type
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void importCustomValue_Etch_RuntimeException() throws Exception
+	{
+		StructValue sv = new StructValue( vf.getType( "_Etch_RuntimeException" ), vf );
+		_Etch_RuntimeException e = (_Etch_RuntimeException) vf.importCustomValue( sv );
+		assertNotNull( e );
+		assertNull( e.msg );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void importCustomValue_Etch_RuntimeException_msg() throws Exception
+	{
+		StructValue sv = new StructValue( vf.getType( "_Etch_RuntimeException" ), vf );
+		sv.put( DefaultValueFactory._mf_msg, "foo" );
+		_Etch_RuntimeException e = (_Etch_RuntimeException) vf.importCustomValue( sv );
+		assertNotNull( e );
+		assertEquals( "foo", e.msg );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void importCustomValue_Unknown() throws Exception
+	{
+		StructValue sv = new StructValue( vf.getType( "x" ), vf );
+		assertNull( vf.importCustomValue( sv ) );
+		// cannot import unsupported type
+	}
+	
+	/**
+	 * A fake implementation of DefaultValueFactory for testing.
+	 */
+	public static class MyValueFactory extends DefaultValueFactory
+	{
+		private final static TypeMap types = new TypeMap();
+		
+		private final static Class2TypeMap class2type = new Class2TypeMap();
+
+		static
+		{
+			DefaultValueFactory.init( types, class2type );
+		}
+		
+		// define our types and fields here:
+		
+		/** type x */
+		public final static Type _mt_x = types.get( "x" );
+		
+		/** type y */
+		public final static Type _mt_y = types.get( "y" );
+		
+		/** field a */
+		public final static Field _mf_a = new Field( "a" );
+		
+		/** field b */
+		public final static Field _mf_b = new Field( "b" );
+		
+		static
+		{
+			types.lock();
+			class2type.lock();
+		}
+
+		/**
+		 * Constructs the ValueFactoryFake.
+		 * @param uri 
+		 */
+		public MyValueFactory( String uri )
+		{
+			super( uri, types, class2type );
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestDummyValueFactory.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestDummyValueFactory.java
new file mode 100644
index 0000000..c7102a6
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestDummyValueFactory.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of DummyValueFactory
+ */
+public class TestDummyValueFactory
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some tests for DummyValueFactory.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestFreePool.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestFreePool.java
new file mode 100644
index 0000000..3717037
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestFreePool.java
@@ -0,0 +1,323 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.etch.bindings.java.support.Pool.PoolRunnable;
+import org.junit.Test;
+
+
+/**
+ * Test of FreePool
+ */
+public class TestFreePool
+{
+	private final static int Q1 = 30; // 1 quanta of dependable clock tick
+	private final static int Q2 = 60; // 2 quanta of dependable clock tick
+	private final static int Q3 = 90; // 3 quanta of dependable clock tick
+	
+	/** @throws Exception */
+	@Test
+	public void close1() throws Exception
+	{
+		FreePool p = new FreePool( 2 );
+		p.close();
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void close2() throws Exception
+	{
+		// free pool thread count exceeded or pool closed
+		FreePool p = new FreePool( 2 );
+		p.close();
+		
+		MyPoolRunnable r = new MyPoolRunnable( 0, false );
+		p.run( r );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void close3() throws Exception
+	{
+		FreePool p = new FreePool( 2 );
+		p.close();
+		p.close();
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void join1() throws Exception
+	{
+		// free pool thread count exceeded or pool closed
+		FreePool p = new FreePool( 2 );
+		p.join();
+		
+		MyPoolRunnable r = new MyPoolRunnable( 0, false );
+		p.run( r );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void join2() throws Exception
+	{
+		FreePool p = new FreePool( 2 );
+		
+		MyPoolRunnable r = new MyPoolRunnable( 0, false );
+		assertFalse( r.done );
+		assertNull( r.ex );
+		
+		p.run( r );
+		
+		Thread.sleep( Q1 );
+		assertTrue( r.done );
+		assertNull( r.ex );
+		
+		p.join();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void join3() throws Exception
+	{
+		FreePool p = new FreePool( 2 );
+		
+		MyPoolRunnable r = new MyPoolRunnable( Q1, false );
+		assertFalse( r.done );
+		assertNull( r.ex );
+		
+		p.run( r );
+		assertFalse( r.done );
+		assertNull( r.ex );
+		
+		p.join();
+		assertTrue( r.done );
+		assertNull( r.ex );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void run1() throws Exception
+	{
+		FreePool p = new FreePool( 2 );
+		
+		MyPoolRunnable r = new MyPoolRunnable( 0, false );
+		assertFalse( r.done );
+		assertNull( r.ex );
+		
+		p.run( r );
+		
+		Thread.sleep( Q1 );
+		assertTrue( r.done );
+		assertNull( r.ex );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void run2() throws Exception
+	{
+		FreePool p = new FreePool( 2 );
+		for (int i = 0; i < 100; i++)
+		{
+			MyPoolRunnable r = new MyPoolRunnable( 0, false );
+			assertFalse( r.done );
+			assertNull( r.ex );
+			
+			p.run( r );
+			
+			Thread.sleep( Q1 );
+			assertTrue( r.done );
+			assertNull( r.ex );
+		}
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void run3() throws Exception
+	{
+		FreePool p = new FreePool( 2 );
+		
+		MyPoolRunnable r = new MyPoolRunnable( 0, true );
+		assertFalse( r.done );
+		assertNull( r.ex );
+		
+		p.run( r );
+		
+		Thread.sleep( Q1 );
+		assertFalse( r.done );
+		assertNotNull( r.ex );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void run4() throws Exception
+	{
+		FreePool p = new FreePool( 2 );
+		
+		MyPoolRunnable r = new MyPoolRunnable( Q2, false );
+		assertFalse( r.done );
+		assertNull( r.ex );
+		
+		p.run( r );
+		
+		Thread.sleep( Q1 );
+		assertFalse( r.done );
+		assertNull( r.ex );
+		
+		Thread.sleep( Q3 );
+		assertTrue( r.done );
+		assertNull( r.ex );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void run5() throws Exception
+	{
+		FreePool p = new FreePool( 2 );
+		
+		MyPoolRunnable r1 = new MyPoolRunnable( Q2, false );
+		assertFalse( r1.done );
+		assertNull( r1.ex );
+		
+		MyPoolRunnable r2 = new MyPoolRunnable( Q2, false );
+		assertFalse( r2.done );
+		assertNull( r2.ex );
+
+		p.run( r1 );
+		p.run( r2 );
+		
+		Thread.sleep( Q1 );
+		assertFalse( r1.done );
+		assertNull( r1.ex );
+		
+		assertFalse( r2.done );
+		assertNull( r2.ex );
+		
+		Thread.sleep( Q3 );
+		assertTrue( r1.done );
+		assertNull( r1.ex );
+		
+		assertTrue( r2.done );
+		assertNull( r2.ex );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void run6() throws Exception
+	{
+		// free pool thread count exceeded
+		FreePool p = new FreePool( 2 );
+		
+		MyPoolRunnable r1 = new MyPoolRunnable( Q2, false );
+		assertFalse( r1.done );
+		assertNull( r1.ex );
+		
+		MyPoolRunnable r2 = new MyPoolRunnable( Q2, false );
+		assertFalse( r2.done );
+		assertNull( r2.ex );
+		
+		MyPoolRunnable r3 = new MyPoolRunnable( Q2, false );
+		assertFalse( r3.done );
+		assertNull( r3.ex );
+
+		p.run( r1 );
+		p.run( r2 );
+		p.run( r3 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void run7() throws Exception
+	{
+		FreePool p = new FreePool( 2 );
+		
+		MyPoolRunnable r1 = new MyPoolRunnable( Q2, false );
+		assertFalse( r1.done );
+		assertNull( r1.ex );
+		
+		MyPoolRunnable r2 = new MyPoolRunnable( Q2, false );
+		assertFalse( r2.done );
+		assertNull( r2.ex );
+		
+		MyPoolRunnable r3 = new MyPoolRunnable( Q2, false );
+		assertFalse( r3.done );
+		assertNull( r3.ex );
+
+		p.run( r1 );
+		p.run( r2 );
+		try { p.run( r3 ); } catch ( IllegalStateException e ) {}
+		
+		Thread.sleep( Q1 );
+		assertFalse( r1.done );
+		assertNull( r1.ex );
+		
+		assertFalse( r2.done );
+		assertNull( r2.ex );
+		
+		assertFalse( r3.done );
+		assertNull( r3.ex );
+		
+		Thread.sleep( Q3 );
+		assertTrue( r1.done );
+		assertNull( r1.ex );
+		
+		assertTrue( r2.done );
+		assertNull( r2.ex );
+		
+		assertFalse( r3.done );
+		assertNull( r3.ex );
+	}
+	
+	private final class MyPoolRunnable implements PoolRunnable
+	{
+		public MyPoolRunnable( int delay, boolean excp )
+		{
+			this.delay = delay;
+			this.excp = excp;
+		}
+		
+		private final int delay;
+		
+		private final boolean excp;
+		
+		public boolean done;
+		
+		public Exception ex;
+
+		public void run() throws Exception
+		{
+			if (delay > 0)
+				Thread.sleep( delay );
+			if (excp)
+				throw new RuntimeException();
+			done = true;
+		}
+		
+		public void exception( Exception e )
+		{
+			ex = e;
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestNullPool.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestNullPool.java
new file mode 100644
index 0000000..042d00e
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestNullPool.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of NullPool
+ */
+public class TestNullPool
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some test for NullPool.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestQueuedPool.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestQueuedPool.java
new file mode 100644
index 0000000..e37d158
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestQueuedPool.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of QueuedPool
+ */
+public class TestQueuedPool
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some test for QueuedPool.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestRemoteBase.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestRemoteBase.java
new file mode 100644
index 0000000..1acdb67
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestRemoteBase.java
@@ -0,0 +1,484 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.TypeMap;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.transport.SessionMessage;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.Transport;
+import org.apache.etch.util.core.io.Transport.WaitDown;
+import org.apache.etch.util.core.io.Transport.WaitUp;
+import org.junit.Test;
+
+
+/**
+ * Test of RemoteBase.
+ */
+public class TestRemoteBase
+{
+	private final MyDeliveryService transport = new MyDeliveryService();
+	private final ValueFactory vf = new MyDefaultValueFactory( "tcp:" );
+	private final RemoteBase remote = new RemoteBase( transport, vf );
+	private final Type mt = new Type( "foo" );
+	private final Type rmt = new Type( "bar" );
+	private final Mailbox mb = new MyMailbox();
+	
+	/**
+	 * Constructs TestRemoteBase.
+	 */
+	public TestRemoteBase()
+	{
+//		assertSame( transport.getSession(), remote );
+		
+//		mt.putValidator( DefaultValueFactory._mf__messageId, Validator_long.get( 0 ) );
+//		mt.setResult( rmt );
+		
+//		rmt.setResponseField( DefaultValueFactory._mf_result );
+//		rmt.putValidator( DefaultValueFactory._mf_result, etch.bindings.java.support.Validator_int.get( 0 ) );
+//		rmt.putValidator( DefaultValueFactory._mf__messageId, Validator_long.get( 0 ) );
+//		rmt.putValidator( DefaultValueFactory._mf__inReplyTo, Validator_long.get( 0 ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void newMessage() throws Exception
+	{
+		Message msg = remote._newMessage( mt );
+		msg.checkType( mt );
+		assertSame( vf, msg.vf() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void send() throws Exception
+	{
+		Message msg = remote._newMessage( mt );
+		
+		remote._send( msg );
+		
+		assertSame( What.TRANSPORT_MESSAGE, transport.what );
+		assertNull( transport.recipient );
+		assertSame( msg, transport.msg );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void begincall() throws Exception
+	{
+		Message msg = remote._newMessage( mt );
+		
+		transport.mb = mb;
+		
+		Mailbox rmb = remote._begincall( msg );
+		
+		assertSame( What.BEGIN_CALL, transport.what );
+		assertSame( msg, transport.msg );
+		assertSame( mb, rmb );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void endcall() throws Exception
+	{
+		Object obj = new Object();
+		
+		transport.result = obj;
+		
+		Object robj = remote._endcall( mb, rmt );
+		
+		assertSame( What.END_CALL, transport.what );
+		assertSame( mb, transport.mb );
+		assertSame( rmt, transport.responseType );
+		assertSame( obj, robj );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportQuery() throws Exception
+	{
+		Object QUERY = "foo";
+		Object RESULT = "bar";
+		
+		assertNull( transport.what );
+		assertNull( transport.query );
+		transport.query_result = RESULT;
+		
+		Object result = remote._transportQuery( QUERY );
+
+		assertSame( What.TRANSPORT_QUERY, transport.what );
+		assertSame( QUERY, transport.query );
+		assertSame( RESULT, result );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportControl() throws Exception
+	{
+		Object CONTROL = "foo";
+		Object VALUE = "bar";
+		
+		assertNull( transport.what );
+		assertNull( transport.control );
+		assertNull( transport.value );
+		
+		remote._transportControl( CONTROL, VALUE );
+
+		assertSame( What.TRANSPORT_CONTROL, transport.what );
+		assertSame( CONTROL, transport.control );
+		assertSame( VALUE, transport.value );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportNotify() throws Exception
+	{
+		Object EVENT = "foo";
+		
+		assertNull( transport.what );
+		assertNull( transport.event );
+		
+		remote._transportNotify( EVENT );
+
+		assertSame( What.TRANSPORT_NOTIFY, transport.what );
+		assertSame( EVENT, transport.event );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void start() throws Exception
+	{
+		assertNull( transport.what );
+		assertNull( transport.query );
+		assertNull( transport.control );
+		assertNull( transport.value );
+		assertNull( transport.event );
+		
+		remote._start();
+		
+		assertSame( What.TRANSPORT_CONTROL, transport.what );
+		assertNull( transport.query );
+		assertSame( Transport.START, transport.control );
+		assertNull( transport.value );
+		assertNull( transport.event );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void waitUp() throws Exception
+	{
+		assertNull( transport.what );
+		assertNull( transport.query );
+		assertNull( transport.control );
+		assertNull( transport.value );
+		assertNull( transport.event );
+		
+		remote._waitUp( 1234 );
+		
+		assertSame( What.TRANSPORT_QUERY, transport.what );
+		assertNotNull( transport.query );
+		assertNull( transport.control );
+		assertNull( transport.value );
+		assertNull( transport.event );
+		
+		assertSame( WaitUp.class, transport.query.getClass() );
+		assertEquals( 1234, ((WaitUp) transport.query).maxDelay );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void startAndWaitUp() throws Exception
+	{
+		assertNull( transport.what );
+		assertNull( transport.query );
+		assertNull( transport.control );
+		assertNull( transport.value );
+		assertNull( transport.event );
+		
+		remote._startAndWaitUp( 2345 );
+		
+		assertSame( What.TRANSPORT_QUERY, transport.what );
+		assertNotNull( transport.query );
+		assertSame( Transport.START, transport.control );
+		assertNull( transport.value );
+		assertNull( transport.event );
+		
+		assertSame( WaitUp.class, transport.query.getClass() );
+		assertEquals( 2345, ((WaitUp) transport.query).maxDelay );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void stop() throws Exception
+	{
+		assertNull( transport.what );
+		assertNull( transport.query );
+		assertNull( transport.control );
+		assertNull( transport.value );
+		assertNull( transport.event );
+		
+		remote._stop();
+		
+		assertSame( What.TRANSPORT_CONTROL, transport.what );
+		assertNull( transport.query );
+		assertSame( Transport.STOP, transport.control );
+		assertNull( transport.value );
+		assertNull( transport.event );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void waitDown() throws Exception
+	{
+		assertNull( transport.what );
+		assertNull( transport.query );
+		assertNull( transport.control );
+		assertNull( transport.value );
+		assertNull( transport.event );
+		
+		remote._waitDown( 3456 );
+		
+		assertSame( What.TRANSPORT_QUERY, transport.what );
+		assertNotNull( transport.query );
+		assertNull( transport.control );
+		assertNull( transport.value );
+		assertNull( transport.event );
+		
+		assertSame( WaitDown.class, transport.query.getClass() );
+		assertEquals( 3456, ((WaitDown) transport.query).maxDelay );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void stopAndWaitDown() throws Exception
+	{
+		assertNull( transport.what );
+		assertNull( transport.query );
+		assertNull( transport.control );
+		assertNull( transport.value );
+		assertNull( transport.event );
+		
+		remote._stopAndWaitDown( 4567 );
+		
+		assertSame( What.TRANSPORT_QUERY, transport.what );
+		assertNotNull( transport.query );
+		assertSame( Transport.STOP, transport.control );
+		assertNull( transport.value );
+		assertNull( transport.event );
+		
+		assertSame( WaitDown.class, transport.query.getClass() );
+		assertEquals( 4567, ((WaitDown) transport.query).maxDelay );
+	}
+
+	/** */
+	public enum What
+	{
+		/** */ TRANSPORT_MESSAGE,
+		/** */ TRANSPORT_QUERY,
+		/** */ TRANSPORT_CONTROL,
+		/** */ TRANSPORT_NOTIFY,
+		/** */ BEGIN_CALL,
+		/** */ END_CALL
+	}
+	
+	/**
+	 * DeliveryService for testing.
+	 */
+	static class MyDeliveryService implements DeliveryService
+	{
+		/** */ public What what;
+		/** */ public Who recipient;
+		/** */ public Message msg;
+		/** */ public Object query;
+		/** */ public Object query_result;
+		/** */ public Object control;
+		/** */ public Object value;
+		/** */ public Object event;
+		/** */ public Mailbox mb;
+		/** */ public Type responseType;
+		/** */ public Object result;
+		
+		public Mailbox begincall( Message msg ) throws Exception
+		{
+			what = What.BEGIN_CALL;
+			this.msg = msg;
+			return mb;
+		}
+
+		public Object endcall( Mailbox mb, Type responseType ) throws Exception
+		{
+			what = What.END_CALL;
+			this.mb = mb;
+			this.responseType = responseType;
+			return result;
+		}
+
+		public boolean sessionMessage( Who sender, Message msg )
+			throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void sessionControl( Object control, Object value )
+			throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void sessionNotify( Object event ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Object sessionQuery( Object query ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+		
+		public void transportMessage( Who recipient, Message msg )
+			throws Exception
+		{
+			what = What.TRANSPORT_MESSAGE;
+			this.recipient = recipient;
+			this.msg = msg;
+		}
+
+		public Object transportQuery( Object query ) throws Exception
+		{
+			what = What.TRANSPORT_QUERY;
+			this.query = query;
+			return query_result;
+		}
+
+		public void transportControl( Object control, Object value )
+			throws Exception
+		{
+			what = What.TRANSPORT_CONTROL;
+			this.control = control;
+			this.value = value;
+		}
+
+		public void transportNotify( Object event ) throws Exception
+		{
+			what = What.TRANSPORT_NOTIFY;
+			this.event = event;
+		}
+
+		public SessionMessage getSession()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void setSession( SessionMessage session )
+		{
+			throw new UnsupportedOperationException();
+		}
+	}
+
+	/**
+	 * A fake implementation of DefaultValueFactory for testing.
+	 */
+	static class MyDefaultValueFactory extends DefaultValueFactory
+	{
+		private final static TypeMap types = new TypeMap();
+		
+		private final static Class2TypeMap class2type = new Class2TypeMap();
+
+		static
+		{
+			DefaultValueFactory.init( types, class2type );
+		}
+
+		/**
+		 * Constructs the ValueFactoryFake.
+		 * @param uri 
+		 */
+		public MyDefaultValueFactory( String uri )
+		{
+			super( uri, types, class2type );
+		}
+	}
+	
+	static class MyMailbox implements Mailbox
+	{
+		public boolean closeDelivery()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean closeRead() throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Long getMessageId()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean message( Who sender, Message msg ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Element read() throws InterruptedException
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Element read( int maxDelay ) throws InterruptedException
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void registerNotify( Notify notify, Object state, int maxDelay )
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void unregisterNotify( Notify notify )
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean isClosed()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean isEmpty()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean isFull()
+		{
+			throw new UnsupportedOperationException();
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestRuntimeExceptionSerializer.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestRuntimeExceptionSerializer.java
new file mode 100644
index 0000000..29a0a1b
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestRuntimeExceptionSerializer.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of RuntimeExceptionSerializer
+ */
+public class TestRuntimeExceptionSerializer
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some test for RuntimeExceptionSerializer.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestStubBase.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestStubBase.java
new file mode 100644
index 0000000..b6da131
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestStubBase.java
@@ -0,0 +1,378 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.etch.bindings.java.msg.AsyncMode;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.transport.SessionMessage;
+import org.apache.etch.util.core.Who;
+import org.junit.Before;
+import org.junit.Test;
+
+
+/** Test StubBase */
+public class TestStubBase
+{
+	private final ValueFactory vf = new DummyValueFactory();
+	private final MyDeliveryService transport = new MyDeliveryService();
+	private final MyObject session = new MyObject();
+	private final MyPool queued = new MyPool();
+	private final MyPool free = new MyPool();
+	private final MyStub stub = new MyStub( transport, session, queued, free );
+	private final Who who = new Who() { /* */ };
+	private final Type howdy = new Type( "howdy" );
+	private final Type nogood = new Type( "nogood" );
+	
+	/** */
+	@Before
+	public void setup()
+	{
+		howdy.setStubHelper(
+			new StubHelper<MyObject>()
+			{
+				@Override
+				public void run( DeliveryService svc, MyObject obj, Who sender,
+					Message msg ) throws Exception
+				{
+					obj.howdy( svc, sender, msg );
+				}
+			} );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construction() throws Exception
+	{
+		assertSame( stub, transport.getSession() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void sessionMessage1() throws Exception
+	{
+		howdy.setAsyncMode( AsyncMode.NONE );
+		
+		Message msg = new Message( howdy, vf );
+		boolean msg_handled = stub.sessionMessage( who, msg );
+		assertTrue( msg_handled );
+		
+		assertSame( What.HOWDY, session.what );
+		assertSame( transport, session.svc );
+		assertSame( who, session.sender );
+		assertSame( msg, session.msg );
+		assertFalse( queued.run );
+		assertFalse( free.run );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void sessionMessage2() throws Exception
+	{
+		howdy.setAsyncMode( AsyncMode.QUEUED );
+		
+		Message msg = new Message( howdy, vf );
+		boolean msg_handled = stub.sessionMessage( who, msg );
+		assertTrue( msg_handled );
+		
+		assertSame( What.HOWDY, session.what );
+		assertSame( transport, session.svc );
+		assertSame( who, session.sender );
+		assertSame( msg, session.msg );
+		assertTrue( queued.run );
+		assertFalse( free.run );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void sessionMessage3() throws Exception
+	{
+		howdy.setAsyncMode( AsyncMode.FREE );
+		
+		Message msg = new Message( howdy, vf );
+		boolean msg_handled = stub.sessionMessage( who, msg );
+		assertTrue( msg_handled );
+		
+		assertSame( What.HOWDY, session.what );
+		assertSame( transport, session.svc );
+		assertSame( who, session.sender );
+		assertSame( msg, session.msg );
+		assertFalse( queued.run );
+		assertTrue( free.run );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void sessionMessage4() throws Exception
+	{
+		howdy.setAsyncMode( AsyncMode.NONE );
+		
+		Message msg = new Message( nogood, vf );
+		boolean msg_handled = stub.sessionMessage( who, msg );
+		assertFalse( msg_handled );
+		
+		assertNull( session.what );
+		assertNull( session.svc );
+		assertNull( session.sender );
+		assertNull( session.msg );
+		assertFalse( queued.run );
+		assertFalse( free.run );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void sessionQuery() throws Exception
+	{
+		Object QUERY = "foo";
+		Object RESULT = "bar";
+		
+		assertNull( session.what );
+		assertNull( session.query );
+		session.query_result = RESULT;
+		
+		Object result = stub.sessionQuery( QUERY );
+
+		assertSame( What.SESSION_QUERY, session.what );
+		assertSame( QUERY, session.query );
+		assertSame( RESULT, result );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void sessionControl() throws Exception
+	{
+		Object CONTROL = "foo";
+		Object VALUE = "bar";
+		
+		assertNull( session.what );
+		assertNull( session.control );
+		assertNull( session.value );
+		
+		stub.sessionControl( CONTROL, VALUE );
+
+		assertSame( What.SESSION_CONTROL, session.what );
+		assertSame( CONTROL, session.control );
+		assertSame( VALUE, session.value );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void sessionNotify() throws Exception
+	{
+		Object EVENT = "foo";
+		
+		assertNull( session.what );
+		assertNull( session.event );
+		
+		stub.sessionNotify( EVENT );
+
+		assertSame( What.SESSION_NOTIFY, session.what );
+		assertSame( EVENT, session.event );
+	}
+	
+	/** */
+	enum What
+	{
+		/** */ TRANSPORT_MESSAGE,
+		/** */ TRANSPORT_QUERY,
+		/** */ TRANSPORT_CONTROL,
+		/** */ TRANSPORT_NOTIFY,
+		/** */ SESSION_QUERY,
+		/** */ SESSION_CONTROL,
+		/** */ SESSION_NOTIFY,
+		/** */ HOWDY
+	}
+	
+	/**
+	 * MyDeliveryService (fake for testing).
+	 */
+	@SuppressWarnings("hiding")
+	static class MyDeliveryService implements DeliveryService
+	{
+		/** */ public What what;
+		/** */ public Message msg;
+		/** */ public Who recipient;
+		/** */ public Object query;
+		/** */ public boolean query_result;
+		/** */ public Object control;
+		/** */ public Object value;
+		/** */ public Object event;
+		
+		public Mailbox begincall( Message msg ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Object endcall( Mailbox mb, Type responseType ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean sessionMessage( Who sender, Message msg )
+			throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void sessionControl( Object control, Object value )
+			throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void sessionNotify( Object event ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Object sessionQuery( Object query ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void transportMessage( Who recipient, Message msg )
+			throws Exception
+		{
+			what = What.TRANSPORT_MESSAGE;
+			this.recipient = recipient;
+			this.msg = msg;
+		}
+
+		public SessionMessage getSession()
+		{
+			return session;
+		}
+
+		public void setSession( SessionMessage session )
+		{
+			this.session = session;
+		}
+		
+		private SessionMessage session;
+
+		public Object transportQuery( Object query ) throws Exception
+		{
+			what = What.TRANSPORT_QUERY;
+			this.query = query;
+			return query_result;
+		}
+
+		public void transportControl( Object control, Object value )
+			throws Exception
+		{
+			what = What.TRANSPORT_CONTROL;
+			this.control = control;
+			this.value = value;
+		}
+
+		public void transportNotify( Object event ) throws Exception
+		{
+			what = What.TRANSPORT_NOTIFY;
+			this.event = event;
+		}
+	}
+	
+	/**
+	 * MyStub (fake for testing).
+	 */
+	static class MyStub extends StubBase<MyObject>
+	{
+		/**
+		 * @param svc
+		 * @param obj
+		 * @param queued
+		 * @param free
+		 */
+		public MyStub( DeliveryService svc, MyObject obj, Pool queued, Pool free )
+		{
+			super( svc, obj, queued, free );
+		}
+	}
+	
+	/**
+	 * MyObject (fake for testing).
+	 */
+	@SuppressWarnings("hiding")
+	static class MyObject implements ObjSession
+	{
+		/** */ public What what;
+		/** */ public Object query;
+		/** */ public Object query_result;
+		/** */ public Object control;
+		/** */ public Object value;
+		/** */ public Object event;
+		/** */ public DeliveryService svc;
+		/** */ public Who sender;
+		/** */ public Message msg;
+		
+		public Object _sessionQuery( Object query ) throws Exception
+		{
+			what = What.SESSION_QUERY;
+			this.query = query;
+			return query_result;
+		}
+		
+		/**
+		 * @param svc
+		 * @param sender
+		 * @param msg
+		 */
+		public void howdy( DeliveryService svc, Who sender, Message msg )
+		{
+			what = What.HOWDY;
+			this.svc = svc;
+			this.sender = sender;
+			this.msg = msg;
+		}
+
+		public void _sessionControl( Object control, Object value )
+			throws Exception
+		{
+			what = What.SESSION_CONTROL;
+			this.control = control;
+			this.value = value;
+		}
+
+		public void _sessionNotify( Object event ) throws Exception
+		{
+			what = What.SESSION_NOTIFY;
+			this.event = event;
+		}
+	}
+	
+	/** */
+	static class MyPool implements Pool
+	{
+		/** */ public boolean run;
+		
+		public void run( PoolRunnable runnable ) throws Exception
+		{
+			run = true;
+			runnable.run();
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestStubHelper.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestStubHelper.java
new file mode 100644
index 0000000..e37199e
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestStubHelper.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of StubHelper
+ */
+public class TestStubHelper
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some test for StubHelper.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestTransportFactory.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestTransportFactory.java
new file mode 100644
index 0000000..769a29d
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestTransportFactory.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of TransportFactory
+ */
+public class TestTransportFactory
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some test for TransportFactory.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestTransportHelper.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestTransportHelper.java
new file mode 100644
index 0000000..d25be50
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestTransportHelper.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of TransportHelper
+ */
+public class TestTransportHelper
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some test for TransportHelper.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestTypeValidator.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestTypeValidator.java
new file mode 100644
index 0000000..0ef5f60
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestTypeValidator.java
@@ -0,0 +1,121 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+import org.apache.etch.bindings.java.msg.Validator;
+import org.junit.Test;
+
+
+/** */
+public class TestTypeValidator
+{
+	/** */
+	@Test( expected = IllegalArgumentException.class )
+	public void testValidate()
+	{
+		new MyTypeValidator( int.class, int.class, -1, "bzzt" );
+	}
+
+	/** */
+	@Test
+	public void testTypeValidator1()
+	{
+		MyTypeValidator v = new MyTypeValidator( int.class, null, 0, "abc" );
+		assertSame( int.class, v.getExpectedClass() );
+		assertEquals( 0, v.getNDims() );
+		assertEquals( "abc", v.toString() );
+	}
+
+	/** */
+	@Test
+	public void testTypeValidator2()
+	{
+		MyTypeValidator v = new MyTypeValidator( boolean.class, null, 0, "def" );
+		assertSame( boolean.class, v.getExpectedClass() );
+		assertEquals( 0, v.getNDims() );
+		assertEquals( "def", v.toString() );
+	}
+
+	/** */
+	@Test
+	public void testTypeValidator3()
+	{
+		MyTypeValidator v = new MyTypeValidator( null, int.class, 1, "ghi" );
+		assertSame( int[].class, v.getExpectedClass() );
+		assertEquals( 1, v.getNDims() );
+		assertEquals( "ghi", v.toString() );
+	}
+
+	/** */
+	@Test
+	public void testTypeValidator4()
+	{
+		MyTypeValidator v = new MyTypeValidator( null, boolean.class, 1, "jkl" );
+		assertSame( boolean[].class, v.getExpectedClass() );
+		assertEquals( 1, v.getNDims() );
+		assertEquals( "jkl", v.toString() );
+	}
+
+	/** */
+	@Test
+	public void testToString()
+	{
+		MyTypeValidator v = new MyTypeValidator( int.class, int.class, 0, "abc" );
+		assertEquals( "abc", v.toString() );
+		
+		v = new MyTypeValidator( int.class, int.class, 0, "def" );
+		assertEquals( "def", v.toString() );
+		
+		v = new MyTypeValidator( int.class, int.class, 0, "ghi" );
+		assertEquals( "ghi", v.toString() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void testSilly() throws Exception
+	{
+		new MyTypeValidator( int.class, int.class, 0, "ghi" ).elementValidator();
+	}
+
+	/** */
+	public static class MyTypeValidator extends TypeValidator
+	{
+		/**
+		 * @param scalarClass
+		 * @param arrayClass
+		 * @param nDims
+		 * @param descr
+		 */
+		public MyTypeValidator( Class<?> scalarClass, Class<?> arrayClass,
+			int nDims, String descr )
+		{
+			super( scalarClass, arrayClass, nDims, descr );
+		}
+
+		public Validator elementValidator()
+		{
+			return null;
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_RuntimeException.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_RuntimeException.java
new file mode 100644
index 0000000..3c94e96
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_RuntimeException.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of Validator_RuntimeException
+ */
+public class TestValidator_RuntimeException
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some test for Validator_RuntimeException.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_StructValue.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_StructValue.java
new file mode 100644
index 0000000..e88f6a7
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_StructValue.java
@@ -0,0 +1,229 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.junit.Test;
+
+
+/**
+ * Test Validator_StructValue.
+ */
+public class TestValidator_StructValue
+{
+	private final ValueFactory vf = new DummyValueFactory();
+	private final Type abc = new Type( "abc" );
+	
+	/** @throws Exception */
+	@Test
+	public void constructor1() throws Exception
+	{
+		testconstructor( 0, "StructValue[abc(669497117), 0]", StructValue.class );
+		testconstructor( 1, "StructValue[abc(669497117), 1]", StructValue[].class );
+		testconstructor( 2, "StructValue[abc(669497117), 2]", StructValue[][].class );
+		testconstructor( 3, "StructValue[abc(669497117), 3]", StructValue[][][].class );
+		testconstructor( 4, "StructValue[abc(669497117), 4]", StructValue[][][][].class );
+		testconstructor( 5, "StructValue[abc(669497117), 5]", StructValue[][][][][].class );
+		testconstructor( 6, "StructValue[abc(669497117), 6]", StructValue[][][][][][].class );
+		testconstructor( 7, "StructValue[abc(669497117), 7]", StructValue[][][][][][][].class );
+		testconstructor( 8, "StructValue[abc(669497117), 8]", StructValue[][][][][][][][].class );
+		testconstructor( 9, "StructValue[abc(669497117), 9]", StructValue[][][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testconstructor( int n, String descr, Class<?> expectedClass )
+	{
+		Validator_StructValue v = Validator_StructValue.get( abc, n );
+		assertEquals( n, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+		assertEquals( abc, v.getType() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor2() throws Exception
+	{
+		Validator_StructValue.get( abc, -1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor3() throws Exception
+	{
+		Validator_StructValue.get( abc, Validator.MAX_NDIMS+1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void elementvalidator1() throws Exception
+	{
+		testelementvalidator( 1, "StructValue[abc(669497117), 0]", StructValue.class );
+		testelementvalidator( 2, "StructValue[abc(669497117), 1]", StructValue[].class );
+		testelementvalidator( 3, "StructValue[abc(669497117), 2]", StructValue[][].class );
+		testelementvalidator( 4, "StructValue[abc(669497117), 3]", StructValue[][][].class );
+		testelementvalidator( 5, "StructValue[abc(669497117), 4]", StructValue[][][][].class );
+		testelementvalidator( 6, "StructValue[abc(669497117), 5]", StructValue[][][][][].class );
+		testelementvalidator( 7, "StructValue[abc(669497117), 6]", StructValue[][][][][][].class );
+		testelementvalidator( 8, "StructValue[abc(669497117), 7]", StructValue[][][][][][][].class );
+		testelementvalidator( 9, "StructValue[abc(669497117), 8]", StructValue[][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testelementvalidator( int n, String descr, Class<?> expectedClass )
+	{
+		Validator_StructValue v = (Validator_StructValue) Validator_StructValue.get( abc, n ).elementValidator();
+		assertEquals( n-1, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+		assertEquals( abc, v.getType() );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void elementvalidator2() throws Exception
+	{
+		Validator_StructValue.get( abc, 0 ).elementValidator();
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_scalar() throws Exception
+	{
+		testgoodvalue( 0, new StructValue( abc, vf ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_array() throws Exception
+	{
+		testgoodvalue( 1, new StructValue[] {} );
+		testgoodvalue( 2, new StructValue[][] {} );
+		testgoodvalue( 3, new StructValue[][][] {} );
+		testgoodvalue( 4, new StructValue[][][][] {} );
+		testgoodvalue( 5, new StructValue[][][][][] {} );
+		testgoodvalue( 6, new StructValue[][][][][][] {} );
+		testgoodvalue( 7, new StructValue[][][][][][][] {} );
+		testgoodvalue( 8, new StructValue[][][][][][][][] {} );
+		testgoodvalue( 9, new StructValue[][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testgoodvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_StructValue.get( abc, n );
+		assertTrue( v.validate( value ) );
+		assertTrue( validateValueOk( v, value ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_scalar() throws Exception
+	{
+		testbadvalue( 0, null );
+		testbadvalue( 0, false );
+		testbadvalue( 0, true );
+		testbadvalue( 0, (byte) 1 );
+		testbadvalue( 0, (short) 2222 );
+		testbadvalue( 0, 33333333 );
+		testbadvalue( 0, 4444444444444444L );
+		testbadvalue( 0, 5.5f );
+		testbadvalue( 0, 6.6 );
+		testbadvalue( 0, "" );
+		testbadvalue( 0, "abc" );
+		testbadvalue( 0, new Object() );
+		testbadvalue( 0, new StructValue( new Type( "def" ), vf ) );
+		testbadvalue( 0, new Date() );
+
+		testbadvalue( 1, null );
+		testbadvalue( 1, false );
+		testbadvalue( 1, true );
+		testbadvalue( 1, (byte) 1 );
+		testbadvalue( 1, (short) 2222 );
+		testbadvalue( 1, 333333 );
+		testbadvalue( 1, 4444444444444444L );
+		testbadvalue( 1, 5.5f );
+		testbadvalue( 1, 6.6 );
+		testbadvalue( 1, "" );
+		testbadvalue( 1, "abc" );
+		testbadvalue( 1, new Object() );
+		testbadvalue( 1, new StructValue( abc, vf ) );
+		testbadvalue( 1, new Date() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_array() throws Exception
+	{
+		testbadvalue( 0, new StructValue[] {} );
+		testbadvalue( 1, new StructValue[][] {} );
+		testbadvalue( 2, new StructValue[][][] {} );
+		testbadvalue( 3, new StructValue[][][][] {} );
+		testbadvalue( 4, new StructValue[][][][][] {} );
+		testbadvalue( 5, new StructValue[][][][][][] {} );
+		testbadvalue( 6, new StructValue[][][][][][][] {} );
+		testbadvalue( 7, new StructValue[][][][][][][][] {} );
+		testbadvalue( 8, new StructValue[][][][][][][][][] {} );
+		testbadvalue( 9, new StructValue[][][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+
+		testbadvalue( 2, new StructValue[] {} );
+		testbadvalue( 3, new StructValue[][] {} );
+		testbadvalue( 4, new StructValue[][][] {} );
+		testbadvalue( 5, new StructValue[][][][] {} );
+		testbadvalue( 6, new StructValue[][][][][] {} );
+		testbadvalue( 7, new StructValue[][][][][][] {} );
+		testbadvalue( 8, new StructValue[][][][][][][] {} );
+		testbadvalue( 9, new StructValue[][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+
+	private void testbadvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_StructValue.get( abc, n );
+		assertFalse( v.validate( value ) );
+		assertFalse( validateValueOk( v, value ) );
+	}
+
+	private boolean validateValueOk( Validator v, Object value )
+	{
+		try
+		{
+			Object x = v.validateValue( value );
+			assertEquals( value, x );
+			return true;
+		}
+		catch ( Exception e )
+		{
+			return false;
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_boolean.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_boolean.java
new file mode 100644
index 0000000..7458b7f
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_boolean.java
@@ -0,0 +1,225 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.junit.Test;
+
+
+/**
+ * Test Validator_boolean.
+ */
+public class TestValidator_boolean
+{
+	private final ValueFactory vf = new DummyValueFactory();
+	
+	/** @throws Exception */
+	@Test
+	public void constructor1() throws Exception
+	{
+		testconstructor( 0, "boolean[0]", Boolean.class );
+		testconstructor( 1, "boolean[1]", boolean[].class );
+		testconstructor( 2, "boolean[2]", boolean[][].class );
+		testconstructor( 3, "boolean[3]", boolean[][][].class );
+		testconstructor( 4, "boolean[4]", boolean[][][][].class );
+		testconstructor( 5, "boolean[5]", boolean[][][][][].class );
+		testconstructor( 6, "boolean[6]", boolean[][][][][][].class );
+		testconstructor( 7, "boolean[7]", boolean[][][][][][][].class );
+		testconstructor( 8, "boolean[8]", boolean[][][][][][][][].class );
+		testconstructor( 9, "boolean[9]", boolean[][][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testconstructor( int n, String descr, Class<?> expectedClass )
+	{
+		Validator_boolean v = Validator_boolean.get( n );
+		assertEquals( n, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor2() throws Exception
+	{
+		Validator_boolean.get( -1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor3() throws Exception
+	{
+		Validator_boolean.get( Validator.MAX_NDIMS+1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void elementvalidator1() throws Exception
+	{
+		testelementvalidator( 1, "boolean[0]", Boolean.class );
+		testelementvalidator( 2, "boolean[1]", boolean[].class );
+		testelementvalidator( 3, "boolean[2]", boolean[][].class );
+		testelementvalidator( 4, "boolean[3]", boolean[][][].class );
+		testelementvalidator( 5, "boolean[4]", boolean[][][][].class );
+		testelementvalidator( 6, "boolean[5]", boolean[][][][][].class );
+		testelementvalidator( 7, "boolean[6]", boolean[][][][][][].class );
+		testelementvalidator( 8, "boolean[7]", boolean[][][][][][][].class );
+		testelementvalidator( 9, "boolean[8]", boolean[][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testelementvalidator( int n, String descr, Class<?> expectedClass )
+	{
+		Validator_boolean v = (Validator_boolean) Validator_boolean.get( n ).elementValidator();
+		assertEquals( n-1, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void elementvalidator2() throws Exception
+	{
+		Validator_boolean.get( 0 ).elementValidator();
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_scalar() throws Exception
+	{
+		testgoodvalue( 0, false );
+		testgoodvalue( 0, true );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_array() throws Exception
+	{
+		testgoodvalue( 1, new boolean[] {} );
+		testgoodvalue( 2, new boolean[][] {} );
+		testgoodvalue( 3, new boolean[][][] {} );
+		testgoodvalue( 4, new boolean[][][][] {} );
+		testgoodvalue( 5, new boolean[][][][][] {} );
+		testgoodvalue( 6, new boolean[][][][][][] {} );
+		testgoodvalue( 7, new boolean[][][][][][][] {} );
+		testgoodvalue( 8, new boolean[][][][][][][][] {} );
+		testgoodvalue( 9, new boolean[][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testgoodvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_boolean.get( n );
+		assertTrue( v.validate( value ) );
+		assertTrue( validateValueOk( v, value ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_scalar() throws Exception
+	{
+		testbadvalue( 0, null );
+		testbadvalue( 0, (byte) 1 );
+		testbadvalue( 0, (short) 2222 );
+		testbadvalue( 0, 33333333 );
+		testbadvalue( 0, 4444444444444444L );
+		testbadvalue( 0, 5.5f );
+		testbadvalue( 0, 6.6 );
+		testbadvalue( 0, "" );
+		testbadvalue( 0, "abc" );
+		testbadvalue( 0, new Object() );
+		testbadvalue( 0, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 0, new Date() );
+
+		testbadvalue( 1, null );
+		testbadvalue( 1, false );
+		testbadvalue( 1, true );
+		testbadvalue( 1, (byte) 1 );
+		testbadvalue( 1, (short) 2222 );
+		testbadvalue( 1, 33333333 );
+		testbadvalue( 1, 4444444444444444L );
+		testbadvalue( 1, 5.5f );
+		testbadvalue( 1, 6.6 );
+		testbadvalue( 1, "" );
+		testbadvalue( 1, "abc" );
+		testbadvalue( 1, new Object() );
+		testbadvalue( 1, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 1, new Date() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_array() throws Exception
+	{
+		testbadvalue( 0, new boolean[] {} );
+		testbadvalue( 1, new boolean[][] {} );
+		testbadvalue( 2, new boolean[][][] {} );
+		testbadvalue( 3, new boolean[][][][] {} );
+		testbadvalue( 4, new boolean[][][][][] {} );
+		testbadvalue( 5, new boolean[][][][][][] {} );
+		testbadvalue( 6, new boolean[][][][][][][] {} );
+		testbadvalue( 7, new boolean[][][][][][][][] {} );
+		testbadvalue( 8, new boolean[][][][][][][][][] {} );
+		testbadvalue( 9, new boolean[][][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+
+		testbadvalue( 2, new boolean[] {} );
+		testbadvalue( 3, new boolean[][] {} );
+		testbadvalue( 4, new boolean[][][] {} );
+		testbadvalue( 5, new boolean[][][][] {} );
+		testbadvalue( 6, new boolean[][][][][] {} );
+		testbadvalue( 7, new boolean[][][][][][] {} );
+		testbadvalue( 8, new boolean[][][][][][][] {} );
+		testbadvalue( 9, new boolean[][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+
+	private void testbadvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_boolean.get( n );
+		assertFalse( v.validate( value ) );
+		assertFalse( validateValueOk( v, value ) );
+	}
+
+	private boolean validateValueOk( Validator v, Object value )
+	{
+		try
+		{
+			Object x = v.validateValue( value );
+			assertEquals( value, x );
+			return true;
+		}
+		catch ( Exception e )
+		{
+			return false;
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_byte.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_byte.java
new file mode 100644
index 0000000..53714b1
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_byte.java
@@ -0,0 +1,272 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.junit.Test;
+
+
+/**
+ * Test Validator_byte.
+ */
+public class TestValidator_byte
+{
+	private final ValueFactory vf = new DummyValueFactory();
+	
+	/** @throws Exception */
+	@Test
+	public void constructor1() throws Exception
+	{
+		testconstructor( 0, "byte[0]", Byte.class );
+		testconstructor( 1, "byte[1]", byte[].class );
+		testconstructor( 2, "byte[2]", byte[][].class );
+		testconstructor( 3, "byte[3]", byte[][][].class );
+		testconstructor( 4, "byte[4]", byte[][][][].class );
+		testconstructor( 5, "byte[5]", byte[][][][][].class );
+		testconstructor( 6, "byte[6]", byte[][][][][][].class );
+		testconstructor( 7, "byte[7]", byte[][][][][][][].class );
+		testconstructor( 8, "byte[8]", byte[][][][][][][][].class );
+		testconstructor( 9, "byte[9]", byte[][][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testconstructor( int n, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = Validator_byte.get( n );
+		assertEquals( n, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor2() throws Exception
+	{
+		Validator_byte.get( -1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor3() throws Exception
+	{
+		Validator_byte.get( Validator.MAX_NDIMS+1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void elementvalidator1() throws Exception
+	{
+		testelementvalidator( 1, "byte[0]", Byte.class );
+		testelementvalidator( 2, "byte[1]", byte[].class );
+		testelementvalidator( 3, "byte[2]", byte[][].class );
+		testelementvalidator( 4, "byte[3]", byte[][][].class );
+		testelementvalidator( 5, "byte[4]", byte[][][][].class );
+		testelementvalidator( 6, "byte[5]", byte[][][][][].class );
+		testelementvalidator( 7, "byte[6]", byte[][][][][][].class );
+		testelementvalidator( 8, "byte[7]", byte[][][][][][][].class );
+		testelementvalidator( 9, "byte[8]", byte[][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testelementvalidator( int n, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = (TypeValidator) Validator_byte.get( n ).elementValidator();
+		assertEquals( n-1, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void elementvalidator2() throws Exception
+	{
+		Validator_byte.get( 0 ).elementValidator();
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_scalar() throws Exception
+	{
+		// BYTES
+		
+		testgoodvalue( 0, (byte) 0 );
+		
+		testgoodvalue( 0, (byte) 1 );
+		testgoodvalue( 0, (byte) 64 );
+		testgoodvalue( 0, Byte.MAX_VALUE );
+		
+		testgoodvalue( 0, (byte) -1 );
+		testgoodvalue( 0, (byte) -64 );
+		testgoodvalue( 0, Byte.MIN_VALUE );
+
+		// SHORTS
+		
+		testgoodvalue( 0, (short) 0 );
+		
+		testgoodvalue( 0, (short) 1 );
+		testgoodvalue( 0, (short) 64 );
+		testgoodvalue( 0, (short) Byte.MAX_VALUE );
+		
+		testgoodvalue( 0, (short) -1 );
+		testgoodvalue( 0, (short) -64 );
+		testgoodvalue( 0, (short) Byte.MIN_VALUE );
+
+		// INTS
+		
+		testgoodvalue( 0, 0 );
+		
+		testgoodvalue( 0, 1 );
+		testgoodvalue( 0, 64 );
+		testgoodvalue( 0, (int) Byte.MAX_VALUE );
+		
+		testgoodvalue( 0, -1 );
+		testgoodvalue( 0, -64 );
+		testgoodvalue( 0, (int) Byte.MIN_VALUE );
+
+		// LONGS
+		
+		testgoodvalue( 0, (long) 0 );
+		
+		testgoodvalue( 0, (long) 1 );
+		testgoodvalue( 0, (long) 64 );
+		testgoodvalue( 0, (long) Byte.MAX_VALUE );
+		
+		testgoodvalue( 0, (long) -1 );
+		testgoodvalue( 0, (long) -64 );
+		testgoodvalue( 0, (long) Byte.MIN_VALUE );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_array() throws Exception
+	{
+		testgoodvalue( 1, new byte[] {} );
+		testgoodvalue( 2, new byte[][] {} );
+		testgoodvalue( 3, new byte[][][] {} );
+		testgoodvalue( 4, new byte[][][][] {} );
+		testgoodvalue( 5, new byte[][][][][] {} );
+		testgoodvalue( 6, new byte[][][][][][] {} );
+		testgoodvalue( 7, new byte[][][][][][][] {} );
+		testgoodvalue( 8, new byte[][][][][][][][] {} );
+		testgoodvalue( 9, new byte[][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testgoodvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_byte.get( n );
+		assertTrue( v.validate( value ) );
+		assertTrue( validateValueOk( v, value ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_scalar() throws Exception
+	{
+		testbadvalue( 0, null );
+		testbadvalue( 0, false );
+		testbadvalue( 0, true );
+//		testbadvalue( 0, (byte) 1 ); good!
+		testbadvalue( 0, (short) 2222 );
+		testbadvalue( 0, 33333333 );
+		testbadvalue( 0, 4444444444444444L );
+		testbadvalue( 0, 5.5f );
+		testbadvalue( 0, 6.6 );
+		testbadvalue( 0, "" );
+		testbadvalue( 0, "abc" );
+		testbadvalue( 0, new Object() );
+		testbadvalue( 0, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 0, new Date() );
+
+		testbadvalue( 1, null );
+		testbadvalue( 1, false );
+		testbadvalue( 1, true );
+		testbadvalue( 1, (byte) 1 );
+		testbadvalue( 1, (short) 2222 );
+		testbadvalue( 1, 333333 );
+		testbadvalue( 1, 4444444444444444L );
+		testbadvalue( 1, 5.5f );
+		testbadvalue( 1, 6.6 );
+		testbadvalue( 1, "" );
+		testbadvalue( 1, "abc" );
+		testbadvalue( 1, new Object() );
+		testbadvalue( 1, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 1, new Date() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_array() throws Exception
+	{
+		testbadvalue( 0, new byte[] {} );
+		testbadvalue( 1, new byte[][] {} );
+		testbadvalue( 2, new byte[][][] {} );
+		testbadvalue( 3, new byte[][][][] {} );
+		testbadvalue( 4, new byte[][][][][] {} );
+		testbadvalue( 5, new byte[][][][][][] {} );
+		testbadvalue( 6, new byte[][][][][][][] {} );
+		testbadvalue( 7, new byte[][][][][][][][] {} );
+		testbadvalue( 8, new byte[][][][][][][][][] {} );
+		testbadvalue( 9, new byte[][][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+
+		testbadvalue( 2, new byte[] {} );
+		testbadvalue( 3, new byte[][] {} );
+		testbadvalue( 4, new byte[][][] {} );
+		testbadvalue( 5, new byte[][][][] {} );
+		testbadvalue( 6, new byte[][][][][] {} );
+		testbadvalue( 7, new byte[][][][][][] {} );
+		testbadvalue( 8, new byte[][][][][][][] {} );
+		testbadvalue( 9, new byte[][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+
+	private void testbadvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_byte.get( n );
+		assertFalse( v.validate( value ) );
+		assertFalse( validateValueOk( v, value ) );
+	}
+
+	private boolean validateValueOk( Validator v, Object value )
+	{
+		try
+		{
+			Object x = v.validateValue( value );
+			assertEquals( value, x );
+			return true;
+		}
+		catch ( Exception e )
+		{
+			return false;
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_custom.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_custom.java
new file mode 100644
index 0000000..e1bec1e
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_custom.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of Validator_custom
+ */
+public class TestValidator_custom
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some test for Validator_custom.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_double.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_double.java
new file mode 100644
index 0000000..c3faa57
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_double.java
@@ -0,0 +1,228 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.junit.Test;
+
+
+/**
+ * Test Validator_double.
+ */
+public class TestValidator_double
+{
+	private final ValueFactory vf = new DummyValueFactory();
+	
+	/** @throws Exception */
+	@Test
+	public void constructor1() throws Exception
+	{
+		testconstructor( 0, "double[0]", Double.class );
+		testconstructor( 1, "double[1]", double[].class );
+		testconstructor( 2, "double[2]", double[][].class );
+		testconstructor( 3, "double[3]", double[][][].class );
+		testconstructor( 4, "double[4]", double[][][][].class );
+		testconstructor( 5, "double[5]", double[][][][][].class );
+		testconstructor( 6, "double[6]", double[][][][][][].class );
+		testconstructor( 7, "double[7]", double[][][][][][][].class );
+		testconstructor( 8, "double[8]", double[][][][][][][][].class );
+		testconstructor( 9, "double[9]", double[][][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testconstructor( int n, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = Validator_double.get( n );
+		assertEquals( n, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor2() throws Exception
+	{
+		Validator_double.get( -1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor3() throws Exception
+	{
+		Validator_double.get( Validator.MAX_NDIMS+1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void elementvalidator1() throws Exception
+	{
+		testelementvalidator( 1, "double[0]", Double.class );
+		testelementvalidator( 2, "double[1]", double[].class );
+		testelementvalidator( 3, "double[2]", double[][].class );
+		testelementvalidator( 4, "double[3]", double[][][].class );
+		testelementvalidator( 5, "double[4]", double[][][][].class );
+		testelementvalidator( 6, "double[5]", double[][][][][].class );
+		testelementvalidator( 7, "double[6]", double[][][][][][].class );
+		testelementvalidator( 8, "double[7]", double[][][][][][][].class );
+		testelementvalidator( 9, "double[8]", double[][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testelementvalidator( int n, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = (TypeValidator) Validator_double.get( n ).elementValidator();
+		assertEquals( n-1, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void elementvalidator2() throws Exception
+	{
+		Validator_double.get( 0 ).elementValidator();
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_scalar() throws Exception
+	{
+		testgoodvalue( 0, 0.0 );
+		testgoodvalue( 0, 1.1 );
+		testgoodvalue( 0, -1.1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_array() throws Exception
+	{
+		testgoodvalue( 1, new double[] {} );
+		testgoodvalue( 2, new double[][] {} );
+		testgoodvalue( 3, new double[][][] {} );
+		testgoodvalue( 4, new double[][][][] {} );
+		testgoodvalue( 5, new double[][][][][] {} );
+		testgoodvalue( 6, new double[][][][][][] {} );
+		testgoodvalue( 7, new double[][][][][][][] {} );
+		testgoodvalue( 8, new double[][][][][][][][] {} );
+		testgoodvalue( 9, new double[][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testgoodvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_double.get( n );
+		assertTrue( v.validate( value ) );
+		assertTrue( validateValueOk( v, value ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_scalar() throws Exception
+	{
+		testbadvalue( 0, null );
+		testbadvalue( 0, false );
+		testbadvalue( 0, true );
+		testbadvalue( 0, (byte) 1 );
+		testbadvalue( 0, (short) 2222 );
+		testbadvalue( 0, 33333333 );
+		testbadvalue( 0, 4444444444444444L );
+		testbadvalue( 0, 5.5f );
+//		testbadvalue( 0, 6.6 ); good!
+		testbadvalue( 0, "" );
+		testbadvalue( 0, "abc" );
+		testbadvalue( 0, new Object() );
+		testbadvalue( 0, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 0, new Date() );
+
+		testbadvalue( 1, null );
+		testbadvalue( 1, false );
+		testbadvalue( 1, true );
+		testbadvalue( 1, (byte) 1 );
+		testbadvalue( 1, (short) 2222 );
+		testbadvalue( 1, 333333 );
+		testbadvalue( 1, 4444444444444444L );
+		testbadvalue( 1, 5.5f );
+		testbadvalue( 1, 6.6 );
+		testbadvalue( 1, "" );
+		testbadvalue( 1, "abc" );
+		testbadvalue( 1, new Object() );
+		testbadvalue( 1, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 1, new Date() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_array() throws Exception
+	{
+		testbadvalue( 0, new double[] {} );
+		testbadvalue( 1, new double[][] {} );
+		testbadvalue( 2, new double[][][] {} );
+		testbadvalue( 3, new double[][][][] {} );
+		testbadvalue( 4, new double[][][][][] {} );
+		testbadvalue( 5, new double[][][][][][] {} );
+		testbadvalue( 6, new double[][][][][][][] {} );
+		testbadvalue( 7, new double[][][][][][][][] {} );
+		testbadvalue( 8, new double[][][][][][][][][] {} );
+		testbadvalue( 9, new double[][][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+
+		testbadvalue( 2, new double[] {} );
+		testbadvalue( 3, new double[][] {} );
+		testbadvalue( 4, new double[][][] {} );
+		testbadvalue( 5, new double[][][][] {} );
+		testbadvalue( 6, new double[][][][][] {} );
+		testbadvalue( 7, new double[][][][][][] {} );
+		testbadvalue( 8, new double[][][][][][][] {} );
+		testbadvalue( 9, new double[][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+
+	private void testbadvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_double.get( n );
+		assertFalse( v.validate( value ) );
+		assertFalse( validateValueOk( v, value ) );
+	}
+
+	private boolean validateValueOk( Validator v, Object value )
+	{
+		try
+		{
+			Object x = v.validateValue( value );
+			assertEquals( value, x );
+			return true;
+		}
+		catch ( Exception e )
+		{
+			return false;
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_float.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_float.java
new file mode 100644
index 0000000..0c5f3a8
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_float.java
@@ -0,0 +1,228 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.junit.Test;
+
+
+/**
+ * Test Validator_float.
+ */
+public class TestValidator_float
+{
+	private final ValueFactory vf = new DummyValueFactory();
+	
+	/** @throws Exception */
+	@Test
+	public void constructor1() throws Exception
+	{
+		testconstructor( 0, "float[0]", Float.class );
+		testconstructor( 1, "float[1]", float[].class );
+		testconstructor( 2, "float[2]", float[][].class );
+		testconstructor( 3, "float[3]", float[][][].class );
+		testconstructor( 4, "float[4]", float[][][][].class );
+		testconstructor( 5, "float[5]", float[][][][][].class );
+		testconstructor( 6, "float[6]", float[][][][][][].class );
+		testconstructor( 7, "float[7]", float[][][][][][][].class );
+		testconstructor( 8, "float[8]", float[][][][][][][][].class );
+		testconstructor( 9, "float[9]", float[][][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testconstructor( int n, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = Validator_float.get( n );
+		assertEquals( n, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor2() throws Exception
+	{
+		Validator_float.get( -1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor3() throws Exception
+	{
+		Validator_float.get( Validator.MAX_NDIMS+1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void elementvalidator1() throws Exception
+	{
+		testelementvalidator( 1, "float[0]", Float.class );
+		testelementvalidator( 2, "float[1]", float[].class );
+		testelementvalidator( 3, "float[2]", float[][].class );
+		testelementvalidator( 4, "float[3]", float[][][].class );
+		testelementvalidator( 5, "float[4]", float[][][][].class );
+		testelementvalidator( 6, "float[5]", float[][][][][].class );
+		testelementvalidator( 7, "float[6]", float[][][][][][].class );
+		testelementvalidator( 8, "float[7]", float[][][][][][][].class );
+		testelementvalidator( 9, "float[8]", float[][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testelementvalidator( int n, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = (TypeValidator) Validator_float.get( n ).elementValidator();
+		assertEquals( n-1, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void elementvalidator2() throws Exception
+	{
+		Validator_float.get( 0 ).elementValidator();
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_scalar() throws Exception
+	{
+		testgoodvalue( 0, 0.0f );
+		testgoodvalue( 0, 1.1f );
+		testgoodvalue( 0, -1.1f );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_array() throws Exception
+	{
+		testgoodvalue( 1, new float[] {} );
+		testgoodvalue( 2, new float[][] {} );
+		testgoodvalue( 3, new float[][][] {} );
+		testgoodvalue( 4, new float[][][][] {} );
+		testgoodvalue( 5, new float[][][][][] {} );
+		testgoodvalue( 6, new float[][][][][][] {} );
+		testgoodvalue( 7, new float[][][][][][][] {} );
+		testgoodvalue( 8, new float[][][][][][][][] {} );
+		testgoodvalue( 9, new float[][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testgoodvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_float.get( n );
+		assertTrue( v.validate( value ) );
+		assertTrue( validateValueOk( v, value ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_scalar() throws Exception
+	{
+		testbadvalue( 0, null );
+		testbadvalue( 0, false );
+		testbadvalue( 0, true );
+		testbadvalue( 0, (byte) 1 );
+		testbadvalue( 0, (short) 2222 );
+		testbadvalue( 0, 33333333 );
+		testbadvalue( 0, 4444444444444444L );
+//		testbadvalue( 0, 5.5f ); good!
+		testbadvalue( 0, 6.6 );
+		testbadvalue( 0, "" );
+		testbadvalue( 0, "abc" );
+		testbadvalue( 0, new Object() );
+		testbadvalue( 0, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 0, new Date() );
+
+		testbadvalue( 1, null );
+		testbadvalue( 1, false );
+		testbadvalue( 1, true );
+		testbadvalue( 1, (byte) 1 );
+		testbadvalue( 1, (short) 2222 );
+		testbadvalue( 1, 333333 );
+		testbadvalue( 1, 4444444444444444L );
+		testbadvalue( 1, 5.5f );
+		testbadvalue( 1, 6.6 );
+		testbadvalue( 1, "" );
+		testbadvalue( 1, "abc" );
+		testbadvalue( 1, new Object() );
+		testbadvalue( 1, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 1, new Date() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_array() throws Exception
+	{
+		testbadvalue( 0, new float[] {} );
+		testbadvalue( 1, new float[][] {} );
+		testbadvalue( 2, new float[][][] {} );
+		testbadvalue( 3, new float[][][][] {} );
+		testbadvalue( 4, new float[][][][][] {} );
+		testbadvalue( 5, new float[][][][][][] {} );
+		testbadvalue( 6, new float[][][][][][][] {} );
+		testbadvalue( 7, new float[][][][][][][][] {} );
+		testbadvalue( 8, new float[][][][][][][][][] {} );
+		testbadvalue( 9, new float[][][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+
+		testbadvalue( 2, new float[] {} );
+		testbadvalue( 3, new float[][] {} );
+		testbadvalue( 4, new float[][][] {} );
+		testbadvalue( 5, new float[][][][] {} );
+		testbadvalue( 6, new float[][][][][] {} );
+		testbadvalue( 7, new float[][][][][][] {} );
+		testbadvalue( 8, new float[][][][][][][] {} );
+		testbadvalue( 9, new float[][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+
+	private void testbadvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_float.get( n );
+		assertFalse( v.validate( value ) );
+		assertFalse( validateValueOk( v, value ) );
+	}
+
+	private boolean validateValueOk( Validator v, Object value )
+	{
+		try
+		{
+			Object x = v.validateValue( value );
+			assertEquals( value, x );
+			return true;
+		}
+		catch ( Exception e )
+		{
+			return false;
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_int.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_int.java
new file mode 100644
index 0000000..a15b8aa
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_int.java
@@ -0,0 +1,292 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.junit.Test;
+
+
+/**
+ * Test Validator_int.
+ */
+public class TestValidator_int
+{
+	private final ValueFactory vf = new DummyValueFactory();
+	
+	/** @throws Exception */
+	@Test
+	public void constructor1() throws Exception
+	{
+		testconstructor( 0, "int[0]", Integer.class );
+		testconstructor( 1, "int[1]", int[].class );
+		testconstructor( 2, "int[2]", int[][].class );
+		testconstructor( 3, "int[3]", int[][][].class );
+		testconstructor( 4, "int[4]", int[][][][].class );
+		testconstructor( 5, "int[5]", int[][][][][].class );
+		testconstructor( 6, "int[6]", int[][][][][][].class );
+		testconstructor( 7, "int[7]", int[][][][][][][].class );
+		testconstructor( 8, "int[8]", int[][][][][][][][].class );
+		testconstructor( 9, "int[9]", int[][][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testconstructor( int n, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = Validator_int.get( n );
+		assertEquals( n, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor2() throws Exception
+	{
+		Validator_int.get( -1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor3() throws Exception
+	{
+		Validator_int.get( Validator.MAX_NDIMS+1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void elementvalidator1() throws Exception
+	{
+		testelementvalidator( 1, "int[0]", Integer.class );
+		testelementvalidator( 2, "int[1]", int[].class );
+		testelementvalidator( 3, "int[2]", int[][].class );
+		testelementvalidator( 4, "int[3]", int[][][].class );
+		testelementvalidator( 5, "int[4]", int[][][][].class );
+		testelementvalidator( 6, "int[5]", int[][][][][].class );
+		testelementvalidator( 7, "int[6]", int[][][][][][].class );
+		testelementvalidator( 8, "int[7]", int[][][][][][][].class );
+		testelementvalidator( 9, "int[8]", int[][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testelementvalidator( int n, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = (TypeValidator) Validator_int.get( n ).elementValidator();
+		assertEquals( n-1, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void elementvalidator2() throws Exception
+	{
+		Validator_int.get( 0 ).elementValidator();
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_scalar() throws Exception
+	{
+		// BYTES
+		
+		testgoodvalue( 0, (byte) 0 );
+		
+		testgoodvalue( 0, (byte) 1 );
+		testgoodvalue( 0, (byte) 64 );
+		testgoodvalue( 0, Byte.MAX_VALUE );
+		
+		testgoodvalue( 0, (byte) -1 );
+		testgoodvalue( 0, (byte) -64 );
+		testgoodvalue( 0, Byte.MIN_VALUE );
+
+		// SHORTS
+		
+		testgoodvalue( 0, (short) 0 );
+		
+		testgoodvalue( 0, (short) 1 );
+		testgoodvalue( 0, (short) 64 );
+		testgoodvalue( 0, (short) Byte.MAX_VALUE );
+		testgoodvalue( 0, (short) 2222 );
+		testgoodvalue( 0, Short.MAX_VALUE );
+		
+		testgoodvalue( 0, (short) -1 );
+		testgoodvalue( 0, (short) -64 );
+		testgoodvalue( 0, (short) Byte.MIN_VALUE );
+		testgoodvalue( 0, (short) -2222 );
+		testgoodvalue( 0, Short.MIN_VALUE );
+
+		// INTS
+		
+		testgoodvalue( 0, 0 );
+		
+		testgoodvalue( 0, 1 );
+		testgoodvalue( 0, 64 );
+		testgoodvalue( 0, (int) Byte.MAX_VALUE );
+		testgoodvalue( 0, 2222 );
+		testgoodvalue( 0, (int) Short.MAX_VALUE );
+		testgoodvalue( 0, 33333333 );
+		testgoodvalue( 0, Integer.MAX_VALUE );
+		
+		testgoodvalue( 0, -1 );
+		testgoodvalue( 0, -64 );
+		testgoodvalue( 0, (int) Byte.MIN_VALUE );
+		testgoodvalue( 0, -2222 );
+		testgoodvalue( 0, (int) Short.MIN_VALUE );
+		testgoodvalue( 0, -33333333 );
+		testgoodvalue( 0, Integer.MIN_VALUE );
+
+		// LONGS
+		
+		testgoodvalue( 0, (long) 0 );
+		
+		testgoodvalue( 0, (long) 1 );
+		testgoodvalue( 0, (long) 64 );
+		testgoodvalue( 0, (long) Byte.MAX_VALUE );
+		testgoodvalue( 0, (long) 2222 );
+		testgoodvalue( 0, (long) Short.MAX_VALUE );
+		testgoodvalue( 0, (long) 33333333 );
+		testgoodvalue( 0, (long) Integer.MAX_VALUE );
+		
+		testgoodvalue( 0, (long) -1 );
+		testgoodvalue( 0, (long) -64 );
+		testgoodvalue( 0, (long) Byte.MIN_VALUE );
+		testgoodvalue( 0, (long) -2222 );
+		testgoodvalue( 0, (long) Short.MIN_VALUE );
+		testgoodvalue( 0, (long) -33333333 );
+		testgoodvalue( 0, (long) Integer.MIN_VALUE );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_array() throws Exception
+	{
+		testgoodvalue( 1, new int[] {} );
+		testgoodvalue( 2, new int[][] {} );
+		testgoodvalue( 3, new int[][][] {} );
+		testgoodvalue( 4, new int[][][][] {} );
+		testgoodvalue( 5, new int[][][][][] {} );
+		testgoodvalue( 6, new int[][][][][][] {} );
+		testgoodvalue( 7, new int[][][][][][][] {} );
+		testgoodvalue( 8, new int[][][][][][][][] {} );
+		testgoodvalue( 9, new int[][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testgoodvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_int.get( n );
+		assertTrue( v.validate( value ) );
+		assertTrue( validateValueOk( v, value ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_scalar() throws Exception
+	{
+		testbadvalue( 0, null );
+		testbadvalue( 0, false );
+		testbadvalue( 0, true );
+//		testbadvalue( 0, (byte) 1 ); good!
+//		testbadvalue( 0, (short) 2222 ); good!
+//		testbadvalue( 0, 33333333 ); good!
+		testbadvalue( 0, 4444444444444444L );
+		testbadvalue( 0, 5.5f );
+		testbadvalue( 0, 6.6 );
+		testbadvalue( 0, "" );
+		testbadvalue( 0, "abc" );
+		testbadvalue( 0, new Object() );
+		testbadvalue( 0, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 0, new Date() );
+
+		testbadvalue( 1, null );
+		testbadvalue( 1, false );
+		testbadvalue( 1, true );
+		testbadvalue( 1, (byte) 1 );
+		testbadvalue( 1, (short) 2222 );
+		testbadvalue( 1, 333333 );
+		testbadvalue( 1, 4444444444444444L );
+		testbadvalue( 1, 5.5f );
+		testbadvalue( 1, 6.6 );
+		testbadvalue( 1, "" );
+		testbadvalue( 1, "abc" );
+		testbadvalue( 1, new Object() );
+		testbadvalue( 1, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 1, new Date() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_array() throws Exception
+	{
+		testbadvalue( 0, new int[] {} );
+		testbadvalue( 1, new int[][] {} );
+		testbadvalue( 2, new int[][][] {} );
+		testbadvalue( 3, new int[][][][] {} );
+		testbadvalue( 4, new int[][][][][] {} );
+		testbadvalue( 5, new int[][][][][][] {} );
+		testbadvalue( 6, new int[][][][][][][] {} );
+		testbadvalue( 7, new int[][][][][][][][] {} );
+		testbadvalue( 8, new int[][][][][][][][][] {} );
+		testbadvalue( 9, new int[][][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+
+		testbadvalue( 2, new int[] {} );
+		testbadvalue( 3, new int[][] {} );
+		testbadvalue( 4, new int[][][] {} );
+		testbadvalue( 5, new int[][][][] {} );
+		testbadvalue( 6, new int[][][][][] {} );
+		testbadvalue( 7, new int[][][][][][] {} );
+		testbadvalue( 8, new int[][][][][][][] {} );
+		testbadvalue( 9, new int[][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+
+	private void testbadvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_int.get( n );
+		assertFalse( v.validate( value ) );
+		assertFalse( validateValueOk( v, value ) );
+	}
+
+	private boolean validateValueOk( Validator v, Object value )
+	{
+		try
+		{
+			Object x = v.validateValue( value );
+			assertEquals( value, x );
+			return true;
+		}
+		catch ( Exception e )
+		{
+			return false;
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_long.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_long.java
new file mode 100644
index 0000000..02e4eef
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_long.java
@@ -0,0 +1,296 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.junit.Test;
+
+
+/**
+ * Test Validator_long.
+ */
+public class TestValidator_long
+{
+	private final ValueFactory vf = new DummyValueFactory();
+	
+	/** @throws Exception */
+	@Test
+	public void constructor1() throws Exception
+	{
+		testconstructor( 0, "long[0]", Long.class );
+		testconstructor( 1, "long[1]", long[].class );
+		testconstructor( 2, "long[2]", long[][].class );
+		testconstructor( 3, "long[3]", long[][][].class );
+		testconstructor( 4, "long[4]", long[][][][].class );
+		testconstructor( 5, "long[5]", long[][][][][].class );
+		testconstructor( 6, "long[6]", long[][][][][][].class );
+		testconstructor( 7, "long[7]", long[][][][][][][].class );
+		testconstructor( 8, "long[8]", long[][][][][][][][].class );
+		testconstructor( 9, "long[9]", long[][][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testconstructor( int n, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = Validator_long.get( n );
+		assertEquals( n, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor2() throws Exception
+	{
+		Validator_long.get( -1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor3() throws Exception
+	{
+		Validator_long.get( Validator.MAX_NDIMS+1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void elementvalidator1() throws Exception
+	{
+		testelementvalidator( 1, "long[0]", Long.class );
+		testelementvalidator( 2, "long[1]", long[].class );
+		testelementvalidator( 3, "long[2]", long[][].class );
+		testelementvalidator( 4, "long[3]", long[][][].class );
+		testelementvalidator( 5, "long[4]", long[][][][].class );
+		testelementvalidator( 6, "long[5]", long[][][][][].class );
+		testelementvalidator( 7, "long[6]", long[][][][][][].class );
+		testelementvalidator( 8, "long[7]", long[][][][][][][].class );
+		testelementvalidator( 9, "long[8]", long[][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testelementvalidator( int n, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = (TypeValidator) Validator_long.get( n ).elementValidator();
+		assertEquals( n-1, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void elementvalidator2() throws Exception
+	{
+		Validator_long.get( 0 ).elementValidator();
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_scalar() throws Exception
+	{
+		// BYTES
+		
+		testgoodvalue( 0, (byte) 0 );
+		
+		testgoodvalue( 0, (byte) 1 );
+		testgoodvalue( 0, (byte) 64 );
+		testgoodvalue( 0, Byte.MAX_VALUE );
+		
+		testgoodvalue( 0, (byte) -1 );
+		testgoodvalue( 0, (byte) -64 );
+		testgoodvalue( 0, Byte.MIN_VALUE );
+
+		// SHORTS
+		
+		testgoodvalue( 0, (short) 0 );
+		
+		testgoodvalue( 0, (short) 1 );
+		testgoodvalue( 0, (short) 64 );
+		testgoodvalue( 0, (short) Byte.MAX_VALUE );
+		testgoodvalue( 0, (short) 2222 );
+		testgoodvalue( 0, Short.MAX_VALUE );
+		
+		testgoodvalue( 0, (short) -1 );
+		testgoodvalue( 0, (short) -64 );
+		testgoodvalue( 0, (short) Byte.MIN_VALUE );
+		testgoodvalue( 0, (short) -2222 );
+		testgoodvalue( 0, Short.MIN_VALUE );
+
+		// INTS
+		
+		testgoodvalue( 0, 0 );
+		
+		testgoodvalue( 0, 1 );
+		testgoodvalue( 0, 64 );
+		testgoodvalue( 0, (int) Byte.MAX_VALUE );
+		testgoodvalue( 0, 2222 );
+		testgoodvalue( 0, (int) Short.MAX_VALUE );
+		testgoodvalue( 0, 33333333 );
+		testgoodvalue( 0, Integer.MAX_VALUE );
+		
+		testgoodvalue( 0, -1 );
+		testgoodvalue( 0, -64 );
+		testgoodvalue( 0, (int) Byte.MIN_VALUE );
+		testgoodvalue( 0, -2222 );
+		testgoodvalue( 0, (int) Short.MIN_VALUE );
+		testgoodvalue( 0, -33333333 );
+		testgoodvalue( 0, Integer.MIN_VALUE );
+
+		// LONGS
+		
+		testgoodvalue( 0, (long) 0 );
+		
+		testgoodvalue( 0, (long) 1 );
+		testgoodvalue( 0, (long) 64 );
+		testgoodvalue( 0, (long) Byte.MAX_VALUE );
+		testgoodvalue( 0, (long) 2222 );
+		testgoodvalue( 0, (long) Short.MAX_VALUE );
+		testgoodvalue( 0, (long) 33333333 );
+		testgoodvalue( 0, (long) Integer.MAX_VALUE );
+		testgoodvalue( 0, 4444444444444444L );
+		testgoodvalue( 0, Long.MAX_VALUE );
+		
+		testgoodvalue( 0, (long) -1 );
+		testgoodvalue( 0, (long) -64 );
+		testgoodvalue( 0, (long) Byte.MIN_VALUE );
+		testgoodvalue( 0, (long) -2222 );
+		testgoodvalue( 0, (long) Short.MIN_VALUE );
+		testgoodvalue( 0, (long) -33333333 );
+		testgoodvalue( 0, (long) Integer.MIN_VALUE );
+		testgoodvalue( 0, -4444444444444444L );
+		testgoodvalue( 0, Long.MIN_VALUE );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_array() throws Exception
+	{
+		testgoodvalue( 1, new long[] {} );
+		testgoodvalue( 2, new long[][] {} );
+		testgoodvalue( 3, new long[][][] {} );
+		testgoodvalue( 4, new long[][][][] {} );
+		testgoodvalue( 5, new long[][][][][] {} );
+		testgoodvalue( 6, new long[][][][][][] {} );
+		testgoodvalue( 7, new long[][][][][][][] {} );
+		testgoodvalue( 8, new long[][][][][][][][] {} );
+		testgoodvalue( 9, new long[][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testgoodvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_long.get( n );
+		assertTrue( v.validate( value ) );
+		assertTrue( validateValueOk( v, value ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_scalar() throws Exception
+	{
+		testbadvalue( 0, null );
+		testbadvalue( 0, false );
+		testbadvalue( 0, true );
+//		testbadvalue( 0, (byte) 1 ); good!
+//		testbadvalue( 0, (short) 2222 ); good!
+//		testbadvalue( 0, 33333333 ); good!
+//		testbadvalue( 0, 4444444444444444L ); good!
+		testbadvalue( 0, 5.5f );
+		testbadvalue( 0, 6.6 );
+		testbadvalue( 0, "" );
+		testbadvalue( 0, "abc" );
+		testbadvalue( 0, new Object() );
+		testbadvalue( 0, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 0, new Date() );
+
+		testbadvalue( 1, null );
+		testbadvalue( 1, false );
+		testbadvalue( 1, true );
+		testbadvalue( 1, (byte) 1 );
+		testbadvalue( 1, (short) 2222 );
+		testbadvalue( 1, 333333 );
+		testbadvalue( 1, 4444444444444444L );
+		testbadvalue( 1, 5.5f );
+		testbadvalue( 1, 6.6 );
+		testbadvalue( 1, "" );
+		testbadvalue( 1, "abc" );
+		testbadvalue( 1, new Object() );
+		testbadvalue( 1, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 1, new Date() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_array() throws Exception
+	{
+		testbadvalue( 0, new long[] {} );
+		testbadvalue( 1, new long[][] {} );
+		testbadvalue( 2, new long[][][] {} );
+		testbadvalue( 3, new long[][][][] {} );
+		testbadvalue( 4, new long[][][][][] {} );
+		testbadvalue( 5, new long[][][][][][] {} );
+		testbadvalue( 6, new long[][][][][][][] {} );
+		testbadvalue( 7, new long[][][][][][][][] {} );
+		testbadvalue( 8, new long[][][][][][][][][] {} );
+		testbadvalue( 9, new long[][][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+
+		testbadvalue( 2, new long[] {} );
+		testbadvalue( 3, new long[][] {} );
+		testbadvalue( 4, new long[][][] {} );
+		testbadvalue( 5, new long[][][][] {} );
+		testbadvalue( 6, new long[][][][][] {} );
+		testbadvalue( 7, new long[][][][][][] {} );
+		testbadvalue( 8, new long[][][][][][][] {} );
+		testbadvalue( 9, new long[][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+
+	private void testbadvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_long.get( n );
+		assertFalse( v.validate( value ) );
+		assertFalse( validateValueOk( v, value ) );
+	}
+
+	private boolean validateValueOk( Validator v, Object value )
+	{
+		try
+		{
+			Object x = v.validateValue( value );
+			assertEquals( value, x );
+			return true;
+		}
+		catch ( Exception e )
+		{
+			return false;
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_object.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_object.java
new file mode 100644
index 0000000..f2c0964
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_object.java
@@ -0,0 +1,340 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.junit.Test;
+
+
+/**
+ * Test Validator_object.
+ */
+public class TestValidator_object
+{
+	private final ValueFactory vf = new DummyValueFactory();
+	
+	/** @throws Exception */
+	@Test
+	public void constructor1() throws Exception
+	{
+		testconstructor( 0, "object[0]", Object.class );
+		testconstructor( 1, "object[1]", Object[].class );
+		testconstructor( 2, "object[2]", Object[][].class );
+		testconstructor( 3, "object[3]", Object[][][].class );
+		testconstructor( 4, "object[4]", Object[][][][].class );
+		testconstructor( 5, "object[5]", Object[][][][][].class );
+		testconstructor( 6, "object[6]", Object[][][][][][].class );
+		testconstructor( 7, "object[7]", Object[][][][][][][].class );
+		testconstructor( 8, "object[8]", Object[][][][][][][][].class );
+		testconstructor( 9, "object[9]", Object[][][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testconstructor( int n, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = Validator_object.get( n );
+		assertEquals( n, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor2() throws Exception
+	{
+		Validator_object.get( -1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor3() throws Exception
+	{
+		Validator_object.get( Validator.MAX_NDIMS+1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void elementvalidator1() throws Exception
+	{
+		testelementvalidator( 0, 0, "object[0]", Object.class );
+		testelementvalidator( 1, 0, "object[0]", Object.class );
+		testelementvalidator( 2, 1, "object[1]", Object[].class );
+		testelementvalidator( 3, 2, "object[2]", Object[][].class );
+		testelementvalidator( 4, 3, "object[3]", Object[][][].class );
+		testelementvalidator( 5, 4, "object[4]", Object[][][][].class );
+		testelementvalidator( 6, 5, "object[5]", Object[][][][][].class );
+		testelementvalidator( 7, 6, "object[6]", Object[][][][][][].class );
+		testelementvalidator( 8, 7, "object[7]", Object[][][][][][][].class );
+		testelementvalidator( 9, 8, "object[8]", Object[][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testelementvalidator( int n, int k, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = (TypeValidator) Validator_object.get( n ).elementValidator();
+		assertEquals( k, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_scalar() throws Exception
+	{
+		testgoodvalue( 0, false );
+		testgoodvalue( 0, true );
+		testgoodvalue( 0, (byte) 1 );
+		testgoodvalue( 0, (short) 2222 );
+		testgoodvalue( 0, 33333333 );
+		testgoodvalue( 0, 4444444444444444L );
+		testgoodvalue( 0, 5.5f );
+		testgoodvalue( 0, 6.6 );
+		testgoodvalue( 0, "" );
+		testgoodvalue( 0, "abc" );
+		testgoodvalue( 0, new Object() );
+		testgoodvalue( 0, new StructValue( new Type( "abc" ), vf ) );
+		testgoodvalue( 0, new Date() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_array() throws Exception
+	{
+		// primitive array types are compatible with object.
+		
+		testgoodvalue( 0, new boolean[] {} );
+		testgoodvalue( 0, new byte[] {} );
+		testgoodvalue( 0, new short[] {} );
+		testgoodvalue( 0, new int[] {} );
+		testgoodvalue( 0, new long[] {} );
+		testgoodvalue( 0, new float[] {} );
+		testgoodvalue( 0, new double[] {} );
+		
+		// ref array types are compatible with object.
+
+		testgoodvalue( 0, new Boolean[] {} );
+		testgoodvalue( 0, new Byte[] {} );
+		testgoodvalue( 0, new Short[] {} );
+		testgoodvalue( 0, new Integer[] {} );
+		testgoodvalue( 0, new Long[] {} );
+		testgoodvalue( 0, new Float[] {} );
+		testgoodvalue( 0, new Double[] {} );
+		testgoodvalue( 0, new String[] {} );
+		testgoodvalue( 0, new Object[] {} );
+		testgoodvalue( 0, new StructValue[] {} );
+		testgoodvalue( 0, new Date[] {} );
+		
+		// ref array types are compatible with object array (same size).
+		
+		testgoodvalue( 1, new Boolean[] {} );
+		testgoodvalue( 1, new Byte[] {} );
+		testgoodvalue( 1, new Short[] {} );
+		testgoodvalue( 1, new Integer[] {} );
+		testgoodvalue( 1, new Long[] {} );
+		testgoodvalue( 1, new Float[] {} );
+		testgoodvalue( 1, new Double[] {} );
+		testgoodvalue( 1, new String[] {} );
+		testgoodvalue( 1, new Object[] {} );
+		testgoodvalue( 1, new StructValue[] {} );
+		testgoodvalue( 1, new Date[] {} );
+		
+		// ref array types are compatible with object array (larger size).
+		
+		testgoodvalue( 1, new Boolean[][] {} );
+		testgoodvalue( 1, new Byte[][] {} );
+		testgoodvalue( 1, new Short[][] {} );
+		testgoodvalue( 1, new Integer[][] {} );
+		testgoodvalue( 1, new Long[][] {} );
+		testgoodvalue( 1, new Float[][] {} );
+		testgoodvalue( 1, new Double[][] {} );
+		testgoodvalue( 1, new String[][] {} );
+		testgoodvalue( 1, new Object[][] {} );
+		testgoodvalue( 1, new StructValue[][] {} );
+		testgoodvalue( 1, new Date[][] {} );
+	}
+	
+	private void testgoodvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_object.get( n );
+		assertTrue( v.validate( value ) );
+		assertTrue( validateValueOk( v, value ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void assignable1() throws Exception
+	{
+		Object x;
+		
+		x = new Object();
+		assertTrue( x( Object.class, Object.class ) );
+
+		x = new Object[] {};
+		assertTrue( x( Object.class, Object[].class ) );
+		
+		x = new Object[][] {};
+		assertTrue( x( Object.class, Object[][].class ) );
+
+		x = new Integer( 0 );
+		assertTrue( x( Object.class, Integer.class ) );
+		
+		x = new Integer[] {};
+		assertTrue( x( Object.class, Integer[].class ) );
+
+		x = new int[] {};
+		assertTrue( x( Object.class, int[].class ) );
+		
+		assertNotNull( x );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void assignable2() throws Exception
+	{
+		Object[] y;
+		
+//		y = new Object();
+		assertFalse( x( Object[].class, Object.class ) );
+
+		y = new Object[] {};
+		assertTrue( x( Object[].class, Object[].class ) );
+		
+		y = new Object[][] {};
+		assertTrue( x( Object[].class, Object[][].class ) );
+
+//		y = new Integer( 0 );
+		assertFalse( x( Object[].class, Integer.class ) );
+		
+		y = new Integer[] { 1, 2, 3 };
+		y[0] = 1;
+		assertTrue( x( Object[].class, Integer[].class ) );
+
+//		y = new int[] {};
+		assertFalse( x( Object[].class, int[].class ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = ArrayStoreException.class )
+	public void assignable3() throws Exception
+	{
+		Object[] x = new Integer[] { 1, 2, 3 };
+		x[0] = true; // wrong type!
+	}
+	
+	private boolean x( Class<?> a, Class<?> b )
+	{
+		return a.isAssignableFrom( b );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void bad_scalar() throws Exception
+	{
+		testbadvalue( 0, null );
+//		testbadvalue( 0, false );
+//		testbadvalue( 0, true );
+//		testbadvalue( 0, (byte) 1 );
+//		testbadvalue( 0, (short) 2222 );
+//		testbadvalue( 0, 33333333 );
+//		testbadvalue( 0, 4444444444444444L );
+//		testbadvalue( 0, 5.5f );
+//		testbadvalue( 0, 6.6 );
+//		testbadvalue( 0, "" );
+//		testbadvalue( 0, "abc" );
+//		testbadvalue( 0, new Object() );
+//		testbadvalue( 0, new StructValue( new Type( "abc" ) ) );
+//		testbadvalue( 0, new Date() );
+
+		testbadvalue( 1, null );
+		testbadvalue( 1, false );
+		testbadvalue( 1, true );
+		testbadvalue( 1, (byte) 1 );
+		testbadvalue( 1, (short) 2222 );
+		testbadvalue( 1, 333333 );
+		testbadvalue( 1, 4444444444444444L );
+		testbadvalue( 1, 5.5f );
+		testbadvalue( 1, 6.6 );
+		testbadvalue( 1, "" );
+		testbadvalue( 1, "abc" );
+		testbadvalue( 1, new Object() );
+		testbadvalue( 1, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 1, new Date() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_array() throws Exception
+	{
+		// primitive arrays cannot map into object arrays...
+		
+		testbadvalue( 1, new boolean[] {} );
+		testbadvalue( 1, new byte[] {} );
+		testbadvalue( 1, new short[] {} );
+		testbadvalue( 1, new int[] {} );
+		testbadvalue( 1, new long[] {} );
+		testbadvalue( 1, new float[] {} );
+		testbadvalue( 1, new double[] {} );
+
+		// too short...
+		
+		testbadvalue( 2, new Object[] {} );
+		testbadvalue( 3, new Object[][] {} );
+		testbadvalue( 4, new Object[][][] {} );
+		testbadvalue( 5, new Object[][][][] {} );
+		testbadvalue( 6, new Object[][][][][] {} );
+		testbadvalue( 7, new Object[][][][][][] {} );
+		testbadvalue( 8, new Object[][][][][][][] {} );
+		testbadvalue( 9, new Object[][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+
+	private void testbadvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_object.get( n );
+		assertFalse( v.validate( value ) );
+		assertFalse( validateValueOk( v, value ) );
+	}
+
+	private boolean validateValueOk( Validator v, Object value )
+	{
+		try
+		{
+			Object x = v.validateValue( value );
+			assertEquals( value, x );
+			return true;
+		}
+		catch ( Exception e )
+		{
+			return false;
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_short.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_short.java
new file mode 100644
index 0000000..88f6e87
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_short.java
@@ -0,0 +1,285 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.junit.Test;
+
+
+/**
+ * @author Manoj
+ *
+ */
+public class TestValidator_short
+{
+	private final ValueFactory vf = new DummyValueFactory();
+	
+	/** @throws Exception */
+	@Test
+	public void constructor1() throws Exception
+	{
+		testconstructor( 0, "short[0]", Short.class );
+		testconstructor( 1, "short[1]", short[].class );
+		testconstructor( 2, "short[2]", short[][].class );
+		testconstructor( 3, "short[3]", short[][][].class );
+		testconstructor( 4, "short[4]", short[][][][].class );
+		testconstructor( 5, "short[5]", short[][][][][].class );
+		testconstructor( 6, "short[6]", short[][][][][][].class );
+		testconstructor( 7, "short[7]", short[][][][][][][].class );
+		testconstructor( 8, "short[8]", short[][][][][][][][].class );
+		testconstructor( 9, "short[9]", short[][][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testconstructor( int n, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = Validator_short.get( n );
+		assertEquals( n, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor2() throws Exception
+	{
+		Validator_short.get( -1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor3() throws Exception
+	{
+		Validator_short.get( Validator.MAX_NDIMS+1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void elementvalidator1() throws Exception
+	{
+		testelementvalidator( 1, "short[0]", Short.class );
+		testelementvalidator( 2, "short[1]", short[].class );
+		testelementvalidator( 3, "short[2]", short[][].class );
+		testelementvalidator( 4, "short[3]", short[][][].class );
+		testelementvalidator( 5, "short[4]", short[][][][].class );
+		testelementvalidator( 6, "short[5]", short[][][][][].class );
+		testelementvalidator( 7, "short[6]", short[][][][][][].class );
+		testelementvalidator( 8, "short[7]", short[][][][][][][].class );
+		testelementvalidator( 9, "short[8]", short[][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testelementvalidator( int n, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = (TypeValidator) Validator_short.get( n ).elementValidator();
+		assertEquals( n-1, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void elementvalidator2() throws Exception
+	{
+		Validator_short.get( 0 ).elementValidator();
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_scalar() throws Exception
+	{
+		// BYTES
+		
+		testgoodvalue( 0, (byte) 0 );
+		
+		testgoodvalue( 0, (byte) 1 );
+		testgoodvalue( 0, (byte) 64 );
+		testgoodvalue( 0, Byte.MAX_VALUE );
+		
+		testgoodvalue( 0, (byte) -1 );
+		testgoodvalue( 0, (byte) -64 );
+		testgoodvalue( 0, Byte.MIN_VALUE );
+
+		// SHORTS
+		
+		testgoodvalue( 0, (short) 0 );
+		
+		testgoodvalue( 0, (short) 1 );
+		testgoodvalue( 0, (short) 64 );
+		testgoodvalue( 0, (short) Byte.MAX_VALUE );
+		testgoodvalue( 0, (short) 2222 );
+		testgoodvalue( 0, Short.MAX_VALUE );
+		
+		testgoodvalue( 0, (short) -1 );
+		testgoodvalue( 0, (short) -64 );
+		testgoodvalue( 0, (short) Byte.MIN_VALUE );
+		testgoodvalue( 0, (short) -2222 );
+		testgoodvalue( 0, Short.MIN_VALUE );
+
+		// INTS
+		
+		testgoodvalue( 0, 0 );
+		
+		testgoodvalue( 0, 1 );
+		testgoodvalue( 0, 64 );
+		testgoodvalue( 0, (int) Byte.MAX_VALUE );
+		testgoodvalue( 0, 2222 );
+		testgoodvalue( 0, (int) Short.MAX_VALUE );
+		
+		testgoodvalue( 0, -1 );
+		testgoodvalue( 0, -64 );
+		testgoodvalue( 0, (int) Byte.MIN_VALUE );
+		testgoodvalue( 0, -2222 );
+		testgoodvalue( 0, (int) Short.MIN_VALUE );
+
+		// LONGS
+		
+		testgoodvalue( 0, (long) 0 );
+		
+		testgoodvalue( 0, (long) 1 );
+		testgoodvalue( 0, (long) 64 );
+		testgoodvalue( 0, (long) Byte.MAX_VALUE );
+		testgoodvalue( 0, (long) 2222 );
+		testgoodvalue( 0, (long) Short.MAX_VALUE );
+		
+		testgoodvalue( 0, (long) -1 );
+		testgoodvalue( 0, (long) -64 );
+		testgoodvalue( 0, (long) Byte.MIN_VALUE );
+		testgoodvalue( 0, (long) -2222 );
+		testgoodvalue( 0, (long) Short.MIN_VALUE );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_array() throws Exception
+	{
+		testgoodvalue( 1, new short[] {} );
+		testgoodvalue( 2, new short[][] {} );
+		testgoodvalue( 3, new short[][][] {} );
+		testgoodvalue( 4, new short[][][][] {} );
+		testgoodvalue( 5, new short[][][][][] {} );
+		testgoodvalue( 6, new short[][][][][][] {} );
+		testgoodvalue( 7, new short[][][][][][][] {} );
+		testgoodvalue( 8, new short[][][][][][][][] {} );
+		testgoodvalue( 9, new short[][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testgoodvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_short.get( n );
+		assertTrue( v.validate( value ) );
+		assertTrue( validateValueOk( v, value ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_scalar() throws Exception
+	{
+		testbadvalue( 0, null );
+		testbadvalue( 0, false );
+		testbadvalue( 0, true );
+//		testbadvalue( 0, (byte) 1 ); good!
+//		testbadvalue( 0, (short) 2222 ); good!
+		testbadvalue( 0, 33333333 );
+		testbadvalue( 0, 4444444444444444L );
+		testbadvalue( 0, 5.5f );
+		testbadvalue( 0, 6.6 );
+		testbadvalue( 0, "" );
+		testbadvalue( 0, "abc" );
+		testbadvalue( 0, new Object() );
+		testbadvalue( 0, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 0, new Date() );
+
+		testbadvalue( 1, null );
+		testbadvalue( 1, false );
+		testbadvalue( 1, true );
+		testbadvalue( 1, (byte) 1 );
+		testbadvalue( 1, (short) 2222 );
+		testbadvalue( 1, 333333 );
+		testbadvalue( 1, 4444444444444444L );
+		testbadvalue( 1, 5.5f );
+		testbadvalue( 1, 6.6 );
+		testbadvalue( 1, "" );
+		testbadvalue( 1, "abc" );
+		testbadvalue( 1, new Object() );
+		testbadvalue( 1, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 1, new Date() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_array() throws Exception
+	{
+		testbadvalue( 0, new short[] {} );
+		testbadvalue( 1, new short[][] {} );
+		testbadvalue( 2, new short[][][] {} );
+		testbadvalue( 3, new short[][][][] {} );
+		testbadvalue( 4, new short[][][][][] {} );
+		testbadvalue( 5, new short[][][][][][] {} );
+		testbadvalue( 6, new short[][][][][][][] {} );
+		testbadvalue( 7, new short[][][][][][][][] {} );
+		testbadvalue( 8, new short[][][][][][][][][] {} );
+		testbadvalue( 9, new short[][][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+
+		testbadvalue( 2, new short[] {} );
+		testbadvalue( 3, new short[][] {} );
+		testbadvalue( 4, new short[][][] {} );
+		testbadvalue( 5, new short[][][][] {} );
+		testbadvalue( 6, new short[][][][][] {} );
+		testbadvalue( 7, new short[][][][][][] {} );
+		testbadvalue( 8, new short[][][][][][][] {} );
+		testbadvalue( 9, new short[][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+
+	private void testbadvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_short.get( n );
+		assertFalse( v.validate( value ) );
+		assertFalse( validateValueOk( v, value ) );
+	}
+
+	private boolean validateValueOk( Validator v, Object value )
+	{
+		try
+		{
+			Object x = v.validateValue( value );
+			assertEquals( value, x );
+			return true;
+		}
+		catch ( Exception e )
+		{
+			return false;
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_string.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_string.java
new file mode 100644
index 0000000..6c2b1b6
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_string.java
@@ -0,0 +1,227 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.junit.Test;
+
+
+/**
+ * Test Validator_string.
+ */
+public class TestValidator_string
+{
+	private final ValueFactory vf = new DummyValueFactory();
+	
+	/** @throws Exception */
+	@Test
+	public void constructor1() throws Exception
+	{
+		testconstructor( 0, "string[0]", String.class );
+		testconstructor( 1, "string[1]", String[].class );
+		testconstructor( 2, "string[2]", String[][].class );
+		testconstructor( 3, "string[3]", String[][][].class );
+		testconstructor( 4, "string[4]", String[][][][].class );
+		testconstructor( 5, "string[5]", String[][][][][].class );
+		testconstructor( 6, "string[6]", String[][][][][][].class );
+		testconstructor( 7, "string[7]", String[][][][][][][].class );
+		testconstructor( 8, "string[8]", String[][][][][][][][].class );
+		testconstructor( 9, "string[9]", String[][][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testconstructor( int n, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = Validator_string.get( n );
+		assertEquals( n, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor2() throws Exception
+	{
+		Validator_string.get( -1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor3() throws Exception
+	{
+		Validator_string.get( Validator.MAX_NDIMS+1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void elementvalidator1() throws Exception
+	{
+		testelementvalidator( 1, "string[0]", String.class );
+		testelementvalidator( 2, "string[1]", String[].class );
+		testelementvalidator( 3, "string[2]", String[][].class );
+		testelementvalidator( 4, "string[3]", String[][][].class );
+		testelementvalidator( 5, "string[4]", String[][][][].class );
+		testelementvalidator( 6, "string[5]", String[][][][][].class );
+		testelementvalidator( 7, "string[6]", String[][][][][][].class );
+		testelementvalidator( 8, "string[7]", String[][][][][][][].class );
+		testelementvalidator( 9, "string[8]", String[][][][][][][][].class );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testelementvalidator( int n, String descr, Class<?> expectedClass )
+	{
+		TypeValidator v = (TypeValidator) Validator_string.get( n ).elementValidator();
+		assertEquals( n-1, v.getNDims() );
+		assertSame( expectedClass, v.getExpectedClass() );
+		assertEquals( descr, v.toString() );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void elementvalidator2() throws Exception
+	{
+		Validator_string.get( 0 ).elementValidator();
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_scalar() throws Exception
+	{
+		testgoodvalue( 0, "" );
+		testgoodvalue( 0, "abc" );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void good_array() throws Exception
+	{
+		testgoodvalue( 1, new String[] {} );
+		testgoodvalue( 2, new String[][] {} );
+		testgoodvalue( 3, new String[][][] {} );
+		testgoodvalue( 4, new String[][][][] {} );
+		testgoodvalue( 5, new String[][][][][] {} );
+		testgoodvalue( 6, new String[][][][][][] {} );
+		testgoodvalue( 7, new String[][][][][][][] {} );
+		testgoodvalue( 8, new String[][][][][][][][] {} );
+		testgoodvalue( 9, new String[][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+	
+	private void testgoodvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_string.get( n );
+		assertTrue( v.validate( value ) );
+		assertTrue( validateValueOk( v, value ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_scalar() throws Exception
+	{
+		testbadvalue( 0, null );
+		testbadvalue( 0, false );
+		testbadvalue( 0, true );
+		testbadvalue( 0, (byte) 1 );
+		testbadvalue( 0, (short) 2222 );
+		testbadvalue( 0, 33333333 );
+		testbadvalue( 0, 4444444444444444L );
+		testbadvalue( 0, 5.5f );
+		testbadvalue( 0, 6.6 );
+//		testbadvalue( 0, "" ); // good!
+//		testbadvalue( 0, "abc" ); // good!
+		testbadvalue( 0, new Object() );
+		testbadvalue( 0, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 0, new Date() );
+
+		testbadvalue( 1, null );
+		testbadvalue( 1, false );
+		testbadvalue( 1, true );
+		testbadvalue( 1, (byte) 1 );
+		testbadvalue( 1, (short) 2222 );
+		testbadvalue( 1, 333333 );
+		testbadvalue( 1, 4444444444444444L );
+		testbadvalue( 1, 5.5f );
+		testbadvalue( 1, 6.6 );
+		testbadvalue( 1, "" );
+		testbadvalue( 1, "abc" );
+		testbadvalue( 1, new Object() );
+		testbadvalue( 1, new StructValue( new Type( "abc" ), vf ) );
+		testbadvalue( 1, new Date() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void bad_array() throws Exception
+	{
+		testbadvalue( 0, new String[] {} );
+		testbadvalue( 1, new String[][] {} );
+		testbadvalue( 2, new String[][][] {} );
+		testbadvalue( 3, new String[][][][] {} );
+		testbadvalue( 4, new String[][][][][] {} );
+		testbadvalue( 5, new String[][][][][][] {} );
+		testbadvalue( 6, new String[][][][][][][] {} );
+		testbadvalue( 7, new String[][][][][][][][] {} );
+		testbadvalue( 8, new String[][][][][][][][][] {} );
+		testbadvalue( 9, new String[][][][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+
+		testbadvalue( 2, new String[] {} );
+		testbadvalue( 3, new String[][] {} );
+		testbadvalue( 4, new String[][][] {} );
+		testbadvalue( 5, new String[][][][] {} );
+		testbadvalue( 6, new String[][][][][] {} );
+		testbadvalue( 7, new String[][][][][][] {} );
+		testbadvalue( 8, new String[][][][][][][] {} );
+		testbadvalue( 9, new String[][][][][][][][] {} );
+		assertEquals( 9, Validator.MAX_NDIMS );
+	}
+
+	private void testbadvalue( int n, Object value )
+	{
+		TypeValidator v = Validator_string.get( n );
+		assertFalse( v.validate( value ) );
+		assertFalse( validateValueOk( v, value ) );
+	}
+
+	private boolean validateValueOk( Validator v, Object value )
+	{
+		try
+		{
+			Object x = v.validateValue( value );
+			assertEquals( value, x );
+			return true;
+		}
+		catch ( Exception e )
+		{
+			return false;
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_void.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_void.java
new file mode 100644
index 0000000..e53a236
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidator_void.java
@@ -0,0 +1,76 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.etch.bindings.java.msg.Validator;
+import org.junit.Test;
+
+
+/**
+ * Test Validator_void.
+ */
+public class TestValidator_void
+{
+    /** */
+	@Test
+	public void test()
+	{
+		test( 0, "void[0]", null, 1 );
+		test( 0, "void[0]", null, (float) 2 );
+		test( 0, "void[0]", null, (double) 3 );
+		test( 0, "void[0]", null, (byte) 4 );
+		test( 0, "void[0]", null, (long) 5 );
+		test( 0, "void[0]", null, (short) 6 );
+		
+	}
+	
+	private void test( int n, String s, Object good, Object bad )
+	{
+		Validator_void v = Validator_void.get( n );
+		assertTrue( v.validate( good ) );
+		assertFalse( v.validate( bad ) );
+	}
+
+    /** */
+	@Test( expected = IllegalArgumentException.class )
+	public void testGetNeg1()
+	{
+		Validator_void.get( -1 );
+	}
+
+    /** */
+	@Test
+	public void testGetNeg2()
+	{
+		assertNull( Validator_void.get( 0 ).elementValidator() );
+	}
+
+    /** */
+	@Test( expected = IllegalArgumentException.class )
+	public void testGetMaxPlusOne()
+	{
+		Validator_void.get( Validator.MAX_NDIMS+1 );
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidators.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidators.java
new file mode 100644
index 0000000..2095fe6
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/TestValidators.java
@@ -0,0 +1,236 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import java.lang.reflect.Array;
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.Validator;
+import org.junit.Assert;
+import org.junit.Test;
+
+
+/** Tests various validators */
+public class TestValidators
+{
+	/** @throws Exception */
+	@Test
+	public void test_boolean() throws Exception
+	{
+		test( Validator_boolean.get( 2 ), 2,
+			new boolean[][] { { false, false }, { false, false } } );
+		
+		test( Validator_boolean.get( 2 ), 2,
+			new boolean[][] { { true, true }, { true, true } } );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test_byte() throws Exception
+	{
+		test( Validator_byte.get( 2 ), 2,
+			new byte[][] { { 0, 0 }, { 0, 0 } } );
+
+		test( Validator_byte.get( 2 ), 2,
+			new byte[][] { { 1, 1 }, { 1, 1 } } );
+
+		test( Validator_byte.get( 2 ), 2,
+			new byte[][] { { -1, -1 }, { -1, -1 } } );
+		
+		test( Validator_byte.get( 2 ), 2,
+			new byte[][] { { Byte.MAX_VALUE, Byte.MAX_VALUE }, { Byte.MAX_VALUE, Byte.MAX_VALUE } } );
+		
+		test( Validator_byte.get( 2 ), 2,
+			new byte[][] { { Byte.MIN_VALUE, Byte.MIN_VALUE }, { Byte.MIN_VALUE, Byte.MIN_VALUE } } );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test_short() throws Exception
+	{
+		test( Validator_short.get( 2 ), 2,
+			new short[][] { { 0, 0 }, { 0, 0 } } );
+		
+		test( Validator_short.get( 2 ), 2,
+			new short[][] { { 1, 1 }, { 1, 1 } } );
+		
+		test( Validator_short.get( 2 ), 2,
+			new short[][] { { -1, -1 }, { -1, -1 } } );
+		
+		test( Validator_short.get( 2 ), 2,
+			new short[][] { { Byte.MAX_VALUE, Byte.MAX_VALUE }, { Byte.MAX_VALUE, Byte.MAX_VALUE } } );
+		
+		test( Validator_short.get( 2 ), 2,
+			new short[][] { { Byte.MIN_VALUE, Byte.MIN_VALUE }, { Byte.MIN_VALUE, Byte.MIN_VALUE } } );
+		
+		test( Validator_short.get( 2 ), 2,
+			new short[][] { { Short.MAX_VALUE, Short.MAX_VALUE }, { Short.MAX_VALUE, Short.MAX_VALUE } } );
+		
+		test( Validator_short.get( 2 ), 2,
+			new short[][] { { Short.MIN_VALUE, Short.MIN_VALUE }, { Short.MIN_VALUE, Short.MIN_VALUE } } );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test_int() throws Exception
+	{
+		test( Validator_int.get( 2 ), 2,
+			new int[][] { { 0, 0 }, { 0, 0 } } );
+		
+		test( Validator_int.get( 2 ), 2,
+			new int[][] { { 1, 1 }, { 1, 1 } } );
+		
+		test( Validator_int.get( 2 ), 2,
+			new int[][] { { -1, -1 }, { -1, -1 } } );
+		
+		test( Validator_int.get( 2 ), 2,
+			new int[][] { { Byte.MAX_VALUE, Byte.MAX_VALUE }, { Byte.MAX_VALUE, Byte.MAX_VALUE } } );
+		
+		test( Validator_int.get( 2 ), 2,
+			new int[][] { { Byte.MIN_VALUE, Byte.MIN_VALUE }, { Byte.MIN_VALUE, Byte.MIN_VALUE } } );
+		
+		test( Validator_int.get( 2 ), 2,
+			new int[][] { { Short.MAX_VALUE, Short.MAX_VALUE }, { Short.MAX_VALUE, Short.MAX_VALUE } } );
+		
+		test( Validator_int.get( 2 ), 2,
+			new int[][] { { Short.MIN_VALUE, Short.MIN_VALUE }, { Short.MIN_VALUE, Short.MIN_VALUE } } );
+		
+		test( Validator_int.get( 2 ), 2,
+			new int[][] { { Integer.MAX_VALUE, Integer.MAX_VALUE }, { Integer.MAX_VALUE, Integer.MAX_VALUE } } );
+		
+		test( Validator_int.get( 2 ), 2,
+			new int[][] { { Integer.MIN_VALUE, Integer.MIN_VALUE }, { Integer.MIN_VALUE, Integer.MIN_VALUE } } );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test_long() throws Exception
+	{
+		test( Validator_long.get( 2 ), 2,
+			new long[][] { { 0, 0 }, { 0, 0 } } );
+		
+		test( Validator_long.get( 2 ), 2,
+			new long[][] { { 1, 1 }, { 1, 1 } } );
+		
+		test( Validator_long.get( 2 ), 2,
+			new long[][] { { -1, -1 }, { -1, -1 } } );
+		
+		test( Validator_long.get( 2 ), 2,
+			new long[][] { { Byte.MAX_VALUE, Byte.MAX_VALUE }, { Byte.MAX_VALUE, Byte.MAX_VALUE } } );
+		
+		test( Validator_long.get( 2 ), 2,
+			new long[][] { { Byte.MIN_VALUE, Byte.MIN_VALUE }, { Byte.MIN_VALUE, Byte.MIN_VALUE } } );
+		
+		test( Validator_long.get( 2 ), 2,
+			new long[][] { { Short.MAX_VALUE, Short.MAX_VALUE }, { Short.MAX_VALUE, Short.MAX_VALUE } } );
+		
+		test( Validator_long.get( 2 ), 2,
+			new long[][] { { Short.MIN_VALUE, Short.MIN_VALUE }, { Short.MIN_VALUE, Short.MIN_VALUE } } );
+		
+		test( Validator_long.get( 2 ), 2,
+			new long[][] { { Integer.MAX_VALUE, Integer.MAX_VALUE }, { Integer.MAX_VALUE, Integer.MAX_VALUE } } );
+		
+		test( Validator_long.get( 2 ), 2,
+			new long[][] { { Integer.MIN_VALUE, Integer.MIN_VALUE }, { Integer.MIN_VALUE, Integer.MIN_VALUE } } );
+		
+		test( Validator_long.get( 2 ), 2,
+			new long[][] { { Long.MAX_VALUE, Long.MAX_VALUE }, { Long.MAX_VALUE, Long.MAX_VALUE } } );
+		
+		test( Validator_long.get( 2 ), 2,
+			new long[][] { { Long.MIN_VALUE, Long.MIN_VALUE }, { Long.MIN_VALUE, Long.MIN_VALUE } } );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test_float() throws Exception
+	{
+		test( Validator_float.get( 2 ), 2,
+			new float[][] { { 0, 0 }, { 0, 0 } } );
+		
+		test( Validator_float.get( 2 ), 2,
+			new float[][] { { 1, 1 }, { 1, 1 } } );
+		
+		test( Validator_float.get( 2 ), 2,
+			new float[][] { { -1, -1 }, { -1, -1 } } );
+		
+		test( Validator_float.get( 2 ), 2,
+			new float[][] { { Float.MAX_VALUE, Float.MAX_VALUE }, { Float.MAX_VALUE, Float.MAX_VALUE } } );
+		
+		test( Validator_float.get( 2 ), 2,
+			new float[][] { { Float.MIN_VALUE, Float.MIN_VALUE }, { Float.MIN_VALUE, Float.MIN_VALUE } } );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test_double() throws Exception
+	{
+		test( Validator_double.get( 2 ), 2,
+			new double[][] { { 0, 0 }, { 0, 0 } } );
+		
+		test( Validator_double.get( 2 ), 2,
+			new double[][] { { 1, 1 }, { 1, 1 } } );
+		
+		test( Validator_double.get( 2 ), 2,
+			new double[][] { { -1, -1 }, { -1, -1 } } );
+		
+		test( Validator_double.get( 2 ), 2,
+			new double[][] { { Double.MAX_VALUE, Double.MAX_VALUE }, { Double.MAX_VALUE, Double.MAX_VALUE } } );
+		
+		test( Validator_double.get( 2 ), 2,
+			new double[][] { { Double.MIN_VALUE, Double.MIN_VALUE }, { Double.MIN_VALUE, Double.MIN_VALUE } } );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test_string() throws Exception
+	{
+		test( Validator_string.get( 2 ), 2,
+			new String[][] { { "", "" }, { "", "" } } );
+		
+		test( Validator_string.get( 2 ), 2,
+			new String[][] { { "abc", "abc" }, { "abc", "abc" } } );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test_custom() throws Exception
+	{
+		test( Validator_custom.get( Date.class, 2, false ), 2,
+			new Date[][] { { new Date(), new Date() }, { new Date(), new Date() } } );
+	}
+	
+	private void test( Validator v, int n, Object o )
+	{
+//		System.out.printf( "testing with %s\n", v );
+//		Assert.assertEquals( n, v.getDim() );
+		
+		Assert.assertTrue( v.validate( o ) );
+		
+		if (n > 0)
+		{
+			
+			
+			int k = Array.getLength( o );
+			for (int i = 0; i < k; i++)
+				test( v.elementValidator(), n-1, Array.get( o, i ) );
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/Test_Etch_AuthException.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/Test_Etch_AuthException.java
new file mode 100644
index 0000000..c7abe49
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/Test_Etch_AuthException.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of _Etch_AuthException
+ */
+public class Test_Etch_AuthException
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some unit tests for _Etch_AuthException
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/Test_Etch_RuntimeException.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/Test_Etch_RuntimeException.java
new file mode 100644
index 0000000..37dc492
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/support/Test_Etch_RuntimeException.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.support;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of _Etch_RuntimeException
+ */
+public class Test_Etch_RuntimeException
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some unit tests for _Etch_RuntimeException.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestArrayValue.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestArrayValue.java
new file mode 100644
index 0000000..380142f
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestArrayValue.java
@@ -0,0 +1,108 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.Type;
+import org.junit.Test;
+
+
+/**
+ * Tests ArrayValue.
+ */
+public class TestArrayValue
+{
+	/** @throws Exception */
+	@Test
+	public void constructor1() throws Exception
+	{
+		ArrayValue av = new ArrayValue( new byte[0] );
+		assertEquals( (byte) 0, av.typeCode() );
+		assertNull( av.customStructType() );
+		assertEquals( 0, av.dim() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void constructor2() throws Exception
+	{
+		Type t1 = new Type( "t1" );
+		ArrayValue av = new ArrayValue( new byte[0], (byte) 1, t1, 2 );
+		assertEquals( (byte) 1, av.typeCode() );
+		assertEquals( t1, av.customStructType() );
+		assertEquals( 2, av.dim() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void constructor3() throws Exception
+	{
+		Type t2 = new Type( "t2" );
+		ArrayValue av = new ArrayValue( new byte[0], (byte) 3, t2, 4 );
+		assertEquals( (byte) 3, av.typeCode() );
+		assertEquals( t2, av.customStructType() );
+		assertEquals( 4, av.dim() );
+	}
+	
+	/** */
+	@Test
+	public void addMany1()
+	{
+		Date dt = new Date();
+		ArrayValue av = new ArrayValue( new Object[] { false, (byte) 1, (short) 2, 3, (long) 4, (float) 1.5, 1.6, "abc", null, dt } );
+		assertEquals( 10, av.size() );
+		int index = 0;
+		assertEquals( false, av.get( index++ ) );
+		assertEquals( (byte) 1, av.get( index++ ) );
+		assertEquals( (short) 2, av.get( index++ ) );
+		assertEquals( 3, av.get( index++ ) );
+		assertEquals( (long) 4, av.get( index++ ) );
+		assertEquals( (float) 1.5, av.get( index++ ) );
+		assertEquals( 1.6, av.get( index++ ) );
+		assertEquals( "abc", av.get( index++ ) );
+		assertEquals( null, av.get( index++ ) );
+		assertEquals( dt, av.get( index++ ) );
+	}
+	
+	/** */
+	@Test
+	public void addMany2()
+	{
+		Date dt = new Date();
+		ArrayValue av = new ArrayValue( new Object[] { (float) 1.5, 1.6, "abc", null, dt, false, (byte) 1, (short) 2, 3, (long) 4 } );
+		assertEquals( 10, av.size() );
+		int index = 0;
+		assertEquals( (float) 1.5, av.get( index++ ) );
+		assertEquals( 1.6, av.get( index++ ) );
+		assertEquals( "abc", av.get( index++ ) );
+		assertEquals( null, av.get( index++ ) );
+		assertEquals( dt, av.get( index++ ) );
+		assertEquals( false, av.get( index++ ) );
+		assertEquals( (byte) 1, av.get( index++ ) );
+		assertEquals( (short) 2, av.get( index++ ) );
+		assertEquals( 3, av.get( index++ ) );
+		assertEquals( (long) 4, av.get( index++ ) );
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestDefaultDeliveryService.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestDefaultDeliveryService.java
new file mode 100644
index 0000000..1bec0ad
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestDefaultDeliveryService.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of DefaultDeliveryService
+ */
+public class TestDefaultDeliveryService
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some unit tests for DefaultDeliveryService.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestFormatFactory.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestFormatFactory.java
new file mode 100644
index 0000000..82fad55
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestFormatFactory.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of FormatFactory
+ */
+public class TestFormatFactory
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some unit tests for FormatFactory.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestMessagizer.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestMessagizer.java
new file mode 100644
index 0000000..dc3226c
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestMessagizer.java
@@ -0,0 +1,508 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.TypeMap;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.DefaultValueFactory;
+import org.apache.etch.bindings.java.support.Validator_int;
+import org.apache.etch.bindings.java.support.Validator_long;
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.SessionPacket;
+import org.apache.etch.util.core.io.Transport;
+import org.apache.etch.util.core.io.TransportPacket;
+import org.junit.Test;
+
+
+/** */
+public class TestMessagizer
+{
+	private final static byte VERSION = 3; // BinaryTaggedData.VERSION;
+	private final static byte NONE = -127; // TypeCode.NONE;
+	
+	/** */
+	public TestMessagizer()
+	{
+		transport = new MyTransportPacket();
+		session = new MySessionMessage();
+		
+		Resources res = new Resources();
+		res.put( Transport.VALUE_FACTORY, vf );
+		
+		m = new Messagizer( transport, "foo:?Messagizer.format=binary", res );
+		m.setSession( session );
+	}
+
+	private final ValueFactory vf = new MyValueFactory( "tcp:" );
+
+	private final MyTransportPacket transport;
+
+	private final MySessionMessage session;
+
+	private final Messagizer m;
+	
+	/** @throws Exception */
+	@Test
+	public void construct1() throws Exception
+	{
+		assertSame( transport, m.getTransport() );
+		assertSame( session, m.getSession() );
+		assertSame( m, transport.getSession() );
+	}
+
+	////////////////////////////////
+	// Test PacketHandler methods //
+	////////////////////////////////
+
+//	/** @throws Exception */
+//	@Test
+//	public void up() throws Exception
+//	{
+//		PacketHandler ph = m;
+//
+//		assertNull( mh.what );
+//		assertNull( mh.src );
+//
+//		ph.up( ps );
+//
+//		assertSame( What.TESTMESSAGEHANDLERUP, mh.what );
+//		assertSame( m, mh.src );
+//		assertSame( ps, m.getSource() );
+//	}
+	
+	private final Who who = new Who() { /* nothing */ };
+
+	/** @throws Exception */
+	@Test
+	public void packet1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{ VERSION, 1, 0, NONE } );
+		
+		session.msg_handled = true;
+		
+		m.sessionPacket( who, buf );
+		
+		assertSame( What.SESSION_MESSAGE, session.what );
+		assertSame( who, session.sender );
+		assertSame( MyValueFactory.mt_add, session.msg.type() );
+		assertEquals( 0, session.msg.size() );
+		assertNull( session.event );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void packet2() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{ VERSION, 1, 0, NONE } );
+		
+		session.msg_handled = false;
+		
+		m.sessionPacket( who, buf );
+		
+		assertSame( What.SESSION_NOTIFY, session.what );
+		assertSame( who, session.sender );
+		assertSame( MyValueFactory.mt_add, session.msg.type() );
+		assertEquals( 0, session.msg.size() );
+		assertNotNull( session.event );
+		
+		UnwantedMessage um = (UnwantedMessage) session.event;
+		assertSame( session.sender, um.sender );
+		assertSame( session.msg, um.msg );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void packet3() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{ VERSION, 2, 0, NONE } );
+		
+		session.msg_handled = true;
+		
+		m.sessionPacket( who, buf );
+		
+		assertSame( What.SESSION_MESSAGE, session.what );
+		assertSame( who, session.sender );
+		assertNotNull( session.msg );
+		assertSame( MyValueFactory.mt_add_result, session.msg.type() );
+		assertEquals( 0, session.msg.size() );
+		assertNull( session.event );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void packet4() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{ VERSION, 2, 0, NONE } );
+		
+		session.msg_handled = false;
+		
+		m.sessionPacket( who, buf );
+		
+		assertSame( What.SESSION_NOTIFY, session.what );
+		assertSame( who, session.sender );
+		assertSame( MyValueFactory.mt_add_result, session.msg.type() );
+		assertEquals( 0, session.msg.size() );
+		assertNotNull( session.event );
+		
+		UnwantedMessage um = (UnwantedMessage) session.event;
+		assertSame( session.sender, um.sender );
+		assertSame( session.msg, um.msg );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void message1() throws Exception
+	{
+		Message msg = new Message( MyValueFactory.mt_add, vf );
+		transport.header_size = 0;
+		
+		assertNull( transport.what );
+		
+		m.transportMessage( who, msg );
+
+		assertSame( What.TRANSPORT_PACKET, transport.what );
+		assertSame( who, transport.recipient );
+		assertNotNull( transport.buf );
+		assertEquals( 4, transport.buf.length );
+		assertEquals( VERSION, transport.buf[0] ); // version
+		assertEquals( (byte) 1, transport.buf[1] ); // message type
+		assertEquals( (byte) 0, transport.buf[2] ); // length
+		assertEquals( NONE, transport.buf[3] ); // none
+	}
+
+	/** @throws Exception */
+	@Test
+	public void message2() throws Exception
+	{
+		Message msg = new Message( MyValueFactory.mt_add_result, vf );
+		transport.header_size = 8;
+		
+		assertNull( transport.what );
+		
+		m.transportMessage( who, msg );
+
+		assertSame( What.TRANSPORT_PACKET, transport.what );
+		assertSame( who, transport.recipient );
+		assertNotNull( transport.buf );
+		assertEquals( 12, transport.buf.length );
+		assertEquals( (byte) 0, transport.buf[0] ); // packet header...
+		assertEquals( (byte) 0, transport.buf[1] );
+		assertEquals( (byte) 0, transport.buf[2] );
+		assertEquals( (byte) 0, transport.buf[3] );
+		assertEquals( (byte) 0, transport.buf[4] );
+		assertEquals( (byte) 0, transport.buf[5] );
+		assertEquals( (byte) 0, transport.buf[6] );
+		assertEquals( (byte) 0, transport.buf[7] );
+		assertEquals( VERSION, transport.buf[8] ); // version
+		assertEquals( (byte) 2, transport.buf[9] ); // message type
+		assertEquals( (byte) 0, transport.buf[10] ); // length
+		assertEquals( NONE, transport.buf[11] ); // none
+	}
+
+	/** @throws Exception */
+	@Test
+	public void sessionQuery() throws Exception
+	{
+		Object QUERY = "foo";
+		Object RESULT = "bar";
+		
+		assertNull( session.what );
+		assertNull( session.query );
+		session.query_result = RESULT;
+		
+		Object result = m.sessionQuery( QUERY );
+
+		assertSame( What.SESSION_QUERY, session.what );
+		assertSame( QUERY, session.query );
+		assertSame( RESULT, result );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void sessionControl() throws Exception
+	{
+		Object CONTROL = "foo";
+		Object VALUE = "bar";
+		
+		assertNull( session.what );
+		assertNull( session.control );
+		assertNull( session.value );
+		
+		m.sessionControl( CONTROL, VALUE );
+
+		assertSame( What.SESSION_CONTROL, session.what );
+		assertSame( CONTROL, session.control );
+		assertSame( VALUE, session.value );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void sessionNotify() throws Exception
+	{
+		Object EVENT = "foo";
+		
+		assertNull( session.what );
+		assertNull( session.event );
+		
+		m.sessionNotify( EVENT );
+
+		assertSame( What.SESSION_NOTIFY, session.what );
+		assertSame( EVENT, session.event );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportQuery() throws Exception
+	{
+		Object QUERY = "foo";
+		Object RESULT = "bar";
+		
+		assertNull( transport.what );
+		assertNull( transport.query );
+		transport.query_result = RESULT;
+		
+		Object result = m.transportQuery( QUERY );
+
+		assertSame( What.TRANSPORT_QUERY, transport.what );
+		assertSame( QUERY, transport.query );
+		assertSame( RESULT, result );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportControl() throws Exception
+	{
+		Object CONTROL = "foo";
+		Object VALUE = "bar";
+		
+		assertNull( transport.what );
+		assertNull( transport.control );
+		assertNull( transport.value );
+		
+		m.transportControl( CONTROL, VALUE );
+
+		assertSame( What.TRANSPORT_CONTROL, transport.what );
+		assertSame( CONTROL, transport.control );
+		assertSame( VALUE, transport.value );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportNotify() throws Exception
+	{
+		Object EVENT = "foo";
+		
+		assertNull( transport.what );
+		assertNull( transport.event );
+		
+		m.transportNotify( EVENT );
+
+		assertSame( What.TRANSPORT_NOTIFY, transport.what );
+		assertSame( EVENT, transport.event );
+	}
+
+	/**
+	 * Reports activities which occur.
+	 */
+	public enum What
+	{
+		/** */ TRANSPORT_PACKET,
+		/** */ TRANSPORT_QUERY,
+		/** */ TRANSPORT_CONTROL,
+		/** */ TRANSPORT_NOTIFY,
+		/** */ SESSION_MESSAGE,
+		/** */ SESSION_QUERY,
+		/** */ SESSION_CONTROL,
+		/** */ SESSION_NOTIFY
+	};
+
+	/** */
+	public static class MyTransportPacket implements TransportPacket
+	{
+		/** */ public int header_size;
+		/** */ public What what;
+		/** */ public Who recipient;
+		/** */ public byte[] buf;
+		/** */ public Object query;
+		/** */ public Object query_result;
+		/** */ public Object control;
+		/** */ public Object value;
+		/** */ public Object event;
+		
+		public int headerSize()
+        {
+	        return header_size;
+        }
+
+		public void transportPacket( Who recipient, FlexBuffer buf ) throws Exception
+        {
+	        what = What.TRANSPORT_PACKET;
+	        this.recipient = recipient;
+	        this.buf = buf.getAvailBytes();
+        }
+
+		public Object transportQuery( Object query ) throws Exception
+		{
+			what = What.TRANSPORT_QUERY;
+			this.query = query;
+			return query_result;
+		}
+
+		public void transportControl( Object control, Object value ) throws Exception
+		{
+			what = What.TRANSPORT_CONTROL;
+			this.control = control;
+			this.value = value;
+		}
+
+		public void transportNotify( Object event ) throws Exception
+		{
+			what = What.TRANSPORT_NOTIFY;
+			this.event = event;
+		}
+
+		public SessionPacket getSession()
+		{
+			return session;
+		}
+
+		public void setSession( SessionPacket session )
+		{
+			this.session = session;
+		}
+		
+		private SessionPacket session;
+	}
+
+	/** */
+	public static class MySessionMessage implements SessionMessage
+	{
+		/** */
+		public What what;
+		/** */
+		public Who sender;
+		/** */
+		public Message msg;
+		/** */
+		public boolean msg_handled;
+		/** */
+		public Object query;
+		/** */
+		public Object query_result;
+		/** */
+		public Object control;
+		/** */
+		public Object value;
+		/** */
+		public Object event;
+
+		public boolean sessionMessage( Who sender, Message msg ) throws Exception
+		{
+			what = What.SESSION_MESSAGE;
+			this.sender = sender;
+			this.msg = msg;
+			return msg_handled;
+		}
+
+		public Object sessionQuery( Object query )
+		{
+			what = What.SESSION_QUERY;
+			this.query = query;
+			return query_result;
+		}
+
+		public void sessionControl( Object control, Object value )
+		{
+			what = What.SESSION_CONTROL;
+			this.control = control;
+			this.value = value;
+		}
+
+		public void sessionNotify( Object event )
+		{
+			what = What.SESSION_NOTIFY;
+			this.event = event;
+		}
+	}
+	
+	/** Private value factory for testing. */
+	public static class MyValueFactory extends DefaultValueFactory
+	{
+		/**
+		 * Construct MyValueFactory.
+		 * @param uri 
+		 */
+		public MyValueFactory( String uri )
+		{
+			super( uri, types, class2type );
+		}
+		
+		private final static TypeMap types = new TypeMap();
+		
+		private final static Class2TypeMap class2type = new Class2TypeMap();
+
+		static
+		{
+			DefaultValueFactory.init( types, class2type );
+		}
+
+		/** */
+		public final static Type mt_add = types.add( new Type( 1, "add" ) );
+
+		/** */
+		public final static Type mt_add_result = types.add( new Type( 2, "add_result" ) );
+
+		/** */
+		public final static Field mf_x = new Field( 3, "x" );
+
+		/** */
+		public final static Field mf_y = new Field( 4, "y" );
+
+		/** */
+		public final static Field mf_result = new Field( 5, "xresult" );
+		
+		static
+		{
+			mt_add.putValidator( mf_x, Validator_int.get( 0 ) );
+			mt_add.putValidator( mf_y, Validator_int.get( 0 ) );
+			mt_add.putValidator( _mf__messageId, Validator_long.get( 0 ) );
+
+			mt_add_result.putValidator( mf_result, Validator_int.get( 0 ) );
+			mt_add_result.putValidator( _mf__messageId, Validator_long.get( 0 ) );
+			mt_add_result.putValidator( _mf__inReplyTo, Validator_long.get( 0 ) );
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestPlainMailbox.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestPlainMailbox.java
new file mode 100644
index 0000000..bbe6976
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestPlainMailbox.java
@@ -0,0 +1,711 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.DummyValueFactory;
+import org.apache.etch.bindings.java.support.Mailbox;
+import org.apache.etch.bindings.java.support.Mailbox.Element;
+import org.apache.etch.bindings.java.support.Mailbox.Notify;
+import org.apache.etch.util.core.Who;
+import org.junit.Ignore;
+import org.junit.Test;
+
+
+/** Test of PlainMailbox */
+public class TestPlainMailbox
+{
+	private final MyMailboxManager mmgr = new MyMailboxManager();
+
+	private final MyNotify notify = new MyNotify();
+	private final MyNotify notify1 = new MyNotify();
+	
+	/** @throws Exception */
+	@Test
+	public void construct1() throws Exception
+	{
+		testConstruct( 1L );
+	}
+
+	/** @throws Exception */
+	@Test( expected = NullPointerException.class )
+	public void construct2() throws Exception
+	{
+		new PlainMailbox( null, 1L );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = NullPointerException.class )
+	public void construct3() throws Exception
+	{
+		new PlainMailbox( mmgr, null );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void closeDelivery1() throws Exception
+	{
+		// open mailbox and close it for delivery while empty.
+		
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		checkCloseDelivery( mb, true );
+		checkMailbox( mb, true, false, true, true, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void closeDelivery2() throws Exception
+	{
+		// open mailbox and close it for delivery while not empty.
+		
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		checkDeliver( mb, true, alice_who, foo_msg );
+		checkMailbox( mb, false, true, false, false, 0 );
+		
+		checkCloseDelivery( mb, true );
+		checkMailbox( mb, false, true, true, true, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void closeDelivery3() throws Exception
+	{
+		// open mailbox and close it for delivery twice.
+		
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		checkCloseDelivery( mb, true );
+		checkMailbox( mb, true, false, true, true, 0 );
+		
+		checkCloseDelivery( mb, false );
+		checkMailbox( mb, true, false, true, true, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void closeRead1() throws Exception
+	{
+		// open mailbox and close it for reading while empty.
+		
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		checkCloseRead( mb, true );
+		checkMailbox( mb, true, false, true, true, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void closeRead2() throws Exception
+	{
+		// open mailbox and close it for reading while not empty.
+		
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		checkDeliver( mb, true, alice_who, foo_msg );
+		checkMailbox( mb, false, true, false, false, 0 );
+		
+		checkCloseRead( mb, true );
+		checkMailbox( mb, true, false, true, true, 1 );
+		checkRedelivered( 0, alice_who, foo_msg );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void closeRead3() throws Exception
+	{
+		// open mailbox and close it for reading twice while empty.
+		
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		checkCloseRead( mb, true );
+		checkMailbox( mb, true, false, true, true, 0 );
+		
+		checkCloseRead( mb, false );
+		checkMailbox( mb, true, false, true, true, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void closeRead4() throws Exception
+	{
+		// open mailbox and close it for reading twice while not empty.
+		
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		checkDeliver( mb, true, alice_who, foo_msg );
+		checkMailbox( mb, false, true, false, false, 0 );
+		
+		checkCloseRead( mb, true );
+		checkMailbox( mb, true, false, true, true, 1 );
+		checkRedelivered( 0, alice_who, foo_msg );
+		
+		checkCloseRead( mb, false );
+		checkMailbox( mb, true, false, true, true, 1 );
+		checkRedelivered( 0, alice_who, foo_msg );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void full1() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		checkDeliver( mb, true, fred_who, foo_msg );
+		checkMailbox( mb, false, true, false, false, 0 );
+		
+		checkDeliver( mb, false, alice_who, bar_msg );
+		checkMailbox( mb, false, true, false, false, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void full2() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		checkDeliver( mb, true, fred_who, foo_msg );
+		checkMailbox( mb, false, true, false, false, 0 );
+		
+		checkDeliver( mb, false, alice_who, bar_msg );
+		checkMailbox( mb, false, true, false, false, 0 );
+		
+		checkDeliver( mb, false, mark_who, baz_msg );
+		checkMailbox( mb, false, true, false, false, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void read1() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		checkDeliver( mb, true, alice_who, bar_msg );
+		checkMailbox( mb, false, true, false, false, 0 );
+
+		checkRead( mb, true, alice_who, bar_msg );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		checkCloseDelivery( mb, true );
+		checkMailbox( mb, true, false, true, true, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void read2() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		checkDeliver( mb, true, alice_who, bar_msg );
+		checkMailbox( mb, false, true, false, false, 0 );
+		
+		checkCloseDelivery( mb, true );
+		checkMailbox( mb, false, true, true, true, 0 );
+
+		checkRead( mb, true, alice_who, bar_msg );
+		checkMailbox( mb, true, false, true, true, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void read3() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		checkDeliver( mb, true, alice_who, bar_msg );
+		checkMailbox( mb, false, true, false, false, 0 );
+		
+		checkCloseDelivery( mb, true );
+		checkMailbox( mb, false, true, true, true, 0 );
+
+		checkRead( mb, true, alice_who, bar_msg );
+		checkMailbox( mb, true, false, true, true, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void read4() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		checkCloseDelivery( mb, true );
+		checkMailbox( mb, true, false, true, true, 0 );
+
+		checkRead( mb, false, null, null );
+		checkMailbox( mb, true, false, true, true, 0 );
+	}
+
+	/** @throws Exception */
+	@Test @Ignore
+	public void read5() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		Thread.sleep( 1000 );
+
+		checkRead( mb, false, null, null );
+		checkMailbox( mb, true, false, true, true, 0 );
+	}
+
+	/** @throws Exception */
+	@Test @Ignore
+	public void read6() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+
+		checkRead( mb, false, null, null );
+		checkMailbox( mb, true, false, true, true, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void read7() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+
+		checkRead( mb, -1, false, null, null );
+		checkMailbox( mb, true, false, false, false, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void read8() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+
+		checkRead( mb, 1, false, null, null );
+		checkMailbox( mb, true, false, false, false, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void deliver1() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		checkMailbox( mb, true, false, false, false, 0 );
+		
+		checkCloseDelivery( mb, true );
+		checkMailbox( mb, true, false, true, true, 0 );
+		
+		checkDeliver( mb, false, fred_who, bar_msg );
+		checkMailbox( mb, true, false, true, true, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void notify1() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		notify.checkMailboxStatus( false, null, null, false );
+		
+		Object state = new Object();
+		
+		mb.registerNotify( notify, state, 0 );
+		notify.checkMailboxStatus( false, null, null, false );
+		
+		checkCloseDelivery( mb, true );
+		notify.checkMailboxStatus( true, mb, state, true );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void notify2() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		notify.checkMailboxStatus( false, null, null, false );
+		
+		Object state = new Object();
+		
+		mb.registerNotify( notify, state, 1000 );
+		notify.checkMailboxStatus( false, null, null, false );
+		
+		Thread.sleep( 2000 );
+		notify.checkMailboxStatus( true, mb, state, true );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void notify3() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		notify.checkMailboxStatus( false, null, null, false );
+		
+		Object state = new Object();
+		
+		mb.registerNotify( notify, state, 0 );
+		notify.checkMailboxStatus( false, null, null, false );
+		
+		Thread.sleep( 2000 );
+		notify.checkMailboxStatus( false, null, null, false );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void notify4() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		notify.checkMailboxStatus( false, null, null, false );
+		
+		Object state = new Object();
+		
+		mb.registerNotify( notify, state, 0 );
+		notify.checkMailboxStatus( false, null, null, false );
+		
+		mb.message( alice_who, foo_msg );
+		notify.checkMailboxStatus( true, mb, state, false );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = NullPointerException.class )
+	public void reg1() throws Exception
+	{
+		// notify == null
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		mb.registerNotify( null, null, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void reg2() throws Exception
+	{
+		// maxDelay < 0
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		mb.registerNotify( notify, null, -1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void reg3() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		mb.registerNotify( notify, null, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void reg4() throws Exception
+	{
+		// this.notify != null
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		mb.registerNotify( notify, null, 0 );
+		mb.registerNotify( notify, null, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void reg5() throws Exception
+	{
+		// this.notify != null
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		mb.registerNotify( notify, null, 0 );
+		mb.registerNotify( notify1, null, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void unreg1() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		mb.unregisterNotify( notify );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void unreg2() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		mb.registerNotify( notify, null, 0 );
+		mb.unregisterNotify( notify );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void unreg3() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		mb.registerNotify( notify, null, 0 );
+		mb.unregisterNotify( notify );
+		mb.unregisterNotify( notify );
+		mb.unregisterNotify( notify1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void unreg4() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		mb.registerNotify( notify, null, 0 );
+		mb.unregisterNotify( notify );
+		mb.registerNotify( notify, null, 0 );
+		mb.unregisterNotify( notify );
+		mb.registerNotify( notify1, null, 0 );
+		mb.unregisterNotify( notify1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void unreg5() throws Exception
+	{
+		// notify != this.notify
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		mb.registerNotify( notify, null, 0 );
+		mb.unregisterNotify( notify1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void unreg6() throws Exception
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, 1L );
+		mb.registerNotify( notify, null, 30 );
+		mb.unregisterNotify( notify );
+	}
+
+	///////////////////
+	// HELPFUL STUFF //
+	///////////////////
+	
+	private final ValueFactory vf = new DummyValueFactory();
+	
+	private final Type mt_foo = new Type( "foo" );
+	private final Message foo_msg = new Message( mt_foo, vf );
+	private final Who fred_who = new Who() { /* */ };
+	
+	private final Type mt_bar = new Type( "bar" );
+	private final Message bar_msg = new Message( mt_bar, vf );
+	private final Who alice_who = new Who() { /* */ };
+	
+	private final Type mt_baz = new Type( "baz" );
+	private final Message baz_msg = new Message( mt_baz, vf );
+	private final Who mark_who = new Who() { /* */ };
+
+	private void testConstruct( Long messageId )
+	{
+		PlainMailbox mb = new PlainMailbox( mmgr, messageId );
+		
+		assertEquals( mmgr, mb.getMailboxManager() );
+		assertEquals( messageId, mb.getMessageId() );
+	}
+	
+	private void checkDeliver( PlainMailbox mb, boolean handled, Who who,
+		Message msg ) throws Exception
+	{
+		assertEquals( handled, mb.message( who, msg ) );
+	}
+	
+	private void checkRead( PlainMailbox mb, boolean present, Who who, Message msg )
+		throws InterruptedException
+	{
+		Element e = mb.read();
+		if (present)
+			checkElement( e, who, msg );
+		else
+			assertNull( e );
+	}
+	
+	private void checkRead( PlainMailbox mb, int maxDelay, boolean present,
+		Who who, Message msg ) throws InterruptedException
+	{
+		Element e = mb.read( maxDelay );
+		if (present)
+			checkElement( e, who, msg );
+		else
+			assertNull( e );
+	}
+
+	private void checkRedelivered( int index, Who who, Message msg )
+	{
+		Element e = mmgr.redelivered.get( index );
+		checkElement( e, who, msg );
+	}
+
+	private void checkElement( Element e, Who who, Message msg )
+	{
+		assertNotNull( e );
+		assertSame( who, e.sender );
+		assertSame( msg, e.msg );
+	}
+
+	private void checkMailbox( PlainMailbox mb, boolean empty, boolean full,
+		boolean closed, boolean unreg, int size )
+	{
+		assertEquals( empty, mb.isEmpty() );
+		assertEquals( full, mb.isFull() );
+		assertEquals( closed, mb.isClosed() );
+		assertEquals( unreg, mmgr.unregistered );
+		assertEquals( size, mmgr.redelivered.size() );
+	}
+	
+	private void checkCloseRead( PlainMailbox mb, boolean closed )
+		throws Exception
+	{
+		assertEquals( closed, mb.closeRead() );
+	}
+	
+	private void checkCloseDelivery( PlainMailbox mb, boolean closed )
+		throws Exception
+	{
+		assertEquals( closed, mb.closeDelivery() );
+	}
+	
+	/** */
+	static class MyNotify implements Notify
+	{
+		public void mailboxStatus( Mailbox mb, Object state, boolean closed )
+		{
+			mailboxStatus = true;
+			mailbox = mb;
+			this.state = state;
+			this.closed = closed;
+		}
+		
+		/**
+		 * @param mailboxStatus
+		 * @param mailbox
+		 * @param state
+		 * @param closed
+		 */
+		public void checkMailboxStatus( boolean mailboxStatus, Mailbox mailbox,
+			Object state, boolean closed )
+		{
+			assertEquals( mailboxStatus, this.mailboxStatus );
+			assertSame( mailbox, this.mailbox );
+			assertSame( state, this.state );
+			assertEquals( closed, this.closed );
+		}
+		
+		private boolean mailboxStatus;
+		
+		private Mailbox mailbox;
+		
+		private Object state;
+		
+		private boolean closed;
+	}
+	
+	/** */
+	static class MyMailboxManager implements MailboxManager
+	{
+		/** */
+		public final List<Element> redelivered = new ArrayList<Element>();
+		
+		/** */
+		public boolean unregistered;
+		
+		public void redeliver( Who sender, Message msg ) throws Exception
+		{
+			redelivered.add( new Element( sender, msg ) );
+		}
+
+		public Mailbox transportCall( Who recipient, Message msg )
+			throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void unregister( Mailbox mb )
+		{
+			unregistered = true;
+		}
+
+		public boolean sessionMessage( Who sender, Message msg )
+			throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void sessionControl( Object control, Object value )
+			throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void sessionNotify( Object event ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Object sessionQuery( Object query ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void transportMessage( Who recipient, Message msg )
+			throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public SessionMessage getSession()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void setSession( SessionMessage session )
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void transportControl( Object control, Object value )
+			throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void transportNotify( Object event ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Object transportQuery( Object query ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestPlainMailboxManager.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestPlainMailboxManager.java
new file mode 100644
index 0000000..cec8a00
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestPlainMailboxManager.java
@@ -0,0 +1,698 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.TypeMap;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.DefaultValueFactory;
+import org.apache.etch.bindings.java.support.Mailbox;
+import org.apache.etch.bindings.java.support.Validator_long;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.Session;
+import org.junit.Test;
+
+
+/** Tests MailboxManager */
+public class TestPlainMailboxManager
+{
+	private final ValueFactory vf = new MyValueFactory( "tcp:" );
+	private final Who who = new Who() {};
+	private final MyTransportMessage transport = new MyTransportMessage();
+	private final MySessionMessage session = new MySessionMessage();
+	private final PlainMailboxManager mmgr = new PlainMailboxManager( transport, "", null );
+	{
+		mmgr.setSession( session );
+	}
+	
+	private Message constructAddMessage() throws Exception
+	{
+		return new Message( MyValueFactory.mt_add, vf );
+	}
+	
+	private Message constructAddResultMessage() throws Exception
+	{
+		return new Message( MyValueFactory.mt_add_result, vf );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construction() throws Exception
+	{
+		assertSame( mmgr, transport.getSession() );
+		assertSame( session, mmgr.getSession() );
+		assertSame( transport, mmgr.getTransport() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportMessage1() throws Exception
+	{
+		// test sending an event message
+		
+		assertNull( transport.what );
+		assertNull( transport.recipient );
+		assertNull( transport.msg );
+		
+		Message msg = constructAddMessage();
+		assertNull( msg.getMessageId() );
+		assertNull( msg.getInReplyTo() );
+		
+		mmgr.transportMessage( who, msg );
+		
+		assertSame( transport.what, What.TRANSPORT_MESSAGE );
+		assertSame( transport.recipient, who );
+		assertSame( transport.msg, msg );
+		
+		assertEquals( 0, mmgr.size() );
+		assertNotNull( msg.getMessageId() );
+		assertNull( msg.getInReplyTo() );
+		assertNull( mmgr.getMailbox( msg.getMessageId() ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportMessage2() throws Exception
+	{
+		// test sending a result message
+		
+		assertNull( transport.what );
+		assertNull( transport.recipient );
+		assertNull( transport.msg );
+		
+		Message msg = constructAddResultMessage();
+		assertNull( msg.getMessageId() );
+		assertNull( msg.getInReplyTo() );
+		msg.setInReplyTo( 1L );
+		
+		mmgr.transportMessage( who, msg );
+		
+		assertSame( transport.what, What.TRANSPORT_MESSAGE );
+		assertSame( transport.recipient, who );
+		assertSame( transport.msg, msg );
+		
+		assertEquals( 0, mmgr.size() );
+		assertNotNull( msg.getMessageId() );
+		assertEquals( 1L, msg.getInReplyTo() );
+		assertNull( mmgr.getMailbox( msg.getMessageId() ) );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void transportMessage3() throws Exception
+	{
+		// test sending a message that has already been sent (has a message id)
+		
+		assertNull( transport.what );
+		assertNull( transport.recipient );
+		assertNull( transport.msg );
+		
+		Message msg = constructAddMessage();
+		assertNull( msg.getMessageId() );
+		msg.setMessageId( 1L );
+
+		// this should trigger msg already sent
+		mmgr.transportMessage( who, msg );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportCall1() throws Exception
+	{
+		// test sending a call message
+		
+		mmgr.sessionNotify( Session.UP );
+		
+		assertNull( transport.what );
+		assertNull( transport.recipient );
+		assertNull( transport.msg );
+		
+		Message msg = constructAddMessage();
+		assertNull( msg.getMessageId() );
+		assertNull( msg.getInReplyTo() );
+		
+		Mailbox mb = mmgr.transportCall( who, msg );
+		
+		assertSame( transport.what, What.TRANSPORT_MESSAGE );
+		assertSame( transport.recipient, who );
+		assertSame( transport.msg, msg );
+		assertNotNull( mb );
+		
+		assertEquals( 1, mmgr.size() );
+		assertNotNull( msg.getMessageId() );
+		assertNull( msg.getInReplyTo() );
+		assertSame( mb, mmgr.getMailbox( msg.getMessageId() ) );
+		
+		mb.closeRead();
+		
+		assertEquals( 0, mmgr.size() );
+		assertNull( mmgr.getMailbox( msg.getMessageId() ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportCall2() throws Exception
+	{
+		// test sending a call message
+		
+		mmgr.sessionNotify( Session.UP );
+		
+		assertNull( transport.what );
+		assertNull( transport.recipient );
+		assertNull( transport.msg );
+		
+		Message msg = constructAddMessage();
+		assertNull( msg.getMessageId() );
+		assertNull( msg.getInReplyTo() );
+		
+		Mailbox mb = mmgr.transportCall( who, msg );
+		
+		assertSame( transport.what, What.TRANSPORT_MESSAGE );
+		assertSame( transport.recipient, who );
+		assertSame( transport.msg, msg );
+		assertNotNull( mb );
+		
+		assertEquals( 1, mmgr.size() );
+		assertNotNull( msg.getMessageId() );
+		assertNull( msg.getInReplyTo() );
+		assertSame( mb, mmgr.getMailbox( msg.getMessageId() ) );
+		
+		mb.closeDelivery();
+		
+		assertEquals( 0, mmgr.size() );
+		assertNull( mmgr.getMailbox( msg.getMessageId() ) );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void transportCall3() throws Exception
+	{
+		// test sending a call message that has already been sent (has a message id)
+		
+		assertNull( transport.what );
+		assertNull( transport.recipient );
+		assertNull( transport.msg );
+		
+		Message msg = constructAddMessage();
+		assertNull( msg.getMessageId() );
+		assertNull( msg.getInReplyTo() );
+		msg.setMessageId( 1L );
+
+		try
+		{
+			// this should trigger msg already sent
+			mmgr.transportCall( who, msg );
+		}
+		finally
+		{
+			assertEquals( 0, mmgr.size() );
+			assertNull( mmgr.getMailbox( msg.getMessageId() ) );
+		}
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void transportCall4() throws Exception
+	{
+		assertNull( transport.what );
+		assertNull( transport.recipient );
+		assertNull( transport.msg );
+		
+		Message msg = constructAddResultMessage();
+		assertNull( msg.getMessageId() );
+		assertNull( msg.getInReplyTo() );
+		msg.setInReplyTo( 1L );
+		
+		try
+		{
+			// this should trigger message is marked as a reply
+			mmgr.transportCall( who, msg );
+		}
+		finally
+		{
+			assertEquals( 0, mmgr.size() );
+			assertNull( mmgr.getMailbox( msg.getMessageId() ) );
+		}
+	}
+
+	/////////////////////////////
+	// tests of sessionMessage //
+	/////////////////////////////
+	
+	/** @throws Exception */
+	@Test
+	public void sessionMessage1() throws Exception
+	{
+		// message without an inReplyTo, session wants it.
+		
+		assertNull( session.what );
+		assertNull( session.sender );
+		assertNull( session.msg );
+		
+		Message msg = constructAddMessage();
+		
+		session.msg_handled = true;
+		boolean msg_handled = mmgr.sessionMessage( who, msg );
+		assertTrue( msg_handled );
+		
+		assertSame( What.SESSION_MESSAGE, session.what );
+		assertSame( who, session.sender );
+		assertSame( msg, session.msg );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void sessionMessage2() throws Exception
+	{
+		// message without an inReplyTo, session doesn't want it.
+		
+		assertNull( session.what );
+		assertNull( session.sender );
+		assertNull( session.msg );
+		
+		Message msg = constructAddMessage();
+		
+		session.msg_handled = false;
+		boolean msg_handled = mmgr.sessionMessage( who, msg );
+		assertFalse( msg_handled );
+		
+		assertSame( What.SESSION_MESSAGE, session.what );
+		assertSame( who, session.sender );
+		assertSame( msg, session.msg );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void sessionMessage3() throws Exception
+	{
+		// message with an inReplyTo which doesn't match a mailbox
+		
+		assertNull( session.what );
+		assertNull( session.sender );
+		assertNull( session.msg );
+		
+		Message msg = constructAddResultMessage();
+		msg.setInReplyTo( 1L );
+		
+		session.msg_handled = true;
+		boolean msg_handled = mmgr.sessionMessage( who, msg );
+		assertFalse( msg_handled );
+
+		assertNull( session.what );
+		assertNull( session.sender );
+		assertNull( session.msg );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void sessionMessage4() throws Exception
+	{
+		// message with an inReplyTo which doesn't match a mailbox
+		
+		assertNull( session.what );
+		assertNull( session.sender );
+		assertNull( session.msg );
+		
+		Message msg = constructAddResultMessage();
+		msg.setInReplyTo( 1L );
+		
+		session.msg_handled = false;
+		boolean msg_handled = mmgr.sessionMessage( who, msg );
+		assertFalse( msg_handled );
+
+		assertNull( session.what );
+		assertNull( session.sender );
+		assertNull( session.msg );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void sessionMessage5() throws Exception
+	{
+		// message with an inReplyTo which matches a mailbox which is open
+		
+		mmgr.sessionNotify( Session.UP );
+		session.what = null;
+		session.event = null;
+		
+		assertNull( session.what );
+		assertNull( session.sender );
+		assertNull( session.msg );
+		
+		assertNull( transport.what );
+		assertNull( transport.recipient );
+		assertNull( transport.msg );
+		
+		Message msg = constructAddMessage();
+		Mailbox mb = mmgr.transportCall( who, msg );
+		
+		assertSame( transport.what, What.TRANSPORT_MESSAGE );
+		assertSame( transport.recipient, who );
+		assertSame( transport.msg, msg );
+		assertNotNull( mb );
+		
+		assertEquals( 1, mmgr.size() );
+		assertNotNull( msg.getMessageId() );
+		assertNull( msg.getInReplyTo() );
+		assertSame( mb, mmgr.getMailbox( msg.getMessageId() ) );
+		
+		Message rmsg = msg.reply( MyValueFactory.mt_add_result );
+		boolean msg_handled = mmgr.sessionMessage( who, rmsg );
+		assertTrue( msg_handled );
+		
+		assertNull( session.what );
+		assertNull( session.sender );
+		assertNull( session.msg );
+		
+		Mailbox.Element x = mb.read();
+		assertSame( who, x.sender );
+		assertSame( rmsg, x.msg );
+		
+		assertEquals( 1, mmgr.size() );
+		assertSame( mb, mmgr.getMailbox( msg.getMessageId() ) );
+		
+		mb.closeRead();
+		
+		assertEquals( 0, mmgr.size() );
+		assertNull( mmgr.getMailbox( msg.getMessageId() ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void sessionMessage6() throws Exception
+	{
+		// message with an inReplyTo which matches a mailbox which is open
+		
+		mmgr.sessionNotify( Session.UP );
+		session.what = null;
+		session.event = null;
+		
+		assertNull( session.what );
+		assertNull( session.sender );
+		assertNull( session.msg );
+		
+		assertNull( transport.what );
+		assertNull( transport.recipient );
+		assertNull( transport.msg );
+		
+		Message msg = constructAddMessage();
+		Mailbox mb = mmgr.transportCall( who, msg );
+		
+		assertSame( transport.what, What.TRANSPORT_MESSAGE );
+		assertSame( transport.recipient, who );
+		assertSame( transport.msg, msg );
+		assertNotNull( mb );
+		
+		assertEquals( 1, mmgr.size() );
+		assertNotNull( msg.getMessageId() );
+		assertNull( msg.getInReplyTo() );
+		assertSame( mb, mmgr.getMailbox( msg.getMessageId() ) );
+		
+		mb.closeRead();
+		
+		assertEquals( 0, mmgr.size() );
+		assertNull( mmgr.getMailbox( msg.getMessageId() ) );
+		
+		Message rmsg = msg.reply( MyValueFactory.mt_add_result );
+		boolean msg_handled = mmgr.sessionMessage( who, rmsg );
+		assertFalse( msg_handled );
+		
+		assertNull( session.what );
+		assertNull( session.sender );
+		assertNull( session.msg );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void sessionQuery() throws Exception
+	{
+		Object QUERY = "foo";
+		Object RESULT = "bar";
+		
+		assertNull( session.what );
+		assertNull( session.query );
+		session.query_result = RESULT;
+		
+		Object result = mmgr.sessionQuery( QUERY );
+
+		assertSame( What.SESSION_QUERY, session.what );
+		assertSame( QUERY, session.query );
+		assertSame( RESULT, result );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void sessionControl() throws Exception
+	{
+		Object CONTROL = "foo";
+		Object VALUE = "bar";
+		
+		assertNull( session.what );
+		assertNull( session.control );
+		assertNull( session.value );
+		
+		mmgr.sessionControl( CONTROL, VALUE );
+
+		assertSame( What.SESSION_CONTROL, session.what );
+		assertSame( CONTROL, session.control );
+		assertSame( VALUE, session.value );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void sessionNotify() throws Exception
+	{
+		Object EVENT = "foo";
+		
+		assertNull( session.what );
+		assertNull( session.event );
+		
+		mmgr.sessionNotify( EVENT );
+
+		assertSame( What.SESSION_NOTIFY, session.what );
+		assertSame( EVENT, session.event );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportQuery() throws Exception
+	{
+		Object QUERY = "foo";
+		Object RESULT = "bar";
+		
+		assertNull( transport.what );
+		assertNull( transport.query );
+		transport.query_result = RESULT;
+		
+		Object result = mmgr.transportQuery( QUERY );
+
+		assertSame( What.TRANSPORT_QUERY, transport.what );
+		assertSame( QUERY, transport.query );
+		assertSame( RESULT, result );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportControl() throws Exception
+	{
+		Object CONTROL = "foo";
+		Object VALUE = "bar";
+		
+		assertNull( transport.what );
+		assertNull( transport.control );
+		assertNull( transport.value );
+		
+		mmgr.transportControl( CONTROL, VALUE );
+
+		assertSame( What.TRANSPORT_CONTROL, transport.what );
+		assertSame( CONTROL, transport.control );
+		assertSame( VALUE, transport.value );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportNotify() throws Exception
+	{
+		Object EVENT = "foo";
+		
+		assertNull( transport.what );
+		assertNull( transport.event );
+		
+		mmgr.transportNotify( EVENT );
+
+		assertSame( What.TRANSPORT_NOTIFY, transport.what );
+		assertSame( EVENT, transport.event );
+	}
+
+	/** */
+	public enum What
+	{
+		/** */ SESSION_MESSAGE,
+		/** */ SESSION_QUERY,
+		/** */ SESSION_CONTROL,
+		/** */ SESSION_NOTIFY,
+		/** */ TRANSPORT_MESSAGE,
+		/** */ TRANSPORT_QUERY,
+		/** */ TRANSPORT_CONTROL,
+		/** */ TRANSPORT_NOTIFY
+	}
+	
+	/** */
+	public static class MyTransportMessage implements TransportMessage
+	{
+		/** */ public What what;
+		/** */ public Who recipient;
+		/** */ public Message msg;
+		/** */ public Object query;
+		/** */ public Object query_result;
+		/** */ public Object control;
+		/** */ public Object value;
+		/** */ public Object event;
+		
+		public void transportMessage( Who recipient, Message msg )
+			throws Exception
+		{
+			what = What.TRANSPORT_MESSAGE;
+			this.recipient = recipient;
+			this.msg = msg;
+		}
+
+		public Object transportQuery( Object query ) throws Exception
+		{
+			what = What.TRANSPORT_QUERY;
+			this.query = query;
+			return query_result;
+		}
+
+		public void transportControl( Object control, Object value )
+			throws Exception
+		{
+			what = What.TRANSPORT_CONTROL;
+			this.control = control;
+			this.value = value;
+		}
+
+		public void transportNotify( Object event ) throws Exception
+		{
+			what = What.TRANSPORT_NOTIFY;
+			this.event = event;
+		}
+
+		public SessionMessage getSession()
+		{
+			return session;
+		}
+
+		public void setSession( SessionMessage session )
+		{
+			this.session = session;
+		}
+		
+		private SessionMessage session;
+	}
+	
+	/** */
+	public static class MySessionMessage implements SessionMessage
+	{
+		/** */ public What what;
+		/** */ public Who sender;
+		/** */ public Message msg;
+		/** */ public boolean msg_handled;
+		/** */ public Object query;
+		/** */ public Object query_result;
+		/** */ public Object control;
+		/** */ public Object value;
+		/** */ public Object event;
+		
+		public boolean sessionMessage( Who sender, Message msg ) throws Exception
+		{
+			what = What.SESSION_MESSAGE;
+			this.sender = sender;
+			this.msg = msg;
+			return msg_handled;
+		}
+
+		public Object sessionQuery( Object query )
+		{
+			what = What.SESSION_QUERY;
+			this.query = query;
+			return query_result;
+		}
+
+		public void sessionControl( Object control, Object value )
+		{
+			what = What.SESSION_CONTROL;
+			this.control = control;
+			this.value = value;
+		}
+
+		public void sessionNotify( Object event )
+		{
+			what = What.SESSION_NOTIFY;
+			this.event = event;
+		}
+	}
+	
+	/** Private value factory for testing. */
+	public static class MyValueFactory extends DefaultValueFactory
+	{
+		/**
+		 * Construct MyValueFactory.
+		 * @param uri 
+		 */
+		public MyValueFactory( String uri )
+		{
+			super( uri, types, class2type );
+		}
+		
+		private final static TypeMap types = new TypeMap();
+		
+		private final static Class2TypeMap class2type = new Class2TypeMap();
+
+		static
+		{
+			DefaultValueFactory.init( types, class2type );
+		}
+
+		/** */
+		public final static Type mt_add = types.get( "add" );
+		
+		/** */
+		public final static Type mt_add_result = types.get( "add_result" );
+		
+		static
+		{
+			mt_add.putValidator( DefaultValueFactory._mf__messageId, Validator_long.get( 0 ) );
+			
+			mt_add_result.putValidator( DefaultValueFactory._mf__messageId, Validator_long.get( 0 ) );
+			mt_add_result.putValidator( DefaultValueFactory._mf__inReplyTo, Validator_long.get( 0 ) );
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestTcp2TransportFactory.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestTcp2TransportFactory.java
new file mode 100644
index 0000000..11fbdf6
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestTcp2TransportFactory.java
@@ -0,0 +1,34 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import org.junit.Test;
+
+/** Test of Tcp2TransportFactory */
+public class TestTcp2TransportFactory
+{
+	/** @throws Exception */
+	@Test
+	public void listener1() throws Exception
+	{
+		
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestTcpTransportFactory.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestTcpTransportFactory.java
new file mode 100644
index 0000000..c35db23
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestTcpTransportFactory.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of TcpTransportFactory
+ */
+public class TestTcpTransportFactory
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some unit tests for TcpTransportFactory.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestUnwantedMessage.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestUnwantedMessage.java
new file mode 100644
index 0000000..f96d6b6
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/TestUnwantedMessage.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test of UnwantedMessage
+ */
+public class TestUnwantedMessage
+{
+	/** @throws Exception */
+	@Test
+	@Ignore
+	public void nothing() throws Exception
+	{
+		// TODO write some unit tests for UnwantedMessage.
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/filters/TestKeepAlive.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/filters/TestKeepAlive.java
new file mode 100644
index 0000000..d2a259f
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/filters/TestKeepAlive.java
@@ -0,0 +1,413 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.filters;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.TypeMap;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.DefaultValueFactory;
+import org.apache.etch.bindings.java.support.Validator_int;
+import org.apache.etch.bindings.java.transport.SessionMessage;
+import org.apache.etch.bindings.java.transport.TransportMessage;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.Session;
+import org.apache.etch.util.core.io.Transport;
+import org.junit.Test;
+
+
+/** */
+public class TestKeepAlive
+{
+	private final MyTransport transport = new MyTransport();
+	private final MySession session = new MySession();
+	private final MyValueFactory vf = new MyValueFactory( "tcp:" );
+	private final Resources resources = new Resources();
+	{
+		resources.put( Transport.VALUE_FACTORY, vf );
+		Log.addSink( null );
+	}
+	
+	private KeepAlive newKeepAlive(String uri) throws Exception
+	{
+		return new KeepAlive(transport,new URL(uri),resources);
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void constructor1() throws Exception
+	{
+		transport.is_server = true;
+		String uri = "tcp://localhost:4801?filter=KeepAlive";
+		KeepAlive filter = newKeepAlive(uri);
+		filter.setSession( session );
+		
+		assertSame(transport.getSession(),filter);
+		assertSame(filter.getSession(),session);
+		assertSame(filter.getServer(),true);
+		assertEquals(filter.getCount(),4);
+		assertEquals(filter.getDelay(),15);
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void constructor2() throws Exception
+	{
+		transport.is_server = true;
+		String uri = "tcp://localhost:4801?filter=KeepAlive&KeepAlive.delay=20&KeepAlive.count=5";
+		KeepAlive filter = newKeepAlive(uri);
+		filter.setSession( session );
+		
+		assertSame(transport.getSession(),filter);
+		assertSame(filter.getSession(),session);
+		assertSame(filter.getServer(),true);
+		assertEquals(filter.getCount(),5);
+		assertEquals(filter.getDelay(),20);
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void constructor3() throws Exception
+	{
+		transport.is_server = false;
+		String uri = "tcp://localhost:4801?filter=KeepAlive";
+		KeepAlive filter = newKeepAlive(uri);
+		filter.setSession( session );
+		
+		assertSame(transport.getSession(),filter);
+		assertSame(filter.getSession(),session);
+		assertSame(filter.getServer(),false);
+		assertEquals(filter.getCount(),4);
+		assertEquals(filter.getDelay(),15);
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void clientup() throws Exception
+	{
+		transport.is_server = false;
+		String uri = "tcp://localhost:4801?filter=KeepAlive&KeepAlive.delay=3";
+		KeepAlive filter = newKeepAlive(uri);
+		filter.setSession( session );		
+		filter.sessionNotify( Session.UP );
+//		System.out.println("Sleeping for 5 seconds");
+		Thread.sleep( 5000 );		 
+//		System.out.println("Out of sleep");
+		assertSame( What.TRANSPORT_MESSAGE, transport.what );
+		Message msg = transport.msg;
+		assertEquals( "_Etch_KeepAliveReq", msg.type().getName() );
+		assertEquals( 4, msg.get( new Field( "count" ) ) );
+		assertEquals( 3, msg.get( new Field( "delay" ) ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void clientup1() throws Exception
+	{
+		transport.is_server = false;
+		String uri = "tcp://localhost:4801?filter=KeepAlive&KeepAlive.delay=2";
+		KeepAlive filter = newKeepAlive(uri);
+		filter.setSession( session );		
+		filter.sessionNotify( Session.UP );
+//		System.out.println("Sleeping for 4 seconds");
+		Thread.sleep( 4000 );		 
+//		System.out.println("Out of sleep");
+		assertSame( What.TRANSPORT_MESSAGE, transport.what );
+		Message msg = transport.msg;
+		assertEquals( "_Etch_KeepAliveReq", msg.type().getName() );
+		assertEquals( 4, msg.get( new Field( "count" ) ) );
+		assertEquals( 2, msg.get( new Field( "delay" ) ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void clientdown() throws Exception
+	{
+		Log.report( "--clientdown" );
+		
+		transport.is_server = false;
+		
+		String uri = "tcp://localhost:4801?filter=KeepAlive"; 
+		
+		KeepAlive filter = newKeepAlive(uri);
+		filter.setSession( session );		
+		filter.sessionNotify( Session.DOWN );
+		
+		assertFalse( session.up );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void serverUp() throws Exception
+	{
+		transport.is_server = true;
+		String uri = "tcp://localhost:4801?filter=KeepAlive"; 		
+		KeepAlive filter = newKeepAlive(uri);
+		filter.setSession( session );		
+		filter.sessionNotify( Session.UP );	
+		
+		Message req = constructMessage();
+		
+		filter.sessionMessage( null, req );
+		
+		assertEquals(req.reply(),transport.msg);
+		
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void serverdown() throws Exception
+	{
+		Log.report( "--clientdown" );
+		
+		transport.is_server = true;
+		
+		String uri = "tcp://localhost:4801?filter=KeepAlive"; 
+		
+		KeepAlive filter = newKeepAlive(uri);
+		filter.setSession( session );		
+		filter.sessionNotify( Session.DOWN );
+		
+		assertFalse( session.up );
+	}
+	
+/*	@Test
+	public void resetClient() throws Exception
+	{
+		transport.is_server = false;
+		String uri = "tcp://localhost:4801?filter=KeepAlive&KeepAlive.delay=2&KeepAlive.count=4"; 	
+		KeepAlive filter = newKeepAlive(uri);
+		filter.setSession( session );		
+		filter.sessionNotify( Session.UP );	
+		
+		System.out.println("Sleeping for 10 seconds");
+		Thread.sleep( 20000 );		 
+		System.out.println("Out of sleep");
+		assertTrue(transport.isReset);		
+	} */
+	
+	
+	private Message constructMessage() throws Exception
+	{
+		int delay = 15;
+		int count = 4;
+		
+		MyValueFactory vf1 = new MyValueFactory( "tcp:" );
+		
+		Field mf_delay = new Field( "delay" );
+		Field mf_count = new Field( "count" );
+		
+		Type mt_request = new Type( "_Etch_KeepAliveReq" );
+		mt_request.putValidator( mf_delay, Validator_int.get( 0 ) );
+		mt_request.putValidator( mf_count, Validator_int.get( 0 ) );
+		vf1.addType( mt_request );
+
+		Type mt_response = new Type( "_Etch_KeepAliveResp" );
+		vf1.addType( mt_response );
+		
+		mt_request.setResult( mt_response );
+		
+		Message msg = new Message( mt_request, vf1 );
+		msg.put( mf_delay, delay );
+		msg.put( mf_count, count );
+		
+		return msg;
+	}
+
+	
+	
+	
+	
+	
+	/** */
+	enum What
+	{
+		/** */ TRANSPORT_MESSAGE,
+		/** */ SESSION_MESSAGE
+	}
+	
+	/**
+	 * @param o
+	 * @return o
+	 * @throws Exception
+	 */
+	static Object cook( Object o ) throws Exception
+	{
+		if (o instanceof Exception)
+		{
+			Exception e = (Exception) o;
+			e.fillInStackTrace();
+			throw e;
+		}
+		return o;
+	}
+	
+	@SuppressWarnings("hiding")
+	private static class MyTransport implements TransportMessage
+	{
+		/** */
+		public MyTransport()
+		{
+			// nothing to do.
+		}
+
+		/** */ public What what;
+		/** */ public Who recipient;
+		/** */ public Message msg;
+		/** */ public Object is_server;
+		/** */ public boolean isReset = false;
+		
+		public void transportMessage( Who recipient, Message msg )
+			throws Exception
+		{
+			Log.report( "transportMessage", "recipient", recipient, "msg", msg );
+			what = What.TRANSPORT_MESSAGE;
+			this.recipient = recipient;
+			
+			this.msg = msg;
+		}
+
+		public SessionMessage getSession()
+		{
+			return session;
+		}
+
+		public void setSession( SessionMessage session )
+		{
+			this.session = session;
+		}
+		
+		private SessionMessage session;
+
+		public Object transportQuery( Object query ) throws Exception
+		{
+			Log.report( "transportQuery", "query", query );
+			
+			if (query == Transport.IS_SERVER)
+				return cook( is_server );
+			
+	//		return query;
+			throw new UnsupportedOperationException( "unknown query "+query );
+		}
+
+		public void transportControl( Object control, Object value )
+			throws Exception
+		{
+			Log.report( "transportControl1", "control", control, "value", value );
+			
+			if (control == Transport.RESET) {
+				Log.report("Control Variable is Reset, changing the reset flag",control);
+				isReset = true;
+			}
+			
+	//		throw new UnsupportedOperationException( "unknown control "+control );
+		}
+
+		public void transportNotify( Object event ) throws Exception
+		{
+			throw new UnsupportedOperationException( "unknown notify "+event );
+		}
+	}
+	
+	@SuppressWarnings("hiding")
+	private static class MySession implements SessionMessage
+	{
+		/** */
+		public MySession()
+		{
+			// nothing to do.
+		}
+
+		/** */ public What what;
+		/** */ public Who sender;
+		/** */ public Message msg;
+		/** */ public boolean handled;
+		/** */ public Object user;
+		/** */ public Object password;
+		/** */ public Boolean up;
+		
+		
+		public boolean sessionMessage( Who sender, Message msg )
+			throws Exception
+		{
+			Log.report( "sessionMessage", "sender", sender, "msg", msg );
+			what = What.SESSION_MESSAGE;
+			this.sender = sender;
+			this.msg = msg;
+			return handled;
+		}
+
+		public Object sessionQuery( Object query ) throws Exception
+		{
+			return query;
+		}
+
+		public void sessionControl( Object control, Object value )
+			throws Exception
+		{
+			Log.report( "sessionControl", "control", control, "value", value );
+			throw new UnsupportedOperationException( "unknown control "+control );
+		}
+
+		public void sessionNotify( Object event ) throws Exception
+		{
+			if (event == Session.UP)
+			{
+				up = true;
+				return;
+			}
+			
+			if (event == Session.DOWN)
+			{
+				up = false;
+				return;
+			}
+		}
+	}
+	
+	private static class MyValueFactory extends DefaultValueFactory
+	{
+		/** 
+		 * @param uri
+		 */		
+		public MyValueFactory( String uri )
+		{
+			super( uri, types, class2type );
+		}
+		
+		private final static TypeMap types = new TypeMap();
+		
+		private final static Class2TypeMap class2type = new Class2TypeMap();
+
+		static
+		{
+			DefaultValueFactory.init( types, class2type );
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/filters/TestLogger.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/filters/TestLogger.java
new file mode 100644
index 0000000..2d36262
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/filters/TestLogger.java
@@ -0,0 +1,276 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.filters;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.TypeMap;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.DefaultValueFactory;
+import org.apache.etch.bindings.java.transport.SessionMessage;
+import org.apache.etch.bindings.java.transport.TransportMessage;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.Session;
+import org.apache.etch.util.core.io.Transport;
+import org.junit.Test;
+
+
+/** */
+public class TestLogger
+{
+	
+	private final MyTransport transport = new MyTransport();
+	private final MySession session = new MySession();
+	private final MyValueFactory vf = new MyValueFactory("tcp:" );
+	private final Resources resources = new Resources();
+	{
+		resources.put( Transport.VALUE_FACTORY, vf );
+		Log.addSink( null );
+	}
+
+	
+	private Logger newLogger(String uri) throws Exception
+	{
+		return new Logger(transport,new URL(uri),null);
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void constructor1() throws Exception {
+		String uri = "tcp://localhost:4802?filter=Logger";
+		Logger.testFlag = true;
+		Logger logger = newLogger(uri);
+		assertEquals(logger.getFileName(),"Log.txt");
+		assertNotSame( logger.getFileName(),logger.getTestRenamedFileName());
+		
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void constructor2() throws Exception {
+		String uri = "tcp://localhost:4802?filter=Logger&Logger.filePath=Test.txt";
+		Logger.testFlag = true;
+		Logger logger = newLogger(uri);
+		assertEquals(logger.getFileName(),"Test.txt");
+		assertNotSame( logger.getFileName(),logger.getTestRenamedFileName());
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void logger() throws Exception {
+		String uri = "tcp://localhost:4802?filter=Logger";
+		Logger.testFlag = true;
+		Logger logger = newLogger(uri);
+		logger.setSession( session );
+		assertSame(transport.getSession(),logger);
+		assertSame(logger.getSession(),session);
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void logger1() throws Exception {
+		String uri = "tcp://localhost:4802?filter=Logger";
+		Logger.testFlag = true;
+		Logger logger = newLogger(uri);
+		logger.setSession( session );
+		assertSame(transport.getSession(),logger);
+		assertSame(logger.getSession(),session);
+		Message m = constructMessage();
+		logger.transportMessage( null, m );
+		assertEquals(m.toString(),transport.msg.toString());
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void logger2() throws Exception {
+		String uri = "tcp://localhost:4802?filter=Logger";
+		Logger.testFlag = true;
+		Logger logger = newLogger(uri);
+		logger.setSession( session );
+		assertSame(transport.getSession(),logger);
+		assertSame(logger.getSession(),session);
+		Message m = constructMessage();
+		logger.sessionMessage( null, m );
+		assertEquals(m.toString(),session.msg.toString());
+	}
+	
+	
+	
+	private Message constructMessage() throws Exception
+	{
+		
+		Type mt_request = new Type( "_Etch_Logger_Test" );
+		
+		
+		Type mt_response = new Type( "_Etch_Logger_Test_Resp" );
+			
+		mt_request.setResult( mt_response );
+		
+		vf.addType( mt_request);
+		
+		Message msg = new Message( mt_request, vf );
+	
+		return msg;
+	}
+
+	/** */
+	enum What
+	{
+		/** */ TRANSPORT_MESSAGE,
+		/** */ SESSION_MESSAGE
+	}
+
+	@SuppressWarnings("hiding")
+	private static class MyTransport implements TransportMessage
+	{
+		/** */
+		public MyTransport()
+		{
+			// nothing to do.
+		}
+
+		/** */ public What what;
+		/** */ public Who recipient;
+		/** */ public Message msg;
+		
+		public void transportMessage( Who recipient, Message msg )
+			throws Exception
+		{
+			Log.report( "transportMessage", "recipient", recipient, "msg", msg );
+			what = What.TRANSPORT_MESSAGE;
+			this.recipient = recipient;
+			
+			this.msg = msg;
+		}
+
+		public SessionMessage getSession()
+		{
+			return session;
+		}
+
+		public void setSession( SessionMessage session )
+		{
+			this.session = session;
+		}
+		
+		private SessionMessage session;
+
+		public Object transportQuery( Object query ) throws Exception
+		{
+			
+			throw new UnsupportedOperationException( "unknown query "+query );
+		}
+
+		public void transportControl( Object control, Object value )
+			throws Exception
+		{
+			
+			
+			throw new UnsupportedOperationException( "unknown control "+control );
+		}
+
+		public void transportNotify( Object event ) throws Exception
+		{
+			throw new UnsupportedOperationException( "unknown notify "+event );
+		}
+	}
+	
+	@SuppressWarnings("hiding")
+	private static class MySession implements SessionMessage
+	{
+		/** */
+		public MySession()
+		{
+			// nothing to do.
+		}
+
+		/** */ public What what;
+		/** */ public Who sender;
+		/** */ public Message msg;
+		/** */ public Boolean up;
+		
+		
+		public boolean sessionMessage( Who sender, Message msg )
+			throws Exception
+		{
+			Log.report( "sessionMessage", "sender", sender, "msg", msg );
+			what = What.SESSION_MESSAGE;
+			this.sender = sender;
+			this.msg = msg;
+			return true;
+		}
+
+		public Object sessionQuery( Object query ) throws Exception
+		{
+			return query;
+		}
+
+		public void sessionControl( Object control, Object value )
+			throws Exception
+		{
+			Log.report( "sessionControl", "control", control, "value", value );
+			throw new UnsupportedOperationException( "unknown control "+control );
+		}
+
+		public void sessionNotify( Object event ) throws Exception
+		{
+			if (event == Session.UP)
+			{
+				up = true;
+				return;
+			}
+			
+			if (event == Session.DOWN)
+			{
+				up = false;
+				return;
+			}
+		}
+	}
+	
+	private static class MyValueFactory extends DefaultValueFactory
+	{
+		/**
+		 * @param uri
+		 */
+		public MyValueFactory( String uri )
+		{
+			super( uri, types, class2type );
+		}
+		
+		private final static TypeMap types = new TypeMap();
+		
+		private final static Class2TypeMap class2type = new Class2TypeMap();
+
+		static
+		{
+			DefaultValueFactory.init( types, class2type );
+		}
+	}
+	
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/filters/TestPwAuth.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/filters/TestPwAuth.java
new file mode 100644
index 0000000..bd68ca3
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/filters/TestPwAuth.java
@@ -0,0 +1,529 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.filters;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.TypeMap;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.DefaultValueFactory;
+import org.apache.etch.bindings.java.transport.SessionMessage;
+import org.apache.etch.bindings.java.transport.TransportMessage;
+import org.apache.etch.bindings.java.transport.filters.PwAuth.UserPassword;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.Session;
+import org.apache.etch.util.core.io.Transport;
+import org.junit.Test;
+
+
+/** */
+public class TestPwAuth
+{
+	private final MyTransport transport = new MyTransport();
+	private final MySession session = new MySession();
+	private final MyValueFactory vf = new MyValueFactory( "tcp:" );
+	private final Resources resources = new Resources();
+	{
+		resources.put( Transport.VALUE_FACTORY, vf );
+		Log.addSink( null );
+	}
+	
+	private PwAuth newPwAuth( String uri ) throws Exception
+	{
+		return new PwAuth( transport, new URL( uri ), resources );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void constructor1() throws Exception
+	{
+		Log.report( "--constructor1" );
+		
+		transport.is_server = true;
+		
+		final PwAuth pwAuth = newPwAuth( "tcp://fred:1234@host:9999" );
+		pwAuth.setSession( session );
+		
+		assertSame( pwAuth, transport.getSession() );
+		assertSame( session, pwAuth.getSession() );
+		
+		assertEquals( true, pwAuth.getServer() );
+		assertNull( pwAuth.transportQuery( PwAuth.USER ) );
+		assertNull( pwAuth.transportQuery( PwAuth.PASSWORD ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void constructor2() throws Exception
+	{
+		Log.report( "--constructor2" );
+		
+		transport.is_server = false;
+		
+		final PwAuth pwAuth = newPwAuth( "tcp://fred:1234@host:9999" );
+		pwAuth.setSession( session );
+		
+		assertSame( pwAuth, transport.getSession() );
+		assertSame( session, pwAuth.getSession() );
+		
+		assertEquals( false, pwAuth.getServer() );
+		assertEquals( "fred", pwAuth.transportQuery( PwAuth.USER ) );
+		assertEquals( "1234", pwAuth.transportQuery( PwAuth.PASSWORD ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void constructor3() throws Exception
+	{
+		Log.report( "--constructor3" );
+		
+		transport.is_server = false;
+		
+		final PwAuth pwAuth = newPwAuth( "tcp://mary:2345@host:9999" );
+		pwAuth.setSession( session );
+		
+		assertSame( pwAuth, transport.getSession() );
+		assertSame( session, pwAuth.getSession() );
+		
+		assertEquals( false, pwAuth.getServer() );
+		assertEquals( "mary", pwAuth.transportQuery( PwAuth.USER ) );
+		assertEquals( "2345", pwAuth.transportQuery( PwAuth.PASSWORD ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void constructor4() throws Exception
+	{
+		Log.report( "--constructor4" );
+		
+		transport.is_server = false;
+		
+		final PwAuth pwAuth = newPwAuth( "tcp://alice@host:9999" );
+		pwAuth.setSession( session );
+		
+		assertSame( pwAuth, transport.getSession() );
+		assertSame( session, pwAuth.getSession() );
+		
+		assertEquals( false, pwAuth.getServer() );
+		assertEquals( "alice", pwAuth.transportQuery( PwAuth.USER ) );
+		assertNull( pwAuth.transportQuery( PwAuth.PASSWORD ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void constructor5() throws Exception
+	{
+		Log.report( "--constructor5" );
+		
+		transport.is_server = false; // IS_SERVER
+		
+		final PwAuth pwAuth = newPwAuth( "tcp://host:9999" );
+		pwAuth.setSession( session );
+		
+		assertSame( pwAuth, transport.getSession() );
+		assertSame( session, pwAuth.getSession() );
+		
+		assertEquals( false, pwAuth.getServer() );
+		assertNull( pwAuth.transportQuery( PwAuth.USER ) );
+		assertNull( pwAuth.transportQuery( PwAuth.PASSWORD ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = Exception.class )
+	public void constructor6() throws Exception
+	{
+		Log.report( "--constructor6" );
+		
+		transport.is_server = new Exception( "is_server failed" );
+		
+		newPwAuth( "tcp://fred:1234@host:9999" );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void clientup1() throws Exception
+	{
+		Log.report( "--clientup1" );
+		
+		transport.is_server = false; // IS_SERVER
+		
+		final PwAuth pwAuth = newPwAuth( "tcp://fred:1234@host:9999" );
+		pwAuth.setSession( session );
+		
+		pwAuth.sessionNotify( Session.UP );
+		
+		assertTrue( session.up );
+		
+		assertSame( What.TRANSPORT_MESSAGE, transport.what );
+		Message msg = transport.msg;
+		assertEquals( "_Etch_PwAuthReq", msg.type().getName() );
+		assertEquals( "fred", msg.get( new Field( "user" ) ) );
+		assertEquals( "1234", msg.get( new Field( "password" ) ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void clientup2() throws Exception
+	{
+		Log.report( "--clientup2" );
+		
+		transport.is_server = false;
+		session.password = "2345";
+		
+		final PwAuth pwAuth = newPwAuth( "tcp://fred@host:9999" );
+		pwAuth.setSession( session );
+		
+		pwAuth.sessionNotify( Session.UP );
+		
+		assertTrue( session.up );
+		
+		assertSame( What.TRANSPORT_MESSAGE, transport.what );
+		Message msg = transport.msg;
+		assertEquals( "_Etch_PwAuthReq", msg.type().getName() );
+		assertEquals( "fred", msg.get( new Field( "user" ) ) );
+		assertEquals( "2345", msg.get( new Field( "password" ) ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void clientup3() throws Exception
+	{
+		Log.report( "--clientup3" );
+		
+		transport.is_server = false;
+		session.user = "mary";
+		session.password = "3456";
+		
+		final PwAuth pwAuth = newPwAuth( "tcp://host:9999" );
+		pwAuth.setSession( session );
+		
+		pwAuth.sessionNotify( Session.UP );
+		
+		assertTrue( session.up );
+		
+		assertSame( What.TRANSPORT_MESSAGE, transport.what );
+		Message msg = transport.msg;
+		assertEquals( "_Etch_PwAuthReq", msg.type().getName() );
+		assertEquals( "mary", msg.get( new Field( "user" ) ) );
+		assertEquals( "3456", msg.get( new Field( "password" ) ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void clientup4() throws Exception
+	{
+		Log.report( "--clientup4" );
+		
+		transport.is_server = false;
+		// session.user = null;
+		session.password = "1234";
+		
+		final PwAuth pwAuth = newPwAuth( "tcp://host:9999" );
+		pwAuth.setSession( session );
+		
+		pwAuth.sessionNotify( Session.UP );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void clientup5() throws Exception
+	{
+		Log.report( "--clientup5" );
+		
+		transport.is_server = false;
+		session.user = "fred";
+//		session.password = null;
+		
+		final PwAuth pwAuth = newPwAuth( "tcp://host:9999" );
+		pwAuth.setSession( session );
+		
+		pwAuth.sessionNotify( Session.UP );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = Exception.class )
+	public void clientup6() throws Exception
+	{
+		Log.report( "--clientup6" );
+		
+		transport.is_server = false;
+		session.user = "fred";
+		session.password = new Exception( "password failed" );
+		
+		final PwAuth pwAuth = newPwAuth( "tcp://host:9999" );
+		pwAuth.setSession( session );
+		
+		pwAuth.sessionNotify( Session.UP );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = Exception.class )
+	public void clientup7() throws Exception
+	{
+		Log.report( "--clientup7" );
+		
+		transport.is_server = false;
+		session.user = new Exception( "user failed" );
+		session.password = "1234";
+		
+		final PwAuth pwAuth = newPwAuth( "tcp://host:9999" );
+		pwAuth.setSession( session );
+		
+		pwAuth.sessionNotify( Session.UP );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void clientdown1() throws Exception
+	{
+		Log.report( "--clientdown1" );
+		
+		transport.is_server = false;
+		
+		final PwAuth pwAuth = newPwAuth( "tcp://host:9999" );
+		pwAuth.setSession( session );
+		
+		pwAuth.sessionNotify( Session.DOWN );
+		
+		assertFalse( session.up );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void serverup1() throws Exception
+	{
+		Log.report( "--serverup1" );
+		
+		transport.is_server = true;
+		
+		final PwAuth pwAuth = newPwAuth( "tcp://host:9999" );
+		pwAuth.setSession( session );
+		
+		pwAuth.sessionNotify( Session.UP );
+		
+		assertTrue( session.up );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void serverdown1() throws Exception
+	{
+		Log.report( "--serverdown1" );
+		
+		transport.is_server = true;
+		
+		final PwAuth pwAuth = newPwAuth( "tcp://host:9999" );
+		pwAuth.setSession( session );
+		
+		pwAuth.sessionNotify( Session.DOWN );
+		
+		assertFalse( session.up );
+		assertNull( session.userPassword.user );
+		assertNull( session.userPassword.password );
+	}
+	
+	// sessionMessage, server, req
+	// sessionMessage, server, resp
+	// sessionMessage, client, req
+	// sessionMessage, client, resp
+	
+	/**
+	 * @param o
+	 * @return o
+	 * @throws Exception
+	 */
+	static Object cook( Object o ) throws Exception
+	{
+		if (o instanceof Exception)
+		{
+			Exception e = (Exception) o;
+			e.fillInStackTrace();
+			throw e;
+		}
+		return o;
+	}
+	
+	/** */
+	enum What
+	{
+		/** */ TRANSPORT_MESSAGE,
+		/** */ SESSION_MESSAGE
+	}
+	
+	@SuppressWarnings("hiding")
+	private static class MyTransport implements TransportMessage
+	{
+		/** */
+		public MyTransport()
+		{
+			// nothing to do.
+		}
+
+		/** */ public What what;
+		/** */ public Who recipient;
+		/** */ public Message msg;
+		/** */ public Object is_server;
+		
+		public void transportMessage( Who recipient, Message msg )
+			throws Exception
+		{
+			Log.report( "transportMessage", "recipient", recipient, "msg", msg );
+			what = What.TRANSPORT_MESSAGE;
+			this.recipient = recipient;
+			this.msg = msg;
+		}
+
+		public SessionMessage getSession()
+		{
+			return session;
+		}
+
+		public void setSession( SessionMessage session )
+		{
+			this.session = session;
+		}
+		
+		private SessionMessage session;
+
+		public Object transportQuery( Object query ) throws Exception
+		{
+			Log.report( "transportQuery", "query", query );
+			
+			if (query == Transport.IS_SERVER)
+				return cook( is_server );
+			
+			throw new UnsupportedOperationException( "unknown query "+query );
+		}
+
+		public void transportControl( Object control, Object value )
+			throws Exception
+		{
+			Log.report( "transportControl", "control", control, "value", value );
+			throw new UnsupportedOperationException( "unknown control "+control );
+		}
+
+		public void transportNotify( Object event ) throws Exception
+		{
+			throw new UnsupportedOperationException( "unknown notify "+event );
+		}
+	}
+	
+	@SuppressWarnings("hiding")
+	private static class MySession implements SessionMessage
+	{
+		/** */
+		public MySession()
+		{
+			// nothing to do.
+		}
+
+		/** */ public What what;
+		/** */ public Who sender;
+		/** */ public Message msg;
+		/** */ public boolean handled;
+		/** */ public Object user;
+		/** */ public Object password;
+		/** */ public Boolean up;
+		/** */ public UserPassword userPassword;
+		
+		public boolean sessionMessage( Who sender, Message msg )
+			throws Exception
+		{
+			Log.report( "sessionMessage", "sender", sender, "msg", msg );
+			what = What.SESSION_MESSAGE;
+			this.sender = sender;
+			this.msg = msg;
+			return handled;
+		}
+
+		public Object sessionQuery( Object query ) throws Exception
+		{
+			Log.report( "sessionQuery", "query", query );
+			
+			if (query == PwAuth.USER)
+				return cook( user );
+			
+			if (query == PwAuth.PASSWORD)
+				return cook( password );
+			
+			throw new UnsupportedOperationException( "unknown query "+query );
+		}
+
+		public void sessionControl( Object control, Object value )
+			throws Exception
+		{
+			Log.report( "sessionControl", "control", control, "value", value );
+			throw new UnsupportedOperationException( "unknown control "+control );
+		}
+
+		public void sessionNotify( Object event ) throws Exception
+		{
+			if (event == Session.UP)
+			{
+				up = true;
+				return;
+			}
+			
+			if (event == Session.DOWN)
+			{
+				up = false;
+				return;
+			}
+			
+			if (event instanceof UserPassword)
+			{
+				userPassword = (UserPassword) event;
+				return;
+			}
+			
+			throw new UnsupportedOperationException( "unknown notify "+event );
+		}
+	}
+	
+	private static class MyValueFactory extends DefaultValueFactory
+	{
+		/**
+		 * @param uri
+		 */
+		public MyValueFactory( String uri )
+		{
+			super( uri, types, class2type );
+		}
+		
+		private final static TypeMap types = new TypeMap();
+		
+		private final static Class2TypeMap class2type = new Class2TypeMap();
+
+		static
+		{
+			DefaultValueFactory.init( types, class2type );
+		}
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/fmt/binary/TestBinaryTaggedDataInOut.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/fmt/binary/TestBinaryTaggedDataInOut.java
new file mode 100644
index 0000000..484a90a
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/transport/fmt/binary/TestBinaryTaggedDataInOut.java
@@ -0,0 +1,908 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.transport.fmt.binary;
+
+import java.io.IOException;
+import java.lang.reflect.Array;
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.TypeMap;
+import org.apache.etch.bindings.java.msg.Validator;
+import org.apache.etch.bindings.java.msg.Validator.Level;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.DefaultValueFactory;
+import org.apache.etch.bindings.java.support.Validator_boolean;
+import org.apache.etch.bindings.java.support.Validator_byte;
+import org.apache.etch.bindings.java.support.Validator_double;
+import org.apache.etch.bindings.java.support.Validator_float;
+import org.apache.etch.bindings.java.support.Validator_int;
+import org.apache.etch.bindings.java.support.Validator_long;
+import org.apache.etch.bindings.java.support.Validator_object;
+import org.apache.etch.bindings.java.support.Validator_short;
+import org.apache.etch.bindings.java.support.Validator_string;
+import org.apache.etch.bindings.java.transport.Messagizer;
+import org.apache.etch.bindings.java.transport.fmt.TypeCode;
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.SessionPacket;
+import org.apache.etch.util.core.io.Transport;
+import org.apache.etch.util.core.io.TransportPacket;
+import org.junit.Assert;
+import org.junit.Test;
+
+
+/**
+ * Test binary input and output.
+ */
+public class TestBinaryTaggedDataInOut
+{
+	private static final double DOUBLE_MIN_NORMAL = 0x1.0p-1022; // Double.MIN_NORMAL;
+	private static final float FLOAT_MIN_NORMAL = 0x1.0p-126f; // Float.MIN_NORMAL;
+	
+	static
+	{
+		Log.addSink( null );
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test public void test_check_value() throws Exception
+	{
+		// i'm testing with hard coded constants on the left hand
+		// side here because this represents our external interface
+		// for messages. if these values change, it could bring about
+		// accidental missile launches, inadvertant bank balance transfers
+		// to unfriendly foreign nations, or the dropping of a small
+		// child's lollipop into the sand. like a pizza face down in
+		// the parking lot, you don't wanna go there.
+		
+//		ValueFactory vf = new DummyValueFactory();
+		BinaryTaggedDataOutput btdo = new BinaryTaggedDataOutput( vf, "none:" );
+		
+		// byte values
+		for (byte i: getBytes( Byte.MIN_VALUE, 256 ))
+			if (i >= TypeCode.MIN_TINY_INT && i <= TypeCode.MAX_TINY_INT)
+				Assert.assertEquals( i, btdo.checkValue( i ) );
+			else
+				Assert.assertEquals( TypeCode.BYTE, btdo.checkValue( i ) );
+		
+		// short values
+		for (short i: getShorts( Short.MIN_VALUE, 65536 ))
+			if (i >= TypeCode.MIN_TINY_INT && i <= TypeCode.MAX_TINY_INT)
+				Assert.assertEquals( (byte) i, btdo.checkValue( i ) );
+			else if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE)
+				Assert.assertEquals( TypeCode.BYTE, btdo.checkValue( i ) );
+			else
+				Assert.assertEquals( TypeCode.SHORT, btdo.checkValue( i ) );
+		
+		// int values
+		for (int i: getTestInts())
+			if (i >= TypeCode.MIN_TINY_INT && i <= TypeCode.MAX_TINY_INT)
+				Assert.assertEquals( (byte) i, btdo.checkValue( i ) );
+			else if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE)
+				Assert.assertEquals( TypeCode.BYTE, btdo.checkValue( i ) );
+			else if (i >= Short.MIN_VALUE && i <= Short.MAX_VALUE)
+				Assert.assertEquals( TypeCode.SHORT, btdo.checkValue( i ) );
+			else
+				Assert.assertEquals( TypeCode.INT, btdo.checkValue( i ) );
+		
+		// long values
+		for (long i: getTestLongs())
+			if (i >= TypeCode.MIN_TINY_INT && i <= TypeCode.MAX_TINY_INT)
+				Assert.assertEquals( (byte) i, btdo.checkValue( i ) );
+			else if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE)
+				Assert.assertEquals( TypeCode.BYTE, btdo.checkValue( i ) );
+			else if (i >= Short.MIN_VALUE && i <= Short.MAX_VALUE)
+				Assert.assertEquals( TypeCode.SHORT, btdo.checkValue( i ) );
+			else if (i >= Integer.MIN_VALUE && i <= Integer.MAX_VALUE)
+				Assert.assertEquals( TypeCode.INT, btdo.checkValue( i ) );
+			else
+				Assert.assertEquals( TypeCode.LONG, btdo.checkValue( i ) );
+		
+		// null value
+		Assert.assertEquals( TypeCode.NULL, btdo.checkValue( null ) );
+		
+		// boolean values
+		Assert.assertEquals( TypeCode.BOOLEAN_FALSE, btdo.checkValue( false ) );
+		Assert.assertEquals( TypeCode.BOOLEAN_TRUE, btdo.checkValue( true ) );
+		
+		// float
+		Assert.assertEquals( TypeCode.FLOAT, btdo.checkValue( 3.14159f ) );
+		
+		// double
+		Assert.assertEquals( TypeCode.DOUBLE, btdo.checkValue( 3.14159 ) );
+		
+		// byte array
+		Assert.assertEquals( TypeCode.BYTES, btdo.checkValue( new byte[0] ) );
+		Assert.assertEquals( TypeCode.BYTES, btdo.checkValue( new byte[1] ) );
+		
+		// string
+		Assert.assertEquals( TypeCode.EMPTY_STRING, btdo.checkValue( "" ) );
+		Assert.assertEquals( TypeCode.STRING, btdo.checkValue( "abc" ) );
+		
+		// struct
+		Assert.assertEquals( TypeCode.CUSTOM, btdo.checkValue( new StructValue( new Type( "foo" ), vf ) ) );
+		
+		// custom
+		Assert.assertEquals( TypeCode.CUSTOM, btdo.checkValue( new Date() ) );
+		
+		// none
+		Assert.assertEquals( TypeCode.NONE, btdo.checkValue( BinaryTaggedData.NONE ) );
+	}
+	
+	private long[] getTestLongs()
+	{
+		int n = 65536+2+6;
+		int k = 65536+2;
+		int min = Short.MIN_VALUE-1;
+		long[] vals = new long[n];
+		int i = 0;
+		while (k-- > 0)
+			vals[i++] = min++;
+		vals[i++] = Integer.MIN_VALUE;
+		vals[i++] = Integer.MAX_VALUE;
+		vals[i++] = Integer.MIN_VALUE-1L;
+		vals[i++] = Integer.MAX_VALUE+1L;
+		vals[i++] = Long.MIN_VALUE;
+		vals[i++] = Long.MAX_VALUE;
+		return vals;
+	}
+
+	private int[] getTestInts()
+	{
+		int n = 65536+2+2;
+		int k = 65536+2;
+		int min = Short.MIN_VALUE-1;
+		int[] vals = new int[n];
+		int i = 0;
+		while (k-- > 0)
+			vals[i++] = min++;
+		vals[i++] = Integer.MIN_VALUE;
+		vals[i++] = Integer.MAX_VALUE;
+		return vals;
+	}
+
+	private short[] getShorts( short min, int n )
+	{
+		short[] vals = new short[n];
+		int i = 0;
+		while (n-- > 0)
+			vals[i++] = min++;
+		return vals;
+	}
+
+	private byte[] getBytes( byte min, int n )
+	{
+		byte[] vals = new byte[n];
+		int i = 0;
+		while (n-- > 0)
+			vals[i++] = min++;
+		return vals;
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	@Test public void test_boolean() throws Exception
+	{
+		testx( new boolean[][] { { false, true }, { true, false } },
+			Validator_boolean.get( 2 ) );
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test public void test_byte() throws Exception
+	{
+		testx( new byte[][] { { Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE }, { 23 } },
+			Validator_byte.get( 2 ) );
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test public void test_short() throws Exception
+	{
+		testx( new short[][] { { Short.MIN_VALUE, Byte.MIN_VALUE, -1, 0, 1,
+			Byte.MAX_VALUE, Short.MAX_VALUE }, { 23 } },
+			Validator_short.get( 2 ) );
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test public void test_int() throws Exception
+	{
+		testx( new int[][] { { Integer.MIN_VALUE, Short.MIN_VALUE, Byte.MIN_VALUE,
+			-1, 0, 1, Byte.MAX_VALUE, Short.MAX_VALUE, Integer.MAX_VALUE }, { 23 } },
+			Validator_int.get( 2 ) );
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test public void test_long() throws Exception
+	{
+		testx( new long[][] { { Long.MIN_VALUE, Integer.MIN_VALUE, Short.MIN_VALUE,
+			Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE, Short.MAX_VALUE,
+			Integer.MAX_VALUE, Long.MAX_VALUE }, { 23 } },
+			Validator_long.get( 2 ) );
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test public void test_float() throws Exception
+	{
+		testx( new float[][] { { -1, 0, 1, Float.MIN_VALUE, FLOAT_MIN_NORMAL,
+			Float.MAX_VALUE, Float.NaN, Float.NEGATIVE_INFINITY,
+			Float.POSITIVE_INFINITY, -0.0f, 1.1f,
+			3.141592653589793238462643383279f }, { 23 } },
+			Validator_float.get( 2 ) );
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test public void test_double() throws Exception
+	{
+		testx( new double[][] { { -1, 0, 1, Double.MIN_VALUE, DOUBLE_MIN_NORMAL,
+			Double.MAX_VALUE, Double.NaN, Double.NEGATIVE_INFINITY,
+			Double.POSITIVE_INFINITY, -0.0f, 1.1f,
+			3.141592653589793238462643383279 }, { 23 } },
+			Validator_double.get( 2 ) );
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test public void test_String() throws Exception
+	{
+		testx( new String[][] { { "", "a", "ab", "abc" }, { "23" } },
+			Validator_string.get( 2 ) );
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test public void test_add() throws Exception
+	{
+		Type add = vf.getType( "add" );
+		
+		Field x = new Field( "x" );
+		add.putValidator( x, Validator_int.get( 0 ) );
+		
+		Field y = new Field( "y" );
+		add.putValidator( y, Validator_int.get( 0 ) );
+		
+		Field _mf__messageId = DefaultValueFactory._mf__messageId;
+		add.putValidator( _mf__messageId, Validator_long.get( 0 ) );
+		
+		long msgid = 0x0102030405060708L;
+		
+//		System.out.printf( "add.id() = %04x\n", add.getId() );
+//		System.out.printf( "x.id() = %04x\n", x.getId() );
+//		System.out.printf( "y.id() = %04x\n", y.getId() );
+//		System.out.printf( "_mf__messageId.id() = %04x\n", _mf__messageId.getId() );
+//		System.out.printf( "msgid = %08x\n", msgid );
+		
+		Message msg = new Message( add, vf );
+		msg.put( x, 1 );
+		msg.put( y, 2 );
+		msg.put( _mf__messageId, msgid );
+		testmsg2bytes( msg, null,  new byte[] { 3, -122, 39, -23, -73, -100, 3, -122, 21, 10, 44, -77, 1, -122, 99, 6, -76, 104, -121, 1, 2, 3, 4, 5, 6, 7, 8, -122, 21, 10, 44, -76, 2, -127 } );
+		testmsg2bytes( msg, false, new byte[] { 3, -122, 39, -23, -73, -100, 3, -122, 21, 10, 44, -77, 1, -122, 99, 6, -76, 104, -121, 1, 2, 3, 4, 5, 6, 7, 8, -122, 21, 10, 44, -76, 2, -127 } );
+		testmsg2bytes( msg, true,  new byte[] { 3, -109, 3, 97, 100, 100, 3, -109, 1, 120, 1, -109, 10, 95, 109, 101, 115, 115, 97, 103, 101, 73, 100, -121, 1, 2, 3, 4, 5, 6, 7, 8, -109, 1, 121, 2, -127 } );
+		
+		msg = new Message( add, vf );
+		msg.put( x, 1000000000 );
+		msg.put( y, 2000000000 );
+		msg.put( _mf__messageId, msgid );
+		testmsg2bytes( msg, null,  new byte[] { 3, -122, 39, -23, -73, -100, 3, -122, 21, 10, 44, -77, -122, 59, -102, -54, 0, -122, 99, 6, -76, 104, -121, 1, 2, 3, 4, 5, 6, 7, 8, -122, 21, 10, 44, -76, -122, 119, 53, -108, 0, -127 } );
+		testmsg2bytes( msg, false, new byte[] { 3, -122, 39, -23, -73, -100, 3, -122, 21, 10, 44, -77, -122, 59, -102, -54, 0, -122, 99, 6, -76, 104, -121, 1, 2, 3, 4, 5, 6, 7, 8, -122, 21, 10, 44, -76, -122, 119, 53, -108, 0, -127 } );
+		testmsg2bytes( msg, true,  new byte[] { 3, -109, 3, 97, 100, 100, 3, -109, 1, 120, -122, 59, -102, -54, 0, -109, 10, 95, 109, 101, 115, 115, 97, 103, 101, 73, 100, -121, 1, 2, 3, 4, 5, 6, 7, 8, -109, 1, 121, -122, 119, 53, -108, 0, -127 } );
+	}
+	
+	private void testmsg2bytes( Message msg, Boolean stringTypeAndField,
+		byte[] expected ) throws Exception
+	{
+		byte[] actual = msg2bytes( msg, stringTypeAndField );
+		try
+		{
+			assertArrayEquals( expected, actual );
+		}
+		catch ( AssertionError e )
+		{
+			dump( expected );
+			dump( actual );
+			throw e;
+		}
+	}
+
+	/** Tests reading a pre-canned add message.
+	 * @throws Exception */
+	@Test public void test_add_in() throws Exception
+	{
+		Type add = vf.getType( "add" );
+		
+		Field x = new Field( "x" );
+		add.putValidator( x, Validator_int.get( 0 ) );
+		
+		Field y = new Field( "y" );
+		add.putValidator( y, Validator_int.get( 0 ) );
+		
+		Field _mf__messageId = DefaultValueFactory._mf__messageId;
+		add.putValidator( _mf__messageId, Validator_long.get( 0 ) );
+		
+		long msgid = 0x0123456789abcdefL;
+
+		byte[] buf =
+		{
+			3, // version
+			-122, // INT (type)
+			39, -23, -73, -100, // add
+			3, // length
+			-122, // INT (key)
+			99, 6, -76, 104,
+			-121, // LONG (value)
+			1, 35, 69, 103, -119, -85, -51, -17,
+			-122, // INT (key)
+			21, 10, 44, -76, // y
+			2, // tiny int = 2 (value)
+			-122, // INT (key)
+			21, 10, 44, -77, // x
+			1, // tiny int = 1 (value)
+			-127 // NONE
+		};
+		Message msg = bytes2msg( buf );
+		msg.checkType( add );
+		Assert.assertEquals( 3, msg.size() );
+		Assert.assertEquals( 1, msg.get( x ) );
+		Assert.assertEquals( 2, msg.get( y ) );
+		Assert.assertEquals( msgid, msg.get( _mf__messageId ) );
+		
+		buf = new byte[]
+		{
+			3, // version
+			-122, // INT (type)
+			39, -23, -73, -100, // add
+			3, // length
+			-122, // INT (key)
+			99, 6, -76, 104,
+			-121, // LONG (value)
+			1, 35, 69, 103, -119, -85, -51, -17,
+			-122, // INT (key)
+			21, 10, 44, -76, // y
+			-122, // INT (value)
+			119, 53, -108, 0,
+			-122, // INT (key)
+			21, 10, 44, -77, // x
+			-122, // INT (value)
+			59, -102, -54, 0,
+			-127 // NONE
+		};
+		msg = bytes2msg( buf );
+		msg.checkType( add );
+		Assert.assertEquals( 3, msg.size() );
+		Assert.assertEquals( 1000000000, msg.get( x ) );
+		Assert.assertEquals( 2000000000, msg.get( y ) );
+		Assert.assertEquals( msgid, msg.get( _mf__messageId ) );
+	}
+
+	/** Tests add performance.
+	 * @throws Exception */
+	@Test public void test_add_perf() throws Exception
+	{
+		Type add = vf.getType( "add" );
+		
+		Field x = new Field( "x" );
+		add.putValidator( x, Validator_int.get( 0 ) );
+		
+		Field y = new Field( "y" );
+		add.putValidator( y, Validator_int.get( 0 ) );
+		
+		Field _mf__messageId = DefaultValueFactory._mf__messageId;
+		add.putValidator( _mf__messageId, Validator_long.get( 0 ) );
+		
+		long msgid = 0x0123456789abcdefL;
+		
+//		System.out.printf( "add.id() = %04x\n", add.getId() );
+//		System.out.printf( "x.id() = %04x\n", x.getId() );
+//		System.out.printf( "y.id() = %04x\n", y.getId() );
+//		System.out.printf( "_mf__messageId.id() = %04x\n", _mf__messageId.getId() );
+//		System.out.printf( "msgid = %08x\n", msgid );
+		
+		Message msg = new Message( add, vf );
+		msg.put( x, 123456789 );
+		msg.put( y, 876543210 );
+		msg.put( _mf__messageId, msgid );
+//		System.out.println( "msg = "+msg );
+		
+		Resources res = new Resources();
+		res.put( Transport.VALUE_FACTORY, vf );
+		MyPacketSource ps = new MyPacketSource();
+		Messagizer m = new Messagizer( ps, "foo:?Messagizer.format=binary", res );
+		m.transportMessage( null, msg );
+		
+		int n = 900973;
+		for (int i = 0; i < 3; i++)
+			testPerf( "test_add_perf", i, m, msg, n );
+	}
+	
+	/** Tests sum performance.
+	 * @throws Exception */
+	@Test public void test_sum_perf() throws Exception
+	{
+		Type sum = vf.getType( "sum" );
+		
+		Field values = new Field( "values" );
+		sum.putValidator( values, Validator_int.get( 1 ) );
+		
+		Field _mf__messageId = DefaultValueFactory._mf__messageId;
+		sum.putValidator( _mf__messageId, Validator_long.get( 0 ) );
+		
+		long msgid = 0x0123456789abcdefL;
+		
+//		System.out.printf( "add.id() = %04x\n", add.getId() );
+//		System.out.printf( "x.id() = %04x\n", x.getId() );
+//		System.out.printf( "y.id() = %04x\n", y.getId() );
+//		System.out.printf( "_mf__messageId.id() = %04x\n", _mf__messageId.getId() );
+//		System.out.printf( "msgid = %08x\n", msgid );
+		
+		int[] array = new int[2];
+		for (int i = 0; i < array.length; i++)
+			array[i] = 123456789;
+		
+		Message msg = new Message( sum, vf );
+		msg.put( values, array );
+		msg.put( _mf__messageId, msgid );
+//		System.out.println( "msg = "+msg );
+		
+		Resources res = new Resources();
+		res.put( Transport.VALUE_FACTORY, vf );
+		MyPacketSource ps = new MyPacketSource();
+		Messagizer m = new Messagizer( ps, "foo:?Messagizer.format=binary", res );
+		m.transportMessage( null, msg );
+		
+		int n = 509520;
+		for (int i = 0; i < 3; i++)
+			testPerf( "test_sum_perf", i, m, msg, n );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void testValueToBytes() throws Exception
+	{
+		// nulls
+		
+		assertValueToBytes( null,
+			new byte[] { 3, 1, 0, -127 } );
+		
+		assertValueToBytes( new Object[] { null },
+			new byte[] { 3, 1, 1, 2, -111, -106, 1, 1, -128, -127, -127 } );
+		
+		// booleans:
+		
+		assertValueToBytes( false,
+			new byte[] { 3, 1, 1, 2, -126, -127 } );
+		
+		assertValueToBytes( true,
+			new byte[] { 3, 1, 1, 2, -125, -127 } );
+		
+		// tiny ints:
+		
+		assertValueToBytes( 0,
+			new byte[] { 3, 1, 1, 2, 0, -127 } );
+		
+		assertValueToBytes( 1,
+			new byte[] { 3, 1, 1, 2, 1, -127 } );
+		
+		assertValueToBytes( -1,
+			new byte[] { 3, 1, 1, 2, -1, -127 } );
+		
+		// bytes:
+		
+		assertValueToBytes( -100,
+			new byte[] { 3, 1, 1, 2, -124, -100, -127 } );
+		
+		// shorts:
+		
+		assertValueToBytes( 10000,
+			new byte[] { 3, 1, 1, 2, -123, 39, 16, -127 } );
+		
+		assertValueToBytes( -10000,
+			new byte[] { 3, 1, 1, 2, -123, -40, -16, -127 } );
+		
+		// ints:
+		
+		assertValueToBytes( 1000000000,
+			new byte[] { 3, 1, 1, 2, -122, 59, -102, -54, 0, -127 } );
+		
+		assertValueToBytes( -1000000000,
+			new byte[] { 3, 1, 1, 2, -122, -60, 101, 54, 0, -127 } );
+		
+		// longs:
+		
+		assertValueToBytes( 1000000000000000000L,
+			new byte[] { 3, 1, 1, 2, -121, 13, -32, -74, -77, -89, 100, 0, 0, -127 } );
+		
+		assertValueToBytes( -1000000000000000000L,
+			new byte[] { 3, 1, 1, 2, -121, -14, 31, 73, 76, 88, -100, 0, 0, -127 } );
+		
+		// float:
+		
+		assertValueToBytes( 12345f,
+			new byte[] { 3, 1, 1, 2, -120, 70, 64, -28, 0, -127 } );
+		
+		// double:
+		
+		assertValueToBytes( 23456d,
+			new byte[] { 3, 1, 1, 2, -119, 64, -42, -24, 0, 0, 0, 0, 0, -127 } );
+		
+		// boolean[]:
+		
+		assertValueToBytes( new boolean[] { true, false },
+			new byte[] { 3, 1, 1, 2, -111, -125, 1, 2, -125, -126, -127, -127 } );
+		
+		// byte[]:
+		
+		assertValueToBytes( new byte[] { 1, 2, 3 },
+			new byte[] { 3, 1, 1, 2, -117, 3, 1, 2, 3, -127 } );
+
+		// byte[][]:
+		
+		assertValueToBytes( new byte[][] { new byte[] { 1, 2, 3 }, new byte[] { 2, 3, 4 } },
+			new byte[] { 3, 1, 1, 2, -111, -124, 2, 2, -117, 3, 1, 2, 3, -117, 3, 2, 3, 4, -127, -127 } );
+
+		// short[]:
+		
+		assertValueToBytes( new short[] { 1, 2, 3 },
+			new byte[] { 3, 1, 1, 2, -111, -123, 1, 3, 1, 2, 3, -127, -127 } );
+
+		// int[]:
+		
+		assertValueToBytes( new int[] { 1, 2, 3 },
+			new byte[] { 3, 1, 1, 2, -111, -122, 1, 3, 1, 2, 3, -127, -127 } );
+
+		// long[]:
+		
+		assertValueToBytes( new long[] { 1, 2, 3 },
+			new byte[] { 3, 1, 1, 2, -111, -121, 1, 3, 1, 2, 3, -127, -127 } );
+
+		// float[]:
+		
+		assertValueToBytes( new float[] { 1, 2, 3 },
+			new byte[] { 3, 1, 1, 2, -111, -120, 1, 3, -120, 63, -128, 0, 0, -120, 64, 0, 0, 0, -120, 64, 64, 0, 0, -127, -127 } );
+
+		// double[]:
+		
+		assertValueToBytes( new double[] { 1, 2, 3 },
+			new byte[] { 3, 1, 1, 2, -111, -119, 1, 3, -119, 63, -16, 0, 0, 0, 0, 0, 0, -119, 64, 0, 0, 0, 0, 0, 0, 0, -119, 64, 8, 0, 0, 0, 0, 0, 0, -127, -127 } );
+
+		// empty string:
+		
+		assertValueToBytes( "",
+			new byte[] { 3, 1, 1, 2, -110, -127 } );
+		
+		// string:
+		
+		assertValueToBytes( "abc",
+			new byte[] { 3, 1, 1, 2, -109, 3, 97, 98, 99, -127 } );
+		
+		// string[]:
+		
+		assertValueToBytes( new String[] { "a", "", "c" },
+			new byte[] { 3, 1, 1, 2, -111, -109, 1, 3, -109, 1, 97, -110, -109, 1, 99, -127, -127 } );
+
+		// Date:
+		
+		assertValueToBytes( new Date( 1234567890L ),
+			new byte[] { 3, 1, 1, 2, -107, -122, 43, 57, 107, -52, 1, -122, 102, 0, 26, 64, -122, 73, -106, 2, -46, -127, -127 } );
+
+		// Date[]:
+		
+		assertValueToBytes( new Date[] { new Date( 1234567890L ), new Date( 2345678901L ) },
+			new byte[] { 3, 1, 1, 2, -111, -107, -122, 43, 57, 107, -52, 1, 2, -107, -122, 43, 57, 107, -52, 1, -122, 102, 0, 26, 64, -122, 73, -106, 2, -46, -127, -107, -122, 43, 57, 107, -52, 1, -122, 102, 0, 26, 64, -121, 0, 0, 0, 0, -117, -48, 56, 53, -127, -127, -127 } );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void badtype() throws Exception
+	{
+		@SuppressWarnings("unused")
+		Message msg = bytes2msg( new byte[] { 3, 1, 0, -127 } );
+//		System.out.println( "msg = "+msg );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void badmsglen1() throws Exception
+	{
+		@SuppressWarnings("unused")
+		Message msg = bytes2msg( new byte[] { 3, 1, -1, -127 } );
+//		System.out.println( "msg = "+msg );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void badmsglen2() throws Exception
+	{
+		@SuppressWarnings("unused")
+		Message msg = bytes2msg( new byte[] { 3, 1, 99, -127 } );
+//		System.out.println( "msg = "+msg );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void badfield() throws Exception
+	{
+		@SuppressWarnings("unused")
+		Message msg = bytes2msg( new byte[] { 3, 1, 1, 2, 2, -127 }, Level.MISSING_OK );
+//		System.out.println( "msg = "+msg );
+	}
+	
+	private void assertValueToBytes( Object value, byte[] expectedBytes ) throws Exception
+	{
+		Type t = new Type( 1, "a" );
+		Field f = new Field( 2, "b" );
+		t.putValidator( f, Validator_object.get( 0 ) );
+		
+		Message msg = new Message( t, vf );
+		msg.put( f, value );
+//		System.out.println( "msg = "+msg );
+		
+		BinaryTaggedDataOutput btdo = new BinaryTaggedDataOutput( vf, "none:" );
+		FlexBuffer buf = new FlexBuffer();
+		
+		btdo.writeMessage( msg, buf );
+		
+		buf.setIndex( 0 );
+		byte[] b = buf.getAvailBytes();
+//		dump( b );
+		assertArrayEquals( expectedBytes, b );
+	}
+	
+	private final static void testPerf( String name, int iter, Messagizer m,
+		Message msg, int n ) throws Exception
+	{
+		long t0 = System.nanoTime();
+		
+		for (int i = 0; i < n; i++)
+			m.transportMessage( null, msg );
+		
+		long t1 = System.nanoTime();
+		double t = (t1-t0) / 1000000000.0;
+		double r = n / t;
+		Log.report( name, "iteration", iter, "time", t, "count", n, "rate", r );
+	}
+	
+	/**
+	 * Test jig for perf tests.
+	 */
+	public static class MyPacketSource implements TransportPacket
+	{
+		public int headerSize()
+        {
+	        return 0;
+        }
+
+		public void transportPacket( Who recipient, FlexBuffer buf ) throws Exception
+        {
+	        // ignore.
+//			System.out.println( buf.avail() );
+        }
+
+		public SessionPacket getSession()
+		{
+			// ignore
+			return null;
+		}
+
+		public void setSession( SessionPacket session )
+		{
+			// ignore
+		}
+
+		public void transportControl( Object control, Object value )
+			throws Exception
+		{
+			// ignore
+		}
+
+		public void transportNotify( Object event ) throws Exception
+		{
+			// ignore
+		}
+
+		public Object transportQuery( Object query ) throws Exception
+		{
+			// ignore
+			return null;
+		}
+	}
+	
+	private byte[] msg2bytes( Message msg, Boolean stringTypeAndField ) throws IOException
+	{
+		FlexBuffer buf = new FlexBuffer();
+		
+		URL u = new URL( "none:" );
+		if (stringTypeAndField != null)
+			u.addTerm( BinaryTaggedDataOutput.STRING_TYPE_AND_FIELD, stringTypeAndField );
+		
+		BinaryTaggedDataOutput btdo = new BinaryTaggedDataOutput( vf, u.toString() );
+		btdo.writeMessage( msg, buf );
+		buf.setIndex( 0 );
+		return buf.getAvailBytes();
+	}
+	
+	private Message bytes2msg( byte[] buf ) throws Exception
+	{
+		return bytes2msg( buf, Level.FULL );
+	}
+	
+	private Message bytes2msg( byte[] buf, Level level ) throws Exception
+	{
+		Level oldLevel = vf.setLevel( level );
+		try
+		{
+			BinaryTaggedDataInput btdi = new BinaryTaggedDataInput( vf, "none:" );
+			return btdi.readMessage( new FlexBuffer( buf ) );
+		}
+		finally
+		{
+			vf.setLevel( oldLevel );
+		}
+	}
+	
+	private void testx( Object x, Validator v )
+		throws Exception
+	{
+		Class<?> c = x.getClass();
+		if (c.isArray())
+		{
+			int n = Array.getLength( x );
+			for (int i = 0; i < n; i++)
+			{
+				testx( Array.get( x, i ), v.elementValidator() );
+			}
+		}
+		test( x, v, null );
+		test( x, v, false );
+		test( x, v, true );
+	}
+	
+	/**
+	 * value factory for tests. it is ok that it is shared between tests.
+	 */
+	
+	final DefaultValueFactory vf = new MyValueFactory( "tcp:" );
+	
+	private final Type mt_foo = vf.getType( "foo" );
+	
+	private final Field mf_x = new Field( "x" );
+	
+	private void test( Object x, Validator v, Boolean stringTypeAndField ) throws Exception
+	{
+//		System.out.println( "-----------------------------------------" );
+		
+		mt_foo.clearValidator( mf_x );
+		mt_foo.putValidator( mf_x, v );
+		
+		Message msg = new Message( mt_foo, vf );
+		msg.put( mf_x, x );
+//		System.out.println( "msg = "+msg );
+		
+		byte[] bufx = msg2bytes( msg, stringTypeAndField );
+//		dump( bufx );
+		Message msg2 = bytes2msg( bufx );
+		
+//		System.out.println( "msg2 = "+msg2 );
+		msg2.checkType( mt_foo );
+		Assert.assertEquals( 1, msg2.size() );
+		Assert.assertTrue( msg.containsKey( mf_x ) );
+		Object y = msg2.get( mf_x );
+		
+		assertEquals( x, y );
+	}
+	
+	@SuppressWarnings("unused")
+	private void dump( byte[] buf )
+	{
+		System.out.print( "byte[/*"+buf.length+"*/] buf = {" );
+		for (int i = 0; i < buf.length; i++)
+		{
+			if (i > 0)
+				System.out.print( ", " );
+			else
+				System.out.print( " " );
+			System.out.printf( "%d", buf[i] );
+		}
+		System.out.println( " }" );
+	}
+
+	private void assertEquals( Object a, Object b )
+	{
+		if (a == null || b == null)
+		{
+			Assert.assertEquals( a, b );
+			return;
+		}
+		
+		Class<?> aClass = a.getClass();
+		Class<?> bClass = b.getClass();
+		
+		if (aClass == bClass)
+		{
+			if (aClass.isArray() && bClass.isArray())
+				assertArrayEquals( a, b );
+			else
+				Assert.assertEquals( a, b );
+		}
+		//else if (a instanceof Number && b instanceof Number)
+		else
+		{
+//			System.out.printf( "a %s, b %s\n", aClass, bClass );
+			Assert.assertEquals( a, b );
+		}
+	}
+
+	private void assertArrayEquals( Object a, Object b )
+	{
+		int an = Array.getLength( a );
+		int bn = Array.getLength( b );
+		
+		assertEquals( an, bn );
+		
+		for (int i = 0; i < an; i++)
+			assertEquals( Array.get( a, i ), Array.get( b, i ) );
+	}
+	
+	/** */
+	static class MyValueFactory extends DefaultValueFactory
+	{
+		private final static TypeMap types = new TypeMap();
+		
+		private final static Class2TypeMap class2type = new Class2TypeMap();
+
+		static
+		{
+			DefaultValueFactory.init( types, class2type );
+		}
+
+		/**
+		 * Constructs the MyValueFactory.
+		 * @param uri
+		 */
+		public MyValueFactory( String uri )
+		{
+			super( uri, types, class2type );
+		}
+	}
+
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/util/TestDateSerializer.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/util/TestDateSerializer.java
new file mode 100644
index 0000000..d5736d3
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/util/TestDateSerializer.java
@@ -0,0 +1,68 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.util;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Date;
+
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.DummyValueFactory;
+import org.junit.Test;
+
+
+/** Tests DateSerializer */
+public class TestDateSerializer
+{
+	/** @throws Exception */
+	@Test
+	public void testImport() throws Exception
+	{
+		Date date = new Date();
+		testDate( date );
+	}
+	
+	private void testDate( Date date )
+	{
+//		System.out.println( "---------------------------------------------" );
+//		System.out.println( "date = "+date );
+		
+		ValueFactory vf = new DummyValueFactory();
+		Type type = new Type( "date" );
+		Class2TypeMap class2type = new Class2TypeMap();
+		DateSerializer.init( type, class2type );
+		ImportExportHelper helper = type.getImportExportHelper();
+		
+		StructValue sv = helper.exportValue( vf, date );
+//		System.out.println( "sv = "+sv );
+		
+		assertEquals( sv.type(), type );
+		
+		Date date2 = (Date) helper.importValue( sv );
+//		System.out.println( "date2 = "+date2 );
+		
+		assertEquals( date, date2 );
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/util/TestStrIntHashMapSerializer.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/util/TestStrIntHashMapSerializer.java
new file mode 100644
index 0000000..9da5dc7
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/util/TestStrIntHashMapSerializer.java
@@ -0,0 +1,130 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.util;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.DummyValueFactory;
+import org.junit.Test;
+
+
+/** Tests StrIntHashMapSerializer */
+public class TestStrIntHashMapSerializer
+{
+	private final ValueFactory vf = new DummyValueFactory();
+	
+	/** @throws Exception */
+	@Test
+	public void test0() throws Exception
+	{
+		StrIntHashMap map = new StrIntHashMap();
+		testMap( map );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test1() throws Exception
+	{
+		StrIntHashMap map = new StrIntHashMap();
+		map.put( "a", 1 );
+		testMap( map );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test2() throws Exception
+	{
+		StrIntHashMap map = new StrIntHashMap();
+		map.put( "a", 1 );
+		map.put( "b", 2 );
+		testMap( map );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test3() throws Exception
+	{
+		StrIntHashMap map = new StrIntHashMap();
+		map.put( "a", 1 );
+		map.put( "b", 2 );
+		map.put( "c", 3 );
+		testMap( map );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void testNullValue() throws Exception
+	{
+		StrIntHashMap map = new StrIntHashMap();
+		map.put( "a", 1 );
+		map.put( "b", null );
+		map.put( "c", 3 );
+		testMap( map );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void testNullKey() throws Exception
+	{
+		StrIntHashMap map = new StrIntHashMap();
+		map.put( "a", 1 );
+		map.put( null, 2 );
+		map.put( "c", 3 );
+		testMap( map );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void testNullKeyValue() throws Exception
+	{
+		StrIntHashMap map = new StrIntHashMap();
+		map.put( "a", 1 );
+		map.put( null, null );
+		map.put( "c", 3 );
+		testMap( map );
+	}
+	
+	private void testMap( StrIntHashMap map )
+	{
+//		System.out.println( "---------------------------------------------" );
+//		System.out.println( "map = "+map );
+		
+		Type type = new Type( "map" );
+		Class2TypeMap class2type = new Class2TypeMap();
+		StrIntHashMapSerializer.init( type, class2type );
+		ImportExportHelper helper = type.getImportExportHelper();
+		
+		StructValue sv = helper.exportValue( vf, map );
+//		System.out.println( "sv = "+sv );
+		
+		assertEquals( sv.type(), type );
+		
+		StrIntHashMap map2 = (StrIntHashMap) helper.importValue( sv );
+//		System.out.println( "map2 = "+map2 );
+		
+		assertEquals( map, map2 );
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/util/TestStrStrHashMapSerializer.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/util/TestStrStrHashMapSerializer.java
new file mode 100644
index 0000000..e706f59
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/util/TestStrStrHashMapSerializer.java
@@ -0,0 +1,129 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.util;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.DummyValueFactory;
+import org.junit.Test;
+
+
+/** Tests StrStrHashMapSerializer */
+public class TestStrStrHashMapSerializer
+{
+	/** @throws Exception */
+	@Test
+	public void test0() throws Exception
+	{
+		StrStrHashMap map = new StrStrHashMap();
+		testMap( map );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test1() throws Exception
+	{
+		StrStrHashMap map = new StrStrHashMap();
+		map.put( "a", "1" );
+		testMap( map );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test2() throws Exception
+	{
+		StrStrHashMap map = new StrStrHashMap();
+		map.put( "a", "1" );
+		map.put( "b", "2" );
+		testMap( map );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test3() throws Exception
+	{
+		StrStrHashMap map = new StrStrHashMap();
+		map.put( "a", "1" );
+		map.put( "b", "2" );
+		map.put( "c", "3" );
+		testMap( map );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void testNullValue() throws Exception
+	{
+		StrStrHashMap map = new StrStrHashMap();
+		map.put( "a", "1" );
+		map.put( "b", null );
+		map.put( "c", "3" );
+		testMap( map );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void testNullKey() throws Exception
+	{
+		StrStrHashMap map = new StrStrHashMap();
+		map.put( "a", "1" );
+		map.put( null, "2" );
+		map.put( "c", "3" );
+		testMap( map );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void testNullKeyValue() throws Exception
+	{
+		StrStrHashMap map = new StrStrHashMap();
+		map.put( "a", "1" );
+		map.put( null, null );
+		map.put( "c", "3" );
+		testMap( map );
+	}
+	
+	private void testMap( StrStrHashMap map )
+	{
+//		System.out.println( "---------------------------------------------" );
+//		System.out.println( "map = "+map );
+		
+		ValueFactory vf = new DummyValueFactory();
+		Type type = new Type( "map" );
+		Class2TypeMap class2type = new Class2TypeMap();
+		StrStrHashMapSerializer.init( type, class2type );
+		ImportExportHelper helper = type.getImportExportHelper();
+		
+		StructValue sv = helper.exportValue( vf, map );
+//		System.out.println( "sv = "+sv );
+		
+		assertEquals( sv.type(), type );
+		
+		StrStrHashMap map2 = (StrStrHashMap) helper.importValue( sv );
+//		System.out.println( "map2 = "+map2 );
+		
+		assertEquals( map, map2 );
+	}
+}
diff --git a/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/util/TestURLSerializer.java b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/util/TestURLSerializer.java
new file mode 100644
index 0000000..3a3b7ec
--- /dev/null
+++ b/binding-java/runtime/src/test/java/org/apache/etch/bindings/java/util/TestURLSerializer.java
@@ -0,0 +1,67 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.java.util;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.DummyValueFactory;
+import org.apache.etch.util.URL;
+import org.junit.Test;
+
+
+/** Tests URLSerializer */
+public class TestURLSerializer
+{
+	/** @throws Exception */
+	@Test
+	public void testImport() throws Exception
+	{
+		URL url = new URL( "scheme://user:pw@host:23/resource;s=1;t=2?p=3&q=4#frag" );
+		test( url );
+	}
+	
+	private void test( URL url )
+	{
+//		System.out.println( "---------------------------------------------" );
+//		System.out.println( "url = "+url );
+
+		ValueFactory vf = new DummyValueFactory();
+		Type type = new Type( "url" );
+		Class2TypeMap class2type = new Class2TypeMap();
+		URLSerializer.init( type, class2type );
+		ImportExportHelper helper = type.getImportExportHelper();
+		
+		StructValue sv = helper.exportValue( vf, url );
+//		System.out.println( "sv = "+sv );
+		
+		assertEquals( sv.type(), type );
+		
+		URL url2 = (URL) helper.importValue( sv );
+//		System.out.println( "url2 = "+url2 );
+		
+		assertEquals( url, url2 );
+	}
+}
diff --git a/binding-xml/build.xml b/binding-xml/build.xml
new file mode 100644
index 0000000..cb92ad1
--- /dev/null
+++ b/binding-xml/build.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-xml-binding" basedir="." default="help">
+    <description>Etch-to-XML Binding</description>
+    <property name="Etch.basedir" location="${basedir}/.." />
+    <import file="${Etch.basedir}/build-support/etch.common.xml" />
+
+    <!-- standard, supported targets -->
+    <target name="Debug"         depends="debug" />
+    <target name="Release"       depends="release" />
+    <target name="Clean"         depends="clean" />
+    <target name="debug"         depends="init-debug,component-all,post-debug"   />
+    <target name="release"       depends="init-release,component-all,post-release" />
+    <target name="clean"         depends="init-clean,component-all,post-clean" />
+    <target name="maven-install" depends="init-maven,release" />
+
+    <target name="init-maven" >
+        <property name="DO.maven.install" value="true" />
+    </target>
+
+    <target name="validate-dependencies" >
+        <mkdir dir="${Etch.logDirectory}" />
+    </target>
+
+    <target name="init-debug" depends="validate-dependencies" >
+        <property name="Etch.build.target" value="Debug" />
+        <property name="Etch.javac.debug" value="on" />
+        <property name="Etch.javac.optimize" value="off" />
+    </target>
+
+    <target name="post-debug" >
+    </target>
+
+    <target name="init-release" depends="validate-dependencies">
+        <!-- For now, keep debug-symbols and no-optimize, even for release builds -->
+        <property name="Etch.build.target" value="Release" />
+        <property name="Etch.javac.debug"  value="on" />
+        <property name="Etch.javac.optimize" value="off" />
+        <!--
+        <property name="Etch.javac.debug"  value="off" />
+        <property name="Etch.javac.optimize" value="on" />
+        -->
+    </target>
+    
+    <target name="post-release" >
+    </target>
+
+    <target name="init-clean" depends="validate-dependencies">
+        <property name="Etch.build.target" value="Clean" />
+    </target>
+
+    <target name="post-clean" >
+        <echo message="Executing clean" />
+    </target>
+
+    <target name="component-all" >
+        <build_component dir="compiler" />
+        <!-- <build_component dir="compiler" /> -->
+    </target>
+
+</project>
diff --git a/binding-xml/compiler/build.xml b/binding-xml/compiler/build.xml
new file mode 100644
index 0000000..d4d59ab
--- /dev/null
+++ b/binding-xml/compiler/build.xml
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-xml-compiler" basedir="." default="help">
+    <description>Etch-to-XML compiler implementation</description>
+    <property name="Etch.basedir" location="${basedir}/../.." />
+    <import file="${Etch.basedir}/build-support/etch.includes.xml" />
+
+    <!-- Static properties of the sub-project -->
+    <property name="proj"                 location="${Etch.basedir}/binding-xml/compiler" />
+    <property name="target"               location="${proj}/target" />
+    <property name="src"                  location="${proj}/src" />        
+    <property name="generatedSrc"         location="${target}/generated-sources" />
+    <property name="classesDirectory"     location="${target}/classes" />
+    <property name="resourcesDirectory"   location="${target}/resources" />
+    <property name="testResultsDirectory" location="${target}/test-results" />
+
+    <!-- MACRO: init-target -->
+    <macrodef name="init-target" >
+        <sequential>
+            <delete dir="${classesDirectory}"   failonerror="false" quiet="true" />
+            <delete dir="${resourcesDirectory}" failonerror="false" quiet="true" />
+            <mkdir dir="${classesDirectory}" />
+            <mkdir dir="${classesDirectory}/main" />
+            <mkdir dir="${classesDirectory}/test" />
+            <mkdir dir="${resourcesDirectory}" />
+        </sequential>
+    </macrodef>
+
+    <!-- MACRO: compile-sources -->
+    <macrodef name="compile-sources" >
+        <sequential>            
+            <!-- compile compiler plugin -->
+            <javac  debug="${Etch.javac.debug}"
+                    target="1.5"
+                    optimize="${Etch.javac.optimize}"
+                    destdir="${classesDirectory}/main" >
+                <src path="${src}/main/java" />
+                <exclude name="**/.svn/**" />
+                <classpath refid="Etch.dependencies.jar.paths" />
+                <classpath>
+                    <pathelement location="${Etch.HOME}/lib/${etch-compiler.jar}" />
+                </classpath>
+            </javac>
+
+            <!-- compiler plugin resources -->
+            <copy todir="${classesDirectory}/main" >
+                <fileset dir="${src}/main/resources">
+                    <include name="**/*.kwd" />
+                    <include name="**/*.vm" />
+                </fileset>
+            </copy>
+
+            <!--
+            <javac  debug="${Etch.javac.debug}"
+                    target="1.5"
+                    optimize="${Etch.javac.optimize}"
+                    destdir="${classesDirectory}/test" >
+                <src path="${src}/test/java" />
+                <exclude name="**/.svn/**" />
+                <classpath refid="Etch.dependencies.jar.paths" />
+                <classpath>
+                    <pathelement location="${classesDirectory}/main" />
+                    <pathelement location="${Etch.HOME}/lib/${etch-compiler.jar}" />
+                </classpath>
+            </javac>
+            -->
+
+        </sequential>
+    </macrodef>
+    
+    <!-- MACRO: bundle-jars -->
+    <macrodef name="bundle-jars" >
+        <attribute name="dist" default="${Etch.dist}" />
+        <sequential>
+            <mkdir dir="@{dist}/lib" />
+            
+            <!-- CREATE jars -->
+
+            <!-- Package up etch-xml-compiler jar -->
+            <jar jarfile="@{dist}/lib/${etch-xml-compiler.jar}" >
+                <manifest>
+                    <attribute name="Copyright"    value="${Etch.copyrightNotice}" />
+                    <attribute name="Version"      value="${Etch.version}" />
+                    <attribute name="LongVersion"  value="${Etch.longversion}" />
+                    <attribute name="Build-Tag"    value="${Etch.buildTag}" />
+                    <attribute name="SVN-Revision" value="${Etch.runtime.revisionNumber}" />
+                </manifest>
+                <metainf dir="${Etch.basedir}" >
+                    <include name="NOTICE.txt" />
+                    <include name="LICENSE.txt" />
+                </metainf>
+                <fileset dir="${classesDirectory}/main">
+                    <include name="org/apache/etch/bindings/**" />
+                    <!-- <include name="resources/**" /> -->
+                </fileset>
+            </jar>
+
+            <!-- CREATE source archives -->
+            
+            <!-- package up etch-xml-compiler src -->
+            <zip destfile="@{dist}/lib/${etch-xml-compiler-src.zip}" >
+                <fileset dir="${src}/main/java" >
+                    <include name="org/apache/etch/bindings/**/*.java" />
+                </fileset>
+                <fileset dir="${src}/main/resources" >
+                    <include name="**/*" />
+                </fileset>
+            </zip>
+
+        </sequential>
+    </macrodef>
+    
+    <!-- INIT TARGET -->
+    <!-- Modify this target to define project specific properties that can only be set at runtime -->
+    <target name="do-init">
+        <delete dir="${target}" failonerror="false" quiet="true" />
+
+        <mkdir dir="${target}" />
+        <mkdir dir="${generatedSrc}" />
+        <mkdir dir="${classesDirectory}" />
+        <mkdir dir="${resourcesDirectory}" />
+        <mkdir dir="${testResultsDirectory}" />
+    </target>
+
+    <!-- CLEAN TARGET -->
+    <target name="do-clean">
+        <delete dir="${target}" />
+    </target>
+
+    <!-- BUILD TARGET -->
+    
+    <target name="generate-sources" >
+        <!-- Generate version info -->
+        <update-tokens filename="${src}/main/java/org/apache/etch/bindings/xml/compiler/CompilerVersion.java" />  
+    </target>
+
+    <target name="compile-for-dist" >
+        <!-- Initialize target directories -->
+        <init-target />
+
+        <!-- Compile Source -->
+        <compile-sources />
+
+        <!-- Bundle Jars -->
+        <bundle-jars dist="${Etch.dist}" />
+    </target>
+    
+    <target name="compile-for-clover" if="Clover.enabled" >
+
+        <echo message="Rebuilding with clover" />
+
+        <!-- initialize-clover -->
+        <initialize-clover suffix="etchxmlcompiler" >
+            <fileset dir="${src}/main/java">
+                <include name="**/*.java" />
+            </fileset>
+            <!--
+            <testsources dir="${src}/test/java">
+                <include name="**/*.java" />
+            </testsources>
+            -->
+        </initialize-clover>
+        
+        <!-- Initialize target directories -->
+        <init-target />
+        
+        <!-- Compile Source -->
+        <compile-sources />
+        
+        <!-- Bundle Jars -->
+        <bundle-jars dist="${Etch.clover-dist}" />
+
+    </target>
+    
+    <target name="do-build" depends="generate-sources,compile-for-dist,compile-for-clover" />
+
+    <!-- TEST TARGET -->
+    <target name="do-test">
+        
+        <!-- Run Unit Tests -->
+        <!--
+        <junit printsummary="yes" haltonfailure="no" dir="${classesDirectory}"
+            errorProperty="build.tests.fail" failureProperty="build.tests.fail">
+            <classpath>
+                <pathelement location="${classesDirectory}/main" />
+                <pathelement location="${classesDirectory}/test" />
+                <pathelement location="${Etch.dependency.junit.jar}" />
+                <pathelement location="${Etch.HOME}/lib/${etch-compiler.jar}" />
+                <pathelement location="${Etch.dependency.clover.jar}"/>
+            </classpath>
+            <formatter type="xml"/>
+            <batchtest fork="true" todir="${testResultsDirectory}">
+                <fileset dir="${src}/test/java">
+                    <include name="**/*.java" />
+                </fileset>
+            </batchtest>
+        </junit>
+        -->
+    </target>
+
+    <!-- POSTBUILD TARGET -->
+    <target name="do-postbuild">
+    </target>
+
+    <target name="do-publish" if="build.tests.fail">
+        <!-- Set flag file if any tests failed -->
+        <touch file="${Etch.runtime.tests.fail}"/>
+    </target>
+
+</project>
diff --git a/binding-xml/compiler/src/main/java/org/apache/etch/bindings/xml/compiler/Compiler.java b/binding-xml/compiler/src/main/java/org/apache/etch/bindings/xml/compiler/Compiler.java
new file mode 100644
index 0000000..c5a0a12
--- /dev/null
+++ b/binding-xml/compiler/src/main/java/org/apache/etch/bindings/xml/compiler/Compiler.java
@@ -0,0 +1,635 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.xml.compiler;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.CmdLineOptions;
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.LogHandler;
+import org.apache.etch.compiler.Output;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.Token;
+import org.apache.etch.compiler.Version;
+import org.apache.etch.compiler.ast.Except;
+import org.apache.etch.compiler.ast.Extern;
+import org.apache.etch.compiler.ast.Item;
+import org.apache.etch.compiler.ast.Message;
+import org.apache.etch.compiler.ast.MessageDirection;
+import org.apache.etch.compiler.ast.Module;
+import org.apache.etch.compiler.ast.MsgDirHelper;
+import org.apache.etch.compiler.ast.Named;
+import org.apache.etch.compiler.ast.ParamList;
+import org.apache.etch.compiler.ast.Parameter;
+import org.apache.etch.compiler.ast.Service;
+import org.apache.etch.compiler.ast.Thrown;
+import org.apache.etch.compiler.ast.TypeRef;
+import org.apache.etch.compiler.opt.ToString;
+import org.apache.etch.compiler.opt.ToString.FieldItem;
+import org.apache.etch.compiler.opt.ToString.FmtItem;
+import org.apache.etch.compiler.opt.ToString.StringItem;
+import org.apache.etch.util.Hash;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.exception.ResourceNotFoundException;
+import org.apache.velocity.runtime.RuntimeServices;
+import org.apache.velocity.runtime.log.LogChute;
+
+
+/**
+ * Compiler is a helper class not only for Backend, but also
+ * for the templates. They call methods here to perform
+ * "hard" tasks.
+ */
+public class Compiler extends Backend
+{
+	private final static String tmplPath1 = "org/apache/etch/bindings/xml/compiler/";
+	private final static String tmplPath2 = "resources/org/apache/etch/bindings/xml/compiler/";
+
+	private final static String fnSuffix = ".xml";
+
+	private final static String VERSION = Version.VERSION + " / " + CompilerVersion.VERSION;
+	
+	private LogHandler lh;
+	
+	/**
+	 * Initializes use of velocity engine and sets up
+	 * resource loaders.
+	 * @throws Exception
+	 */
+	private void initVelocity()
+		throws Exception
+	{
+		Velocity.setProperty( Velocity.RUNTIME_LOG_LOGSYSTEM, new MyLogger() );
+		
+		Velocity.setProperty( Velocity.RESOURCE_LOADER, "file, class" );
+
+		Velocity.setProperty( "file.resource.loader.description", "Velocity File Resource Loader" );
+		Velocity.setProperty( "file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.FileResourceLoader" );
+		Velocity.setProperty( "file.resource.loader.path", "." );
+
+		Velocity.setProperty( "class.resource.loader.description", "Velocity Classpath Resource Loader" );
+		Velocity.setProperty( "class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader" );
+		
+		Velocity.init();
+	}
+	
+	private static class MyLogger implements LogChute
+	{
+		private final LogHandler lh = null;
+		
+		public void init( RuntimeServices rts ) throws Exception
+		{
+			// ignore.
+		}
+
+		public boolean isLevelEnabled( int level )
+		{
+			return level >= 2;
+		}
+
+		public void log( int level, String msg )
+		{
+			if (level < 2)
+				return;
+			
+			if (lh != null)
+				lh.report( level == 2 ? LogHandler.LEVEL_WARNING : LogHandler.LEVEL_ERROR, null, msg );
+			else
+				System.out.printf( "Velocity msg (%d): %s\n", level, msg );
+		}
+
+		public void log( int level, String msg, Throwable e )
+		{
+			if (level < 2)
+				return;
+			
+			if (lh != null)
+				lh.report( level == 2 ? LogHandler.LEVEL_WARNING : LogHandler.LEVEL_ERROR, null, msg );
+			else
+				System.out.printf( "Velocity msg (%d): %s: %s\n", level, msg, e );
+		}
+	}
+
+	/**
+	 * @param path
+	 * @param fn
+	 * @return the velocity template
+	 * @throws Exception
+	 */
+	private Template getTemplate( String[] path, String fn )
+		throws Exception
+	{
+		ResourceNotFoundException rnfe = null;
+		
+		for (String p: path)
+		{
+			if (p == null)
+				continue;
+			
+//			System.out.println( "trying to load template "+(p+fn) );
+			try
+			{
+				if (Velocity.resourceExists( p+fn ))
+					return Velocity.getTemplate( p+fn );
+			}
+			catch ( ResourceNotFoundException e )
+			{
+				rnfe = e;
+			}
+			catch ( Exception e )
+			{
+				System.out.println( "ignoring "+e);
+			}
+		}
+		
+		if (rnfe != null)
+			throw rnfe;
+		
+		throw new ResourceNotFoundException("could not find resource: "+fn);
+	}
+
+	/**
+	 * Constructs the Compiler. This is a helper class not only
+	 * for Backend, but also for the templates. They call methods
+	 * here to perform "hard" tasks.
+	 *
+	 * @throws Exception
+	 */
+	public Compiler() throws Exception
+	{
+		initVelocity();
+		
+		String[] path = { tmplPath1, tmplPath2 };
+		vf_vm = getTemplate( path, "vf.vm" );
+	}
+
+	private final Template vf_vm;
+
+	@Override
+	public void generate( Module module, CmdLineOptions options )
+		throws Exception
+	{
+		// xml always wants to not flatten packages:
+		options.noFlattenPackages = true;
+		
+		lh = options.lh;
+		
+		Output dir = options.output;
+		
+		String m = module.name().name;
+		if (m.length() > 0)
+		{
+			dir = dir.newPackage( m );
+		}
+
+		// generate code for each service.
+
+		for (Service intf : module)
+		{
+			generate( intf, dir );
+		}
+	}
+
+	private void generate( final Service intf, Output dir )
+		throws Exception
+	{
+		// Generate the value factory file
+
+		doFile( dir, getVfName( intf ) + fnSuffix, lh, new Gen()
+		{
+			public void run( PrintWriter pw ) throws Exception
+			{
+				generateVf( pw, intf );
+			}
+		} );
+	}
+
+	/**
+	 * Generate the value factory for the service.
+	 * @param pw
+	 * @param intf
+	 * @throws Exception
+	 */
+	void generateVf( PrintWriter pw, Service intf )
+		throws Exception
+	{
+		// params keeps track of the total set of parameters
+		// named (for enums, structs, exceptions, and messages).
+		Set<String> params = new HashSet<String>();
+		VelocityContext context = new VelocityContext();
+		context.put( "now", new Date() );
+		context.put( "version", VERSION );
+		context.put( "helper", this );
+		context.put( "intf", intf );
+		context.put( "params", params );
+		vf_vm.merge( context, pw );
+	}
+
+	private String getVfName( Service intf )
+	{
+		return getIntfName( intf, MessageDirection.BOTH );
+	}
+
+	private String getIntfName( Service intf, MessageDirection mc )
+	{
+		String suffix = MsgDirHelper.getSuffix( mc );
+		return intf.name()+suffix;
+	}
+
+	@Override
+	public String asyncReceiverPoolName( Message msg )
+	{
+		return msg.getAsyncReceiver().toString().toLowerCase();
+	}
+
+	@Override
+	public String getTypeValue( TypeRef type, Token value ) throws Exception
+	{
+//		System.out.println( "getTypeValue called with: "+type+": "+value );
+		Token t = type.type();
+		switch (t.kind)
+		{
+			case EtchGrammarConstants.STRING: return protectString( value.image );
+			default: return value.image;
+		}
+	}
+
+	private String protectString( String s ) throws Exception
+	{
+		return s;
+		//return protectAttr(s);
+	}
+
+	/**
+	 * @param type
+	 * @return type name appropriate for use as a structure
+	 * element or exception parameter or function parameter
+	 * or result.
+	 */
+	@Override
+	public String getTypeName( TypeRef type )
+	{
+		if (type.dim() > 0)
+			return getNativeTypeName( type )/*+dim2spec( type.dim() )*/;
+		return getRefTypeName( type );
+	}
+
+	/**
+	 * @param type the etch type
+	 * @return the fundamental native type for java. so etch
+	 * int -> java int, while etch string -> java String.
+	 */
+	@Override
+	public String getNativeTypeName( TypeRef type )
+	{
+		Token t = type.type();
+		switch (t.kind)
+		{
+			case EtchGrammarConstants.VOID: return "void";
+			case EtchGrammarConstants.BOOLEAN: return "boolean";
+			case EtchGrammarConstants.BYTE: return "byte";
+			case EtchGrammarConstants.SHORT: return "short";
+			case EtchGrammarConstants.INT: return "int";
+			case EtchGrammarConstants.LONG: return "long";
+			case EtchGrammarConstants.FLOAT: return "float";
+			case EtchGrammarConstants.DOUBLE: return "double";
+			case EtchGrammarConstants.STRING: return "string";
+			case EtchGrammarConstants.OBJECT: return "object";
+			default:
+			{
+				// we have to use a fully qualified name here.
+				// find the actual type...
+				Named<?> n = type.intf().get( t.image );
+				if (n == null)
+					throw new IllegalArgumentException( String.format(
+						"undefined or ambiguous name at line %d: %s",
+						t.beginLine, t.image ) );
+				String s = n.efqname( this );
+				
+				if ( s == null && n instanceof Extern )
+					s = t.image;
+				
+				return s;
+			}
+		}
+	}
+	
+	
+	/**
+	 * @param type
+	 * @return true if the type is an etch builtin type.
+	 */
+	public boolean isBasicType(TypeRef type) {
+		
+		Token t = type.type();
+		
+		switch (t.kind)
+		{
+		case EtchGrammarConstants.VOID:
+			return true;
+		case EtchGrammarConstants.BOOLEAN:
+			return true;
+		case EtchGrammarConstants.BYTE:
+			return true;
+		case EtchGrammarConstants.SHORT:
+			return true;
+		case EtchGrammarConstants.INT:
+			return true;
+		case EtchGrammarConstants.LONG:
+			return true;
+		case EtchGrammarConstants.FLOAT:
+			return true;
+		case EtchGrammarConstants.DOUBLE:
+			return true;
+		case EtchGrammarConstants.STRING:
+			return true;
+		case EtchGrammarConstants.OBJECT:
+			return true;
+
+		// patch here. more generic approach needed.
+		// currently, only taking care of Map, Set, List & Datetime
+		case EtchGrammarConstants.ID:
+			if ( t.toString().equals("Map") || t.toString().equals("List") ||
+					t.toString().equals("Set") || t.toString().equals("Datetime") )
+				return true;
+		}
+		return false;
+	}
+
+	/**
+	 * @param type the etch type
+	 * @return the fundamental native reference type for java.
+	 * so etch int -> java Integer, while etch string -> java String.
+	 */
+	private String getRefTypeName( TypeRef type )
+	{
+		Token t = type.type();
+		switch (t.kind)
+		{
+			case EtchGrammarConstants.VOID: return "void";
+			case EtchGrammarConstants.BOOLEAN: return "boolean";
+			case EtchGrammarConstants.BYTE: return "byte";
+			case EtchGrammarConstants.SHORT: return "short";
+			case EtchGrammarConstants.INT: return "int";
+			case EtchGrammarConstants.LONG: return "long";
+			case EtchGrammarConstants.FLOAT: return "float";
+			case EtchGrammarConstants.DOUBLE: return "double";
+			case EtchGrammarConstants.STRING: return "string";
+			case EtchGrammarConstants.OBJECT: return "object";
+			default:
+			{
+				// we have to use a fully qualified name here.
+				// find the actual type...
+				Named<?> n = type.intf().get( t.image );
+				if (n == null)
+					throw new IllegalArgumentException( String.format(
+						"undefined or ambiguous name at line %d: %s",
+						t.beginLine, t.image ) );
+				
+				
+				if ( n.isExtern() )
+					return n.fqname();
+				
+				return n.efqname( this );
+			}
+		}
+	}
+
+	@Override
+	public String formatString( ParamList<Service> n, boolean isExcept )
+		throws ParseException, IOException
+	{
+		ToString ts = (ToString) n.getOpt( "ToString" );
+		List<FmtItem> list;
+		if (ts != null)
+		{
+			list = ts.getFormat();
+			n.checkFormatList( ts.lineno(), list );
+		}
+		else
+			list = n.mkFormatList( isExcept, false );
+
+		if (list.size() == 1)
+		{
+			return list.get( 0 ).value();
+		}
+
+		StringBuffer sb = new StringBuffer();
+		sb.append( "String.format( " );
+		sb.append( "\"" );
+		for (FmtItem i: list)
+		{
+			if (i instanceof FieldItem)
+			{
+				sb.append( "%s" );
+			}
+			else
+			{
+				escape( sb, ((StringItem) i).value() );
+			}
+		}
+		sb.append( "\"" );
+		for (FmtItem i: list)
+		{
+			if (i instanceof FieldItem)
+			{
+				sb.append( ", " );
+				sb.append( ((FieldItem) i).value() );
+			}
+		}
+		sb.append( " )" );
+		return sb.toString();
+	}
+
+	private void escape( StringBuffer sb, String s ) throws IOException
+	{
+		StringReader rdr = new StringReader( s );
+		int c;
+		while ((c = rdr.read()) >= 0)
+		{
+			if (c == '"') sb.append( "\\\"" );
+			else if (c == '\\') sb.append( "\\\\" );
+			else if (c == '\t') sb.append( "\\t" );
+			else if (c == '\r') sb.append( "\\r" );
+			else if (c == '\n') sb.append( "\\n" );
+			else sb.append( (char) c );
+		}
+	}
+
+	@Override
+	public String mfvname( String vname )
+	{
+		return "_mf_"+vname;
+	}
+
+	@Override
+	public String mtvname( String vname )
+	{
+		return "_mt_"+vname;
+	}
+
+	@Override
+	public String getLang()
+	{
+		return "xml";
+	}
+
+	@Override
+	public String enum_efqname( String fqname, String moduleName,
+		String serviceName, String enumName )
+	{
+		return fqname;
+	}
+
+	@Override
+	public String except_efqname(String fqname, String moduleName, String serviceName, String exceptName) {
+
+		return fqname;
+	}
+
+	@Override
+	public String struct_efqname(String fqname, String moduleName, String serviceName, String enumName) {
+
+		return fqname;
+	}
+
+	@Override
+	public String qualifyParameterName( Token name )
+	{
+		return name.image;
+	}
+
+	@Override
+	public String qualifyConstantName( Service intf, Token name )
+	{
+		return intf.fqname()+'.'+name.image;
+	}
+
+	@Override
+	public String qualifyEnumName( Service intf, Token name )
+	{
+		return intf.fqname()+'.'+name.image;
+	}
+
+	@Override
+	public String getValidator( Named<?> named )
+	{
+		if (named instanceof Parameter)
+		{
+			Parameter param = (Parameter) named;
+			TypeRef type = param.type();
+
+			if (type.isBuiltin())
+				return "Validator_"+type.type()+".get( "+type.dim()+" )";
+
+			return "Validator_custom.getCustom( "+type.getNamed( type.intf() ).efqname( this )+".class, "+type.dim()+" )";
+		}
+
+		if (named instanceof Thrown)
+		{
+			Thrown thrown = (Thrown) named;
+			Except e = (Except) thrown.getNamed();
+			return "Validator_custom.getCustom( "+e.efqname( this )+".class, 0 )";
+		}
+
+		if (named instanceof Item)
+			return "Validator_boolean.get( 0 )";
+
+		return "null";
+	}
+
+	/**
+	 * @param descriptions
+	 * @return string with descriptions
+	 */
+	public String emitXml(List<String> descriptions)
+	{
+		StringBuffer buffer = new StringBuffer();
+		for(int i = 0; i < descriptions.size(); i++)
+		{
+			Object objMessage = descriptions.get(i);
+			String message = "";
+			if(objMessage != null)
+			{
+				message = objMessage.toString();
+			}
+
+			buffer.append(message);
+
+			if(i < descriptions.size() - 1)
+			{
+				buffer.append("\r\n");
+			}
+		}
+
+		return buffer.toString();
+	}
+
+	/**
+	 * @param unprotected
+	 * @return attribute value protected.
+	 * @throws IOException
+	 */
+	public String protectAttr(String unprotected) throws IOException
+	{
+		return org.apache.etch.util.core.xml.XmlParser.ProtectAttrValue.toString(unprotected);
+	}
+
+	/**
+	 * @param unprotected
+	 * @return cdata value protected.
+	 * @throws IOException
+	 */
+	public String protectCData(String unprotected) throws IOException
+	{
+		return org.apache.etch.util.core.xml.XmlParser.ProtectCData.toString(unprotected);
+	}
+
+	@Override
+	public void addDefaults( Service service ) throws ParseException
+	{
+		addBuiltin( service, newName( "List" ), "List", true );
+		addBuiltin( service, newName( "Map" ), "Map", true );
+		addBuiltin( service, newName( "Set" ), "Set", true );
+		addBuiltin( service, newName( "Datetime" ), "Datetime", false );
+	}
+
+	/**
+	 * @param n
+	 * @return the id of the named item.
+	 */
+	public int id( Named<?> n )
+	{
+		if (n instanceof Item || n instanceof Parameter)
+			return Hash.hash( n.name().name() );
+		
+		return Hash.hash( n.fqname() );
+	}
+}
diff --git a/binding-xml/compiler/src/main/java/org/apache/etch/bindings/xml/compiler/CompilerVersion.java b/binding-xml/compiler/src/main/java/org/apache/etch/bindings/xml/compiler/CompilerVersion.java
new file mode 100644
index 0000000..84cf5c5
--- /dev/null
+++ b/binding-xml/compiler/src/main/java/org/apache/etch/bindings/xml/compiler/CompilerVersion.java
@@ -0,0 +1,33 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.xml.compiler;
+
+/**
+ * The version info of this Etch backend (compiler).
+ */
+public interface CompilerVersion
+{
+	// This file is edited by the production build system to replace the value
+	// of VERSION below with whatever it wants the version string to actually be.
+	
+	/** The version of this Etch backend (compiler) */
+	public String VERSION = "xml 1.1.0-incubating (LOCAL-0)";
+}
diff --git a/binding-xml/compiler/src/main/java/org/apache/etch/bindings/xml/compiler/CompilerVersion.java.tmpl b/binding-xml/compiler/src/main/java/org/apache/etch/bindings/xml/compiler/CompilerVersion.java.tmpl
new file mode 100644
index 0000000..fcf4e72
--- /dev/null
+++ b/binding-xml/compiler/src/main/java/org/apache/etch/bindings/xml/compiler/CompilerVersion.java.tmpl
@@ -0,0 +1,30 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.bindings.xml.compiler;
+
+/**
+ * The version info of this Etch backend (compiler).
+ */
+public interface CompilerVersion
+{
+	// This file is edited by the production build system to replace the value
+	// of VERSION below with whatever it wants the version string to actually be.
+	
+	/** The version of this Etch backend (compiler) */
+	public String VERSION = "xml @EtchLongVersion@ (@EtchBuildTag@)";
+}
diff --git a/binding-xml/compiler/src/main/resources/org/apache/etch/bindings/xml/compiler/vf.vm b/binding-xml/compiler/src/main/resources/org/apache/etch/bindings/xml/compiler/vf.vm
new file mode 100644
index 0000000..d928fa1
--- /dev/null
+++ b/binding-xml/compiler/src/main/resources/org/apache/etch/bindings/xml/compiler/vf.vm
@@ -0,0 +1,361 @@
+## Copyright 2007-2008 Cisco Systems Inc.
+##
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy
+## of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations
+## under the License.
+<?xml version="1.0" encoding="utf-8" ?>
+
+<!--
+// This file automatically generated by:
+//   $version
+//   $now
+// This file is automatically created and should not be edited!
+-->
+
+<module name="$intf.parent().name()">
+#if ($intf.parent().descr().size() > 0)
+	<description>$helper.emitXml($intf.parent().descr())</description>
+#end
+	<service name="$intf.name()">
+#if ($intf.parent().descr().size() > 0)
+		<description>$helper.protectCData($helper.emitXml($intf.descr()))</description>
+#end
+## iterate through externs, grouping them together
+		<consts>
+#foreach( $n in $intf.iterator() )
+#if ($n.isConstant())
+			<const name="$n.name()" type="$helper.getNativeTypeName( $n.type() )" value="$helper.protectAttr($helper.getTypeValue( $n.type(), $n.value() ))">
+#if ($n.descr().size() > 0)
+				<description>$helper.protectCData($helper.emitXml($n.descr()))</description>
+#end
+			</const>
+			
+#end
+#end
+## --- constants from mixed-in interfaces --- 
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+#foreach( $n in $z.constants( true ) )
+#if ($n.isConstant())
+			
+			<const name="$n.name()" type="$helper.getNativeTypeName( $n.type() )" value="$helper.protectAttr($helper.getTypeValue( $n.type(), $n.value() ))">
+#if ($n.descr().size() > 0)
+				<description>$helper.protectCData($helper.emitXml($n.descr()))</description>
+#end
+			</const>
+#end
+#end
+#end
+#end
+		</consts>
+		
+## iterate through externs, grouping them together
+		<externs>
+#foreach( $n in $intf.iterator() )
+#if ($n.isExtern())
+			<extern name="$n.name()" typeId="$helper.id( $n )" typeName="$n.fqname()">
+#foreach ( $opt in $n.opts() )
+				<externmap language="$opt.getLanguage().toString()" name="$opt.getXname().toString()" nImport="$opt.getXnameImport().toString()" serializer="$opt.getSerializer().toString()" sImport="$opt.getSerializerImport().toString()">	
+				</externmap>
+#end
+#if ($n.descr().size() > 0)
+				<description>$helper.protectCData($helper.emitXml($n.descr()))</description>
+#end
+			</extern>
+			
+#end
+#end
+## --- externs from mixed-in interfaces
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+#foreach( $n in $z.externs( true ) )
+#if ($n.isExtern())
+			
+			<extern name="$n.name()" typeId="$helper.id( $n )" typeName="$n.fqname()">
+#foreach ( $opt in $n.opts() )
+				<externmap language="$opt.getLanguage().toString()" name="$opt.getXname().toString()" nImport="$opt.getXnameImport().toString()" serializer="$opt.getSerializer().toString()" sImport="$opt.getSerializerImport().toString()">	
+				</externmap>
+#end
+#if ($n.descr().size() > 0)
+				<description>$helper.protectCData($helper.emitXml($n.descr()))</description>
+#end
+			</extern>
+#end
+#end
+#end
+#end
+		</externs>
+		
+## iterate through enums, grouping them together
+		<enums>
+#foreach( $n in $intf.iterator() )
+#if ($n.isEnumx())
+			<enum name="$n.name()" typeId="$helper.id( $n )" typeName="$n.fqname()">
+#if ($n.descr().size() > 0)
+				<description>$helper.protectCData($helper.emitXml($n.descr()))</description>
+#end
+#foreach( $param in $n.iterator() )
+				<entry value="$param.name()" entryId="$helper.id( $param )" />
+#end
+			</enum>
+			
+#end
+#end
+## --- enums from mixed-in interfaces
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+#foreach( $n in $z.enums( true ) )
+#if ($n.isEnumx())
+			
+			<enum name="$n.name()" typeId="$helper.id( $n )" typeName="$n.fqname()">
+#if ($n.descr().size() > 0)
+				<description>$helper.protectCData($helper.emitXml($n.descr()))</description>
+#end
+#foreach( $param in $n.iterator() )
+				<entry value="$param.name()" entryId="$helper.id( $param )" />
+#end
+			</enum>
+#end
+#end
+#end
+#end
+		</enums>
+
+## iterate through structures, grouping them together
+		<structs>
+#foreach( $n in $intf.iterator() )
+#if ($n.isStruct())
+			<struct name="$n.name()" typeId="$helper.id( $n )" typeName="$n.fqname()" #if($n.hasExtends())baseType="$n.getExtends().fqname()"#else baseType="null"#end>
+#if ($n.descr().size() > 0)
+				<description>$helper.protectCData($helper.emitXml($n.descr()))</description>
+#end
+#foreach( $param in $n.iterator() )
+				<field name="$param.name()" fieldId="$helper.id( $param )" fieldName="$param.fqname()" type="$helper.getTypeName($param.type())" isPrimitiveType="$helper.isBasicType($param.type())" isArray="$param.type().isArray()" #if($param.type().isArray())dimension="$param.type().dim()"#end>
+#if ($param.descr().size() > 0)
+					<description>$helper.protectCData($helper.emitXml($param.descr()))</description>
+#end
+				</field>
+#end
+			</struct>
+#end
+#end
+
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+#foreach( $n in $z.structs( true ) )
+#if ($n.isStruct())
+			
+			<struct name="$n.name()" typeId="$helper.id( $n )" typeName="$n.fqname()"  #if($n.hasExtends())baseType="$n.getExtends().fqname()"#else baseType="null"#end>
+#if ($n.descr().size() > 0)
+				<description>$helper.protectCData($helper.emitXml($n.descr()))</description>
+#end
+#foreach( $param in $n.iterator() )
+				<field name="$param.name()" fieldId="$helper.id( $param )" fieldName="$param.fqname()" type="$helper.getTypeName($param.type())" isPrimitiveType="$helper.isBasicType($param.type())"  isArray="$param.type().isArray()" #if($param.type().isArray())dimension="$param.type().dim()"#end>
+#if ($param.descr().size() > 0)
+					<description>$helper.protectCData($helper.emitXml($param.descr()))</description>
+#end
+				</field>
+#end
+			</struct>
+#end
+#end
+#end
+#end
+		</structs>
+
+## iterate through exceptions, grouping them together		
+		<exceptions>
+#foreach( $n in $intf.iterator() )
+#if ($n.isExcept())
+			<exception name="$n.name()" isUnchecked="$n.isUnchecked()" typeId="$helper.id( $n )" typeName="$n.fqname()" #if($n.hasExtends())baseType="$n.getExtends().fqname()"#else baseType="null"#end>
+#if ($n.descr().size() > 0)
+				<description>$helper.protectCData($helper.emitXml($n.descr()))</description>
+#end
+#foreach( $param in $n.iterator() )
+				<field name="$param.name()" fieldId="$helper.id( $param )" fieldName="$param.fqname()" type="$param.type().type()" isArray="$param.type().isArray()" #if($param.type().isArray())dimension="$param.type().dim()"#end>
+#if ($param.descr().size() > 0)
+					<description>$helper.protectCData($helper.emitXml($param.descr()))</description>
+#end
+				</field>
+#end
+			</exception>
+#end
+#end
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+#foreach( $n in $z.exceptions( true ) )
+#if ($n.isExcept())
+			
+			<exception name="$n.name()" isUnchecked="$n.isUnchecked()" typeId="$helper.id( $n )" typeName="$n.fqname()" #if($n.hasExtends())baseType="$n.getExtends().fqname()"#else baseType="null"#end>
+#if ($n.descr().size() > 0)
+				<description>$helper.protectCData($helper.emitXml($n.descr()))</description>
+#end
+#foreach( $param in $n.iterator() )
+				<field name="$param.name()" fieldId="$helper.id( $param )" fieldName="$param.fqname()" type="$param.type().type()" isArray="$param.type().isArray()" #if($param.type().isArray())dimension="$param.type().dim()"#end>
+#if ($param.descr().size() > 0)
+					<description>$helper.protectCData($helper.emitXml($param.descr()))</description>
+#end
+				</field>
+#end
+			</exception>
+#end
+#end
+#end
+#end
+		</exceptions>
+		
+## --------------------------------------------------
+## iterate through messages, grouping them together		
+## --------------------------------------------------
+		<methods>
+#foreach( $n in $intf.iterator() )
+#if ($n.isMessage())
+#if (!$n.isHidden())
+#if (!$n.isOneway())
+#set( $r = $n.getResultMessage() )
+#end
+			<method name="$n.name()" typeId="$helper.id( $n )" typeName="$n.fqname()" asyncReceiverMode="$n.getAsyncReceiver().toString().toLowerCase()" isOneway="$n.isOneway()" messageDirection="$n.getMessageDirection().toString().toLowerCase()" >
+#if ($n.descr().size() > 0)
+				<description>$helper.protectCData($helper.emitXml($n.descr()))</description>
+#end				
+#if ($n.hasThrown())
+#foreach( $thrownItem in $n.thrown().iterator() )
+				<exception name="$thrownItem" type="$thrownItem.getNamed().efqname($helper)">
+					<description>$helper.protectCData($helper.emitXml($thrownItem.descr()))</description>
+				</exception>
+#end
+#end
+#if ($n.hasAuth())
+				<authorize methodName="$n.getAuth().method()">
+#foreach( $authArg in $n.getAuth().args() )
+					<argument name="$authArg.value()" />
+#end
+				</authorize>
+#end
+#foreach( $param in $n.iterator() )
+				<field name="$param.name()" fieldId="$helper.id( $param )" fieldName="$param.fqname()" type="$helper.getNativeTypeName($param.type())" isPrimitiveType="$helper.isBasicType($param.type())" isArray="$param.type().isArray()" #if($param.type().isArray())dimension="$param.type().dim()"#end>
+#if ($param.descr().size() > 0)
+					<description>$helper.protectCData($helper.emitXml($param.descr()))</description>
+#end
+				</field>
+#end
+				<result #if (!$n.isOneway())fieldId="$helper.id( $n.getResultMessage() )" fieldName="$n.getResultMessage().fqname()"#end type="$helper.getNativeTypeName($n.type())" isPrimitiveType="$helper.isBasicType($n.type())" isArray="$n.type().isArray()" #if($n.type().isArray())dimension="$n.type().dim()"#end>
+#if ($n.returnDescr().size() > 0)
+					<description>$helper.protectCData($helper.emitXml($n.returnDescr()))</description>
+#end
+				</result>
+			</method>
+			
+## ------------------
+## result message 
+## ------------------
+#if (!$n.isOneway())
+			<method name="$r.name()" typeId="$helper.id( $r )" typeName="$r.fqname()" asyncReceiverMode="$r.getAsyncReceiver().toString().toLowerCase()" isOneway="true" messageDirection="$r.msgDir().toString().toLowerCase()" timeout="$n.getTimeout()" responseField="result">
+#if ($r.descr().size() > 0)
+				<description>$helper.protectCData($helper.emitXml($n.descr()))</description>
+#end			
+#foreach( $param in $r.iterator() )
+				<field name="$param.name()" fieldId="$helper.id( $param )" fieldName="$param.fqname()" type="$helper.getNativeTypeName($param.type())" isPrimitiveType="$helper.isBasicType($param.type())" isArray="$param.type().isArray()" #if($param.type().isArray())dimension="$param.type().dim()"#end>
+#if ($param.descr().size() > 0)
+					<description>$helper.protectCData($helper.emitXml($param.descr()))</description>
+#end
+				</field>
+#end
+			</method>
+#end
+#end
+#end
+#end
+
+## -----------------------
+## add mixin stuff here 
+## -----------------------
+#foreach( $x in $intf.iterator() )
+#if( $x.isMixin() )
+#set( $m = $x.getModule() )
+#set( $z = $m.iterator().next() )
+#foreach( $n in $z.messages( true ) )
+#if(!$n.isHidden())
+#if (!$n.isOneway())
+#set( $r = $n.getResultMessage() )
+#end
+			<method name="$n.name()" typeId="$helper.id( $n )" typeName="$n.fqname()" asyncReceiverMode="$n.getAsyncReceiver().toString().toLowerCase()" isOneway="$n.isOneway()" messageDirection="$n.getMessageDirection().toString().toLowerCase()" >
+#if ($n.descr().size() > 0)
+				<description>$helper.protectCData($helper.emitXml($n.descr()))</description>
+#end				
+#if ($n.hasThrown())
+#foreach( $thrownItem in $n.thrown().iterator() )
+				<exception name="$thrownItem" type="$thrownItem.getNamed().efqname($helper)">
+					<description>$helper.protectCData($helper.emitXml($thrownItem.descr()))</description>
+				</exception>
+#end
+#end
+#if ($n.hasAuth())
+				<authorize methodName="$n.getAuth().method()">
+#foreach( $authArg in $n.getAuth().args() )
+					<argument name="$authArg.value()" />
+#end
+				</authorize>
+#end
+#foreach( $param in $n.iterator() )
+				<field name="$param.name()" fieldId="$helper.id( $param )" fieldName="$param.fqname()" type="$helper.getNativeTypeName($param.type())" isPrimitiveType="$helper.isBasicType($param.type())" isArray="$param.type().isArray()" #if($param.type().isArray())dimension="$param.type().dim()"#end>
+#if ($param.descr().size() > 0)
+					<description>$helper.protectCData($helper.emitXml($param.descr()))</description>
+#end
+				</field>
+#end
+				<result #if (!$n.isOneway())fieldId="$helper.id( $n.getResultMessage() )" fieldName="$n.getResultMessage().fqname()"#end type="$helper.getNativeTypeName($n.type())" isPrimitiveType="$helper.isBasicType($n.type())"  isArray="$n.type().isArray()" #if($n.type().isArray())dimension="$n.type().dim()"#end>
+#if ($n.returnDescr().size() > 0)
+					<description>$helper.protectCData($helper.emitXml($n.returnDescr()))</description>
+#end
+				</result>
+			</method>
+			
+## --------------------------
+## result mixed-in message
+## --------------------------
+#if (!$n.isOneway())
+			<method name="$r.name()" typeId="$helper.id( $r )" typeName="$r.fqname()" asyncReceiverMode="$r.getAsyncReceiver().toString().toLowerCase()" isOneway="true" messageDirection="$r.msgDir().toString().toLowerCase()" timeout="$n.getTimeout()" responseField="result" >
+#if ($r.descr().size() > 0)
+				<description>$helper.protectCData($helper.emitXml($n.descr()))</description>
+#end
+#foreach( $param in $r.iterator() )
+				<field name="$param.name()" fieldId="$helper.id( $param )" fieldName="$param.fqname()" type="$helper.getNativeTypeName($param.type())" isPrimitiveType="$helper.isBasicType($param.type())" isArray="$param.type().isArray()" #if($param.type().isArray())dimension="$param.type().dim()"#end>
+#if ($param.descr().size() > 0)
+					<description>$helper.protectCData($helper.emitXml($param.descr()))</description>
+#end
+				</field>
+#end
+			</method>
+#end
+#end
+#end
+#end
+#end
+
+## ------ end mixin stuff here ------
+		</methods>
+## iterate over raw messages, and define them all here
+
+</service>
+</module>
+
+
diff --git a/build-support/NUnitToJUnit.xsl b/build-support/NUnitToJUnit.xsl
new file mode 100644
index 0000000..4c4a828
--- /dev/null
+++ b/build-support/NUnitToJUnit.xsl
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+    <xsl:output method="xml" indent="yes" encoding="utf-8" version="1.0" cdata-section-elements="failure" />
+
+    <xsl:template match="test-results/test-suite">
+
+        <xsl:variable name="testcases" select="//test-suite[./results/test-case]"/>
+        <!--
+        <xsl:variable name="asmClass">
+            <xsl:choose>
+                <xsl:when test="$testcases"><xsl:value-of select="$testcases[1]/../../@name"/></xsl:when>
+                <xsl:otherwise><xsl:value-of select="@name"/></xsl:otherwise>
+            </xsl:choose>
+        </xsl:variable>
+        -->
+        <testsuite name="NUnitTests" time="{@time}" tests="{count($testcases//test-case)}"
+            errors="" failures="{count($testcases//test-case/failure)}">
+
+            <xsl:for-each select="$testcases">
+
+                <xsl:variable name="suite" select="."/>
+                <xsl:variable name="generalfailure" select="./failure"/>
+                <xsl:for-each select=".//test-case">
+                
+                <xsl:variable name="testClass" select="concat(substring-before(./@name, ./../../@name), ./../../@name)" />
+                <xsl:variable name="testName" select="substring-after(./@name, concat($testClass,'.'))" />
+
+                <testcase classname="{$testClass}" name="{$testName}" time="{./@time}" >
+                
+                 
+                <xsl:if test="./failure">
+                <xsl:variable name="failstack" select="count(./failure/stack-trace/*) + count(./failure/stack-trace/text())"/>
+                <failure>
+                    <xsl:choose>
+                        <xsl:when test="$failstack &gt; 0 or not($generalfailure)">
+MESSAGE: <xsl:value-of select="./failure/message"/>
++++++++++++++++++++
+STACK TRACE: <xsl:value-of select="./failure/stack-trace"/>
+                        </xsl:when>
+                        <xsl:otherwise>
+MESSAGE: <xsl:value-of select="$generalfailure/message"/>
++++++++++++++++++++
+STACK TRACE: <xsl:value-of select="$generalfailure/stack-trace"/>
+                        </xsl:otherwise>
+                    </xsl:choose>
+                </failure>
+                </xsl:if>
+                </testcase>
+                </xsl:for-each>
+            </xsl:for-each>
+
+        </testsuite>
+
+    </xsl:template>
+
+</xsl:stylesheet>
diff --git a/build-support/README.txt b/build-support/README.txt
new file mode 100644
index 0000000..7f7d099
--- /dev/null
+++ b/build-support/README.txt
@@ -0,0 +1,5 @@
+Shared ant-targets and macros.
+
+Catch all, ant/build support stuff.
+
+
diff --git a/build-support/default_header.txt b/build-support/default_header.txt
new file mode 100644
index 0000000..6a354e0
--- /dev/null
+++ b/build-support/default_header.txt
@@ -0,0 +1,17 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
diff --git a/build-support/dependencies.xml b/build-support/dependencies.xml
new file mode 100644
index 0000000..846def9
--- /dev/null
+++ b/build-support/dependencies.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-dependencies" basedir="." default="check-all">
+    <description>Etch Dependencies</description>
+    <property name="Etch.basedir" location="${basedir}/.." />
+    
+    <!-- Load Environment -->
+    <property environment="env" />
+    
+    <!-- Load dependencies -->
+    <property file="${Etch.basedir}/build.dependencies" prefix="default" />
+    
+    <target name="check-javacc" >
+        <fail message="${default.javacc.home}/bin/lib/javacc.jar cannot be found. Please set 'javacc.home' in build.dependencies">
+            <condition>
+                <not><available file="${default.javacc.home}/bin/lib/javacc.jar" /></not>
+            </condition>
+        </fail>
+        <echo message="Using ${default.javacc.home}/bin/lib/javacc.jar ..." />
+    </target>
+    
+    <target name="check-junit">
+        <fail message="${default.junit.lib}/junit-4.3.1.jar cannot be found. Please set 'junit.lib' in build.dependencies">
+            <condition>
+                <not><available file="${default.junit.lib}/junit-4.3.1.jar" /></not>
+            </condition>
+        </fail>        
+        <echo message="Using ${default.junit.lib}/junit-4.3.1.jar ..." />
+    </target>
+    
+    <target name="check-velocity">
+        <fail message="${default.velocity.lib}/velocity-dep-1.5.jar cannot be found. Please set 'velocity.lib' in build.dependencies">
+            <condition>
+                <not><available file="${default.velocity.lib}/velocity-dep-1.5.jar" /></not>
+            </condition>
+        </fail>        
+        <echo message="Using ${default.velocity.lib}/velocity-dep-1.5.jar ..." />
+    </target>
+    
+    <target name="check-dotnet" >
+        <echo message="ANT-DOTNET" />
+    </target>
+    
+    <target name="check-all" depends="check-javacc,check-junit,check-velocity,check-dotnet" />
+    
+
+</project>
diff --git a/build-support/etch.common.xml b/build-support/etch.common.xml
new file mode 100644
index 0000000..76cf536
--- /dev/null
+++ b/build-support/etch.common.xml
@@ -0,0 +1,314 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch.common" basedir="." >
+
+    <!-- Static properties -->
+    <property name="Etch.copyrightNotice"    value="Copyright (c) 2007-2008 Cisco Systems, Inc. All rights reserved." />
+
+    <!-- Load Environment -->
+    <property environment="env" />
+    <property file="${Etch.basedir}/build.dependencies" prefix="build" />
+
+    <!-- Validate properties -->
+    
+    <!-- Compute top of tree -->
+    <condition property="Etch.basedir" value="${basedir}" >
+        <not><isset property="Etch.basedir" /></not>
+    </condition>
+    <property name="Etch.runtime.workspace" value="${Etch.basedir}" />
+
+    <!-- load runtime properties -->
+    <property prefix="Etch.property."      file="${Etch.basedir}/etch.properties" />
+    <property prefix="Etch.runtime."       file="${Etch.basedir}/bamboo.properties" />
+    
+    <!-- Compute version numbers -->
+    <condition property="Etch.property.majorVersion" value="0">
+        <not><isset property="Etch.property.majorVersion" /></not>
+    </condition>
+    <condition property="Etch.property.minorVersion" value="0" >
+        <not><isset property="Etch.property.minorVersion" /></not>
+    </condition>
+    <condition property="Etch.property.patchVersion" value="0" >
+        <not><isset property="Etch.property.patchVersion" /></not>
+    </condition>
+    <condition property="Etch.runtime.buildKey" value="LOCAL" >
+        <not><isset property="Etch.runtime.buildKey" /></not>
+    </condition>
+    <condition property="Etch.runtime.buildNumber" value="0" >
+        <not><isset property="Etch.runtime.buildNumber" /></not>
+    </condition>
+    <condition property="Etch.runtime.revisionNumber" value="0" >
+        <not><isset property="Etch.runtime.revisionNumber" /></not>
+    </condition>
+    <condition property="Etch.property.suffix" value="" >
+        <not><isset property="Etch.property.suffix" /></not>
+    </condition>
+
+    <property name="Etch.target"                location="${Etch.basedir}/target" />
+    <property name="Etch.dist"                  location="${Etch.target}/Installers/dist" />
+    <property name="Etch.clover-dist"           location="${Etch.target}/Installers/dist-clover" />
+    <property name="Etch.support"               location="${Etch.target}/Support/dist" />
+    <property name="Etch.clover-support"        location="${Etch.target}/Support/dist-clover" />
+
+    <property name="Etch.version"               value="${Etch.property.majorVersion}.${Etch.property.minorVersion}.${Etch.property.patchVersion}" />
+    <property name="Etch.longversion"           value="${Etch.version}${Etch.property.suffix}" />
+    <property name="Etch.longname"              value="apache-etch-${Etch.longversion}" />
+    <property name="Etch.shortversion"          value="${Etch.property.majorVersion}.${Etch.property.minorVersion}" />
+    <property name="Etch.buildTag"              value="${Etch.runtime.buildKey}-${Etch.runtime.buildNumber}" />
+    <property name="Etch.buildSupportDirectory" location="${Etch.basedir}/build-support" />
+    <property name="Etch.logDirectory"          location="${Etch.target}/BuildLogs" />
+    <property name="Etch.installerDirectory"    location="${Etch.target}/Installers" />
+
+    <condition property="Etch.runtime.tests.fail" value="${Etch.target}\fail">
+        <isset property="build.publish" />
+    </condition>
+
+    <!-- define artifacts -->
+    <property name="etch-compiler.jar"            value="etch-compiler-${Etch.version}.jar" />
+    <property name="etch-compiler-src.zip"        value="etch-compiler-${Etch.version}-src.zip" />
+    <property name="etch-java-compiler.jar"       value="etch-java-compiler-${Etch.version}.jar" />
+    <property name="etch-java-compiler-src.zip"   value="etch-java-compiler-${Etch.version}-src.zip" />
+    <property name="etch-java-runtime.jar"        value="etch-java-runtime-${Etch.version}.jar" />
+    <property name="etch-java-runtime-src.zip"    value="etch-java-runtime-${Etch.version}-src.zip" />
+    <property name="etch-csharp-compiler.jar"     value="etch-csharp-compiler-${Etch.version}.jar" />
+    <property name="etch-csharp-compiler-src.zip" value="etch-csharp-compiler-${Etch.version}-src.zip" />
+    <property name="etch-xml-compiler.jar"        value="etch-xml-compiler-${Etch.version}.jar" />
+    <property name="etch-xml-compiler-src.zip"    value="etch-xml-compiler-${Etch.version}-src.zip" />
+    <property name="etch-util.jar"                value="etch-util-${Etch.version}.jar" />
+    <property name="etch-util-src.zip"            value="etch-util-${Etch.version}-src.zip" />
+    <property name="etch-ant-task.jar"            value="etch-ant-plugin-${Etch.version}.jar" />
+    <property name="etch-ant-task-src.zip"        value="etch-ant-plugin-${Etch.version}-src.zip" />
+
+    <!-- Define filterset for build-time substitutions -->
+    <filterset id="Etch.buildTokens" >
+        <filter token="EtchVersion"               value="${Etch.version}" />
+        <filter token="EtchLongVersion"           value="${Etch.longversion}" />
+        <filter token="EtchLongName"              value="${Etch.longname}" />
+        <filter token="EtchBuildTag"              value="${Etch.buildTag}" />
+        <filter token="EtchRuntimeRevisionNumber" value="${Etch.runtime.revisionNumber}" />
+        <filter token="EtchRuntimeBuildKey"       value="${Etch.runtime.buildKey}" />
+        <filter token="EtchRuntimeBuildNumber"    value="${Etch.runtime.buildNumber}" />
+        <filter token="EtchMajorVersion"          value="${Etch.property.majorVersion}" />
+        <filter token="EtchMinorVersion"          value="${Etch.property.minorVersion}" />
+        <filter token="EtchPatchVersion"          value="${Etch.property.patchVersion}" />
+    </filterset>
+
+    <!-- TODO: Migrate to .NET tasks for ANT -->
+    <property name="tool.vs-2k5-task" value="${Etch.runtime.workspace}/scripts/vs-2k5-task.bat" />
+
+    <!-- NSIS installer support -->
+    <property name="tool.makensis"    value="${build.nsis.home}\makensis.exe" />
+    <condition property="NSIS.enabled">
+        <and>
+            <os family="windows" />
+            <available file="${tool.makensis}" />
+        </and>
+    </condition>
+    
+    <tempfile property="Etch.build.tmpdir" destdir="/tmp" />
+
+    <property   name="Etch.dependency.javacc.home" value="${build.javacc.home}" />
+    <property   name="Etch.dependency.junit.jar" location="${build.junit.lib}/junit-4.3.1.jar" />
+    <property   name="Etch.dependency.velocity.jar" value="${build.velocity.lib}/velocity-1.5.jar" />
+    <property   name="Etch.dependency.velocity-dep.jar" value="${build.velocity.lib}/velocity-dep-1.5.jar" />
+    <property   name="Etch.dependency.ant-dotnet-1.0.jar" value="${build.ant-dotnet.lib}/ant-dotnet-1.0.jar" />
+
+    <!-- Csharp Support -->
+    <condition property="USE.dotnet">
+        <and>
+            <os family="windows" />
+            <available file="${build.dotnet.home}/msbuild.exe" />
+        </and>
+    </condition>
+    <condition property="USE.mono">
+        <and>
+            <not><os family="windows" /></not>
+            <!-- TODO mono support is not fully baked, use -DUSE.mono to test -->
+            <!-- <available file="${build.mono.home}/bin/mdtool" /> -->
+            <isset property="USE.mono" />
+        </and>
+    </condition>
+    <condition property="BUILD.csharp">
+        <or>
+            <isset property="USE.dotnet" />
+            <isset property="USE.mono" />
+        </or>
+    </condition>
+    <property name="tool.mdtool" value="${build.mono.home}/bin/mdtool" />
+
+    <!-- clover support -->
+    <!-- TODO: make this toggle-able -->
+    <property name="With.clover" value="true" />
+    <condition property="Clover.enabled" >
+        <and>
+            <available file="${build.clover.home}/lib/clover.jar" />
+            <isset property="With.clover" />
+        </and>
+    </condition>
+    <property name="Etch.dependency.clover.jar" value="${build.clover.home}/lib/clover.jar" />
+    <taskdef resource="cloverlib.xml" classpath="${Etch.dependency.clover.jar}" />
+    <!-- If Clover is enabled, use the clover version of the Etch build, this
+         allows code-coverage metrics to be collected throughout the build process -->
+    <condition property="Etch.HOME" value="${Etch.clover-dist}" >
+        <istrue value="${Clover.enabled}" />
+    </condition>
+    <condition property="Etch.HOME" value="${Etch.dist}" >
+        <not><isset property="Etch.HOME" /></not>
+    </condition>
+    <condition property="Etch.SUPPORT" value="${Etch.clover-support}" >
+        <istrue value="${Clover.enabled}" />
+    </condition>
+    <condition property="Etch.SUPPORT" value="${Etch.support}" >
+        <not><isset property="Etch.SUPPORT" /></not>
+    </condition>
+    <property name="Clover.path" location="${Etch.clover-dist}/clover" />
+    <property name="Clover.db.path" location="${Clover.path}/db" />
+    <property name="Clover.db" location="${Clover.db.path}/clover.master.db" />
+    <property name="Clover.coverage" location="${Clover.path}/code-coverage-results" />
+    
+    <!-- properties for examples -->
+    <property name="EXAMPLE.etch.home" value="${Etch.dist}" />
+    <property name="EXAMPLE.etch.version" value="${Etch.version}" />
+    <property name="EXAMPLE.ant.dotnet.jar" value="${Etch.dependency.ant-dotnet-1.0.jar}" />
+    
+    <!-- csharp support -->
+    <taskdef onerror="report" resource="org/apache/ant/dotnet/antlib.xml" classpath="${Etch.dependency.ant-dotnet-1.0.jar}" />
+
+    <!-- dependencies -->
+    <!-- TODO: remove clover reference if clover-disabled -->
+    <path id="Etch.dependencies.jar.paths">
+        <pathelement location="${Etch.dependency.velocity-dep.jar}" />
+        <pathelement location="${Etch.dependency.junit.jar}" />
+        <pathelement location="${Etch.dependency.clover.jar}" />
+    </path>
+
+    <!-- macros -->
+    <macrodef name="build_component" >
+        <attribute name="root"     default="." />
+        <attribute name="dir"      />
+        <attribute name="target"   default="${Etch.build.target}" />
+        <attribute name="script"   default="build" />
+        <attribute name="antfile"  default="@{script}.xml" />
+        <attribute name="loglabel" default="@{dir}" />
+        <attribute name="output"   default="${Etch.logDirectory}/@{loglabel}.@{target}.txt" />
+        <element   name="componentAntElements" optional="true" implicit="true" />
+        <sequential>
+            <echo message="@{loglabel}.@{target}" />
+            <ant dir="@{root}/@{dir}" antfile="@{antfile}" inheritAll="false" inheritRefs="false" output="@{output}" target="@{target}">
+                <propertyset id="build-parameters">
+                    <propertyref name="DO.maven.install" />
+                    <propertyref name="build.tests.fail" />
+                </propertyset>
+                <componentAntElements />
+            </ant>
+        </sequential>
+    </macrodef>
+    
+    <macrodef name="build_example" >
+        <attribute name="root"     default="." />
+        <attribute name="dir"      />
+        <attribute name="script"   default="build" />
+        <attribute name="antfile"  default="@{script}.xml" />
+        <attribute name="loglabel" default="@{dir}" />
+        <attribute name="logdir"   default="logs" />
+        <attribute name="target"   default="${Etch.build.target}" />
+        <attribute name="output"   default="@{logdir}/@{loglabel}.txt" />
+        <element   name="componentAntElements" optional="true" implicit="true" />
+        <sequential>
+            <mkdir dir="@{logdir}" />
+            <echo message="@{loglabel}" />
+            <ant dir="@{root}/@{dir}" antfile="@{antfile}" inheritAll="false" inheritRefs="false" output="@{output}" target="@{target}">
+                <propertyset id="examples-parameters">
+                    <propertyref prefix="EXAMPLE" />
+                    <mapper type="glob" from="EXAMPLE.*" to="*" />
+                </propertyset>
+                <componentAntElements />
+            </ant>
+        </sequential>
+    </macrodef>    
+    
+
+    <!-- token filter macro -->
+    <macrodef name="update-tokens" >
+        <attribute name="filename" />
+        <attribute name="template" default="@{filename}.tmpl" />
+        <sequential>
+            <!-- Generate version info -->
+            <copy tofile="@{filename}" file="@{template}" overwrite="true">
+                <filterset refid="Etch.buildTokens" />
+            </copy>
+        </sequential>
+    </macrodef>
+
+    <!-- NSIS macro -->
+    <macrodef name="makensis">
+        <attribute name="root"        default="." />
+        <attribute name="dir"         default="." />
+        <attribute name="target"      default="${Etch.build.target}" />
+        <attribute name="script"      default="myscript" />
+        <attribute name="loglabel"    default="@{script}" />
+        <attribute name="destfile"    default="@{script}-setup.exe" />
+        <attribute name="version"     default="${Etch.version}" />
+        <attribute name="output"      default="${Etch.logsDirectory}/@{loglabel}.@{target}.txt" />
+        <attribute name="failonerror" default="false" />
+        <sequential>
+            <exec executable="${tool.makensis}" dir="@{root}/@{dir}" failonerror="@{failonerror}" >
+                <arg value="/V4" />
+                <arg value="/DPRODUCT_VERSION=@{version}" />
+                <arg value="/DOUT_FILE=@{destfile}" />
+                <arg value="@{script}.nsi" />
+            </exec>
+        </sequential>
+    </macrodef>
+    
+    <!-- Clover macro -->
+    <macrodef name="initialize-clover" >
+        <attribute name="enabled"     default="${Clover.enabled}" />
+        <attribute name="suffix"      default="none" />
+        <element   name="options"     implicit="true" /> 
+        <sequential>
+            <!-- TODO: do not make directories if clover is disabled -->
+            <mkdir dir="${Clover.db.path}/@{suffix}" />
+            <clover-setup 
+                    initstring="${Clover.db.path}/@{suffix}/clover.db"
+                    enabled="@{enabled}"
+                    source="1.5"
+                    flushpolicy="threaded"
+                    flushinterval="90000" >
+                <options />
+            </clover-setup>
+        </sequential>
+    </macrodef>
+
+    <!-- MONO mdtool macro -->
+    <macrodef name="mdtool">
+        <attribute name="dir"         default="." />
+        <attribute name="failonerror" default="false" />
+        <attribute name="project"     default="project.csproj" />
+        <attribute name="target"      default="${Etch.build.target}" />
+        <sequential>
+            <exec executable="${tool.mdtool}" dir="@{dir}" failonerror="@{failonerror}" >
+                <arg value="build" />
+                <arg value="--buildfile:@{project}" />
+            </exec>
+        </sequential>
+    </macrodef>
+
+</project>
diff --git a/build-support/etch.includes.xml b/build-support/etch.includes.xml
new file mode 100644
index 0000000..328044a
--- /dev/null
+++ b/build-support/etch.includes.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch.include" default="help" basedir=".">
+  <description>Etch Ant Include file</description>
+
+  <!-- Standard Properties shared by all sub-projects -->
+  <import file="etch.common.xml" />
+
+  <!-- Standard targets, do not modify or overload. Overload the "do-*" targets in each sub-project -->
+  <target name="debug"           depends="init-Debug,all" />
+  <target name="Debug"           depends="debug" />
+  <target name="release"         depends="init-Release,all" />
+  <target name="Release"         depends="release" />
+  <target name="clean"           depends="init-Clean,init,do-clean" />
+  <target name="Clean"           depends="clean" />
+  <target name="help"            depends="init-Help" />
+  <target name="Help"            depends="init-Help" />
+  <target name="debug-rebuild"   depends="Clean,Debug" />
+  <target name="release-rebuild" depends="Clean,Release" />
+
+  <target name="init-Help" depends="do-help">
+     <!-- Generic help message -->
+     <echo>
+     The following Generic targets are supported:
+        Debug           := Debug build
+        Release         := Release build
+        Clean           := Clean action
+        debug-rebuild   := Clean then Debug build
+        release-rebuild := Clean then Release build
+     </echo>
+  </target>
+
+  <target name="init-Debug">
+     <!-- Debug Target -->
+     <tstamp />
+     <property name="Etch.build.target"     value="Debug" />
+     <property name="Etch.javac.debug"      value="on" />
+     <property name="Etch.javac.optimize"   value="off" />
+  </target>
+
+  <target name="init-Release">
+    <!-- Release Target -->
+    <tstamp />
+    <property name="Etch.build.target"      value="Release" />
+    <property name="Etch.javac.debug"       value="on" />
+    <property name="Etch.javac.optimize"    value="off" />
+  </target>
+
+  <target name="init-Clean">
+     <!-- Clean Target -->
+     <property name="Etch.build.target"     value="Clean" />
+  </target>
+
+  <target name="property-init" >
+     <!-- Initialize target-specific properties --> 
+  </target>
+
+
+  <target name="init" depends="property-init,do-init">
+     <!-- Initialization Target -->
+  </target>
+
+  <target name="build" depends="init,do-build">
+     <!-- Build target -->
+  </target>
+
+  <target name="postbuild" depends="build,do-postbuild">
+     <!-- Post-build Target -->
+  </target>
+
+  <target name="test" depends="postbuild,do-test">
+     <!-- Test Target -->
+  </target>
+
+  <target name="posttest" depends="test" if="build.publish">
+    <!-- Posttest Target -->
+	<antcall target="do-publish"/>
+  </target>
+
+  <target name="all" depends="test,posttest">
+     <!-- all target -->
+  </target>
+
+  <!-- Overload these targets in each sub-project -->
+  <target name="do-init">
+    <!-- Use this target for any pre-build initialization
+         (directory creation, etc.), the following parameters will be defined
+         before this target is called:
+
+         Etch.build.target      :=  One of "Debug" or "Release"
+    -->
+    <echo message="No Initialization defined." />
+  </target>
+
+  <target name="do-build">
+    <!-- Use this target for the actual build
+         logic. "do-init" will be called before
+         this target.
+    -->
+  </target>
+
+  <target name="do-clean">
+    <!-- Use this target to implement any build-clean
+         logic. "do-init" will *not* be called before
+         this target.
+    -->
+    <echo message="No Clean target defined." />
+  </target>
+
+  <target name="do-postbuild">
+    <!-- Use this target to copy the build products
+         to the common workspace build dir, i.e. X:\Build.
+         The "do-build" target must complete successfully
+         before this target is called.
+    -->
+    <echo message="No Postbuild defined." />
+  </target>
+
+  <target name="do-test">
+    <!-- Use this target to execute unit tests -->
+    <echo message="No Unit Tests Defined." />
+  </target>
+
+  <target name="do-publish">
+	<!-- Use this target to publish the build
+         results but if the tests successfully
+         passed -->
+    <echo>No Publishing defined.</echo>
+  </target>
+
+  <target name="do-help">
+    <!-- Use this target to list any special targets
+         or help messages for the subproject.
+    -->
+    <echo>
+    The following special targets are supported:
+        None
+    </echo>
+  </target>
+
+</project>
diff --git a/build-support/realclean.bat b/build-support/realclean.bat
new file mode 100644
index 0000000..9ce9993
--- /dev/null
+++ b/build-support/realclean.bat
@@ -0,0 +1,24 @@
+@rem  Licensed to the Apache Software Foundation (ASF) under one   *
+@rem  or more contributor license agreements.  See the NOTICE file *
+@rem  distributed with this work for additional information        *
+@rem  regarding copyright ownership.  The ASF licenses this file   *
+@rem  to you under the Apache License, Version 2.0 (the            *
+@rem  "License"); you may not use this file except in compliance   *
+@rem  with the License.  You may obtain a copy of the License at   *
+@rem                                                               *
+@rem    http://www.apache.org/licenses/LICENSE-2.0                 *
+@rem                                                               *
+@rem  Unless required by applicable law or agreed to in writing,   *
+@rem  software distributed under the License is distributed on an  *
+@rem  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+@rem  KIND, either express or implied.  See the License for the    *
+@rem  specific language governing permissions and limitations      *
+@rem  under the License.                                           *
+call ant clean
+
+del binding-csharp\compiler\src\main\java\etch\bindings\csharp\compiler\CompilerVersion.java
+del binding-xml\compiler\src\main\java\etch\bindings\xml\compiler\CompilerVersion.java
+del binding-java\compiler\src\main\java\etch\bindings\java\compiler\CompilerVersion.java
+del compiler\src\main\java\etch\compiler\Version.java
+del binding-csharp\runtime\src\main\csharp\Properties\AssemblyInfo.cs
+svn update .
diff --git a/build-support/realclean.sh b/build-support/realclean.sh
new file mode 100755
index 0000000..4b76f55
--- /dev/null
+++ b/build-support/realclean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+#  Licensed to the Apache Software Foundation (ASF) under one   *
+#  or more contributor license agreements.  See the NOTICE file *
+#  distributed with this work for additional information        *
+#  regarding copyright ownership.  The ASF licenses this file   *
+#  to you under the Apache License, Version 2.0 (the            *
+#  "License"); you may not use this file except in compliance   *
+#  with the License.  You may obtain a copy of the License at   *
+#                                                               *
+#    http://www.apache.org/licenses/LICENSE-2.0                 *
+#                                                               *
+#  Unless required by applicable law or agreed to in writing,   *
+#  software distributed under the License is distributed on an  *
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+#  KIND, either express or implied.  See the License for the    *
+#  specific language governing permissions and limitations      *
+#  under the License.                                           *
+ant clean
+find . -name 'CompilerVersion.java' -exec rm -f {} \;
+rm -f compiler/src/main/java/etch/compiler/Version.java
+rm -f binding-csharp/runtime/src/main/csharp/Properties/AssemblyInfo.cs
+svn update .
+
diff --git a/build.dependencies b/build.dependencies
new file mode 100644
index 0000000..3ba90a8
--- /dev/null
+++ b/build.dependencies
@@ -0,0 +1,45 @@
+# Licensed to the Apache Software Foundation (ASF) under one   *

+# or more contributor license agreements.  See the NOTICE file *

+# distributed with this work for additional information        *

+# regarding copyright ownership.  The ASF licenses this file   *

+# to you under the Apache License, Version 2.0 (the            *

+# "License"); you may not use this file except in compliance   *

+# with the License.  You may obtain a copy of the License at   *

+#                                                              *

+#   http://www.apache.org/licenses/LICENSE-2.0                 *

+#                                                              *

+# Unless required by applicable law or agreed to in writing,   *

+# software distributed under the License is distributed on an  *

+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+# KIND, either express or implied.  See the License for the    *

+# specific language governing permissions and limitations      *

+# under the License.                                           *

+

+##

+## Core Dependencies .. these must be set

+##

+

+javacc.home=${env.TOOLS_DIR}/javacc/4.0

+junit.lib=${env.TOOLS_DIR}/junit/4.3.1

+velocity.lib=${env.TOOLS_DIR}/velocity/1.5

+

+##

+## Optional Dependencies

+##

+

+## NSIS

+nsis.home=${env.NSIS_HOME}

+

+## Clover

+clover.home=${env.CLOVER_HOME}

+

+## Csharp support

+ant-dotnet.lib=${env.TOOLS_DIR}/apache-ant-dotnet/1.0

+nunit.home=${env.NUNIT_HOME}

+

+# Set to the .NET 2.0 framework install

+dotnet.home=${env.windir}/Microsoft.NET/Framework/v2.0.50727

+

+# MONO support still a bit flakey

+mono.home=${env.MONO_HOME}

+

diff --git a/build.xml b/build.xml
new file mode 100755
index 0000000..c7d6f6c
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+-->
+<project name="etch" default="debug" basedir=".">
+    <description>Master build script for Etch</description>
+    <import file="build-support/etch.common.xml" />
+
+    <!-- standard, supported targets -->
+    <target name="Debug"         depends="debug" />
+    <target name="Release"       depends="release" />
+    <target name="Clean"         depends="clean" />
+    <target name="debug"         depends="init-debug,component-all,post-debug"   />
+    <target name="release"       depends="init-release,component-all,post-release" />
+    <target name="clean"         depends="init-clean,component-all,post-clean" />
+    <target name="realclean"     depends="clean,extra-clean" />
+    <target name="maven-install" depends="init-maven,release" />
+
+    <!-- Execute a clean, then 'debug' build -->
+    <target name="rebuild-debug">
+        <ant target="clean" />
+        <ant target="debug" />
+    </target>
+
+    <!-- Execute a clean, then 'release' build -->
+    <target name="rebuild-release">
+        <ant target="clean" />
+        <ant target="release" />
+    </target>
+
+    <!-- Execute a clean, then 'release' and then maven snapshot install (e.g. like running 'mvn clean install') -->
+    <target name="rebuild-maven-install">
+        <ant target="clean" />
+        <ant target="maven-install" />
+    </target>
+
+    <!-- framework targets, do not call these directly -->
+
+    <target name="init-maven" >
+        <property name="DO.maven.install" value="true" />
+    </target>
+
+    <target name="validate-dependencies" >
+        <tstamp />
+        <build_component dir="build-support" target="check-all" script="dependencies" />
+        
+        <echo message="Workspace: ${Etch.basedir}" />
+        <echo message="SVN Revision: ${Etch.runtime.revisionNumber}" />
+        <echo message="Version: ${Etch.property.majorVersion}.${Etch.property.minorVersion}" />
+        <echo message="BuildKey: ${Etch.runtime.buildKey}" />
+        <echo message="BuildNumber: ${Etch.runtime.buildNumber}" />
+        <echo message="LogDir: ${Etch.logDirectory}" />
+        <echo message="InstallDir: ${Etch.installerDirectory}" />
+        <mkdir dir="${Etch.logDirectory}" />
+    </target>
+
+    <target name="init-debug" depends="validate-dependencies,do-clover-init" >
+        <property name="Etch.build.target" value="Debug" />
+        <property name="Etch.javac.debug" value="on" />
+        <property name="Etch.javac.optimize" value="off" />
+    </target>
+
+    <target name="post-debug" depends="do-clover-report">
+    </target>
+
+    <target name="init-release" depends="validate-dependencies,do-clover-init">
+        <!-- For now, keep debug-symbols and no-optimize, even for release builds -->
+        <property name="Etch.build.target" value="Release" />
+        <property name="Etch.javac.debug"  value="on" />
+        <property name="Etch.javac.optimize" value="off" />
+        <!--
+        <property name="Etch.javac.debug"  value="off" />
+        <property name="Etch.javac.optimize" value="on" />
+        -->
+    </target>
+    
+    <target name="post-release" depends="do-clover-report">
+    </target>
+
+    <target name="do-clover-init" >
+    </target>
+        
+    <target name="do-clover-report" if="Clover.enabled" >
+        <!-- Generate Coverage Report -->
+        <mkdir dir="${Clover.coverage}" />
+        
+        <clover-merge initString="${Clover.db}">
+            <cloverDbSet dir="${Clover.db.path}">
+                <include name="**/clover.db" />
+            </cloverDbSet>
+        </clover-merge>
+        
+        <!-- TODO: implement a toggle for the PDF report -->
+        <!-- <clover-pdf-report initstring="${Clover.db}" outfile="${Clover.coverage}/coverage.pdf" />  -->
+        
+        <clover-report initstring="${Clover.db}" >
+            <current alwaysReport="true" outfile="${Clover.coverage}/coverage.xml">
+                <format type="xml"/>
+            </current>
+        </clover-report>
+
+        <!-- Clean Clover DB -->
+        <!-- <clover-clean initstring="${Clover.db}" keepdb="false" /> -->
+    </target>
+
+
+    <target name="init-clean" depends="validate-dependencies">
+        <property name="Etch.build.target" value="Clean" />
+    </target>
+
+    <target name="post-clean" >
+        <echo message="Executing clean" />
+        <delete quiet="true" dir="${Etch.target}" />
+    </target>
+
+    <target name="extra-clean">
+        <!-- remove files that were overwritten by the filtered copy -->
+        <!--
+        <delete file="compiler/src/main/java/org/apache/etch/compiler/Version.java" />
+        <delete file="binding-java/compiler/src/main/java/org/apache/etch/bindings/java/compiler/CompilerVersion.java" />
+        <delete file="binding-xml/compiler/src/main/java/org/apache/etch/bindings/xml/compiler/CompilerVersion.java" />
+        <delete file="binding-csharp/compiler/src/main/java/org/apache/etch/bindings/csharp/compiler/CompilerVersion.java" />
+        <delete file="binding-csharp/runtime/src/main/csharp/Properties/AssemblyInfo.cs" />
+        -->
+    </target>    
+
+    <!-- Component targets; Add to this set -->
+
+    <target name="component-all" >
+        <!-- Core -->
+        <build_component dir="util" />
+        <build_component dir="compiler" />
+        
+        <!-- IDE/tool plugins -->
+        <build_component dir="plugins/ant" />
+        
+        <!-- Bindings -->
+        <build_component dir="binding-xml" />
+        <build_component dir="binding-java" />
+        <build_component dir="binding-csharp" />
+        
+        <!-- Examples -->
+        <build_component dir="examples" />
+        
+        <!-- Functional Tests -->
+        <build_component dir="tests" />
+        
+        <!-- Installer/zip Bundles -->
+        <build_component dir="installers" />
+    </target>
+
+</project>
diff --git a/compiler/build.xml b/compiler/build.xml
new file mode 100644
index 0000000..9b5d364
--- /dev/null
+++ b/compiler/build.xml
@@ -0,0 +1,308 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-compiler" basedir="." default="help">
+    <description>Common utilities for compiler implementations and java binding</description>
+    <property name="Etch.basedir" location="${basedir}/.." />
+    <import file="${Etch.basedir}/build-support/etch.includes.xml" />
+
+    <!-- Static properties of the sub-project -->
+    <property name="proj"                 location="${Etch.basedir}/compiler" />
+    <property name="target"               location="${proj}/target" />
+    <property name="src"                  location="${proj}/src" />
+    <property name="generatedSrc"         location="${target}/generated-sources" />
+    <property name="classesDirectory"     location="${target}/classes" />
+    <property name="resourcesDirectory"   location="${target}/resources" />
+    <property name="testResultsDirectory" location="${target}/test-results" />
+
+    <!-- MACRO: init-target -->
+    <macrodef name="init-target" >
+        <sequential>
+            <delete dir="${classesDirectory}" failonerror="false" quiet="true" />
+            <mkdir dir="${classesDirectory}" />
+            <mkdir dir="${classesDirectory}/main" />
+            <mkdir dir="${classesDirectory}/test" />
+            <mkdir dir="${resourcesDirectory}" />
+            <mkdir dir="${testResultsDirectory}" />
+        </sequential>
+    </macrodef>
+
+    <!-- MACRO: compile-sources -->
+    <macrodef name="compile-sources" >
+        <attribute name="support" default="${Etch.support}" />
+        <sequential>
+            <mkdir dir="${classesDirectory}/main" />
+            <mkdir dir="${classesDirectory}/test" />
+
+            <!-- compile main -->
+            <javac  debug="${Etch.javac.debug}"
+                    target="1.5"
+                    optimize="${Etch.javac.optimize}"
+                    destdir="${classesDirectory}/main" >
+                <src path="${src}/main/java" />
+                <src path="${generatedSrc}/main/javacc/java" />
+                <exclude name="**/.svn/**" />
+                <classpath refid="Etch.dependencies.jar.paths" />
+                <classpath>
+                    <pathelement location="@{support}/lib/${etch-util.jar}" />
+                </classpath>
+            </javac>
+
+            <!-- main-resources -->
+            <copy todir="${classesDirectory}/main">
+                <fileset dir="${src}/main/resources">
+                    <include name="**" />
+                </fileset>
+            </copy>            
+
+            <!-- compile test -->
+            <javac  debug="${Etch.javac.debug}"
+                    target="1.5"
+                    optimize="${Etch.javac.optimize}"
+                    destdir="${classesDirectory}/test" >
+                <src path="${src}/test/java" />
+                <exclude name="**/.svn/**" />
+                <classpath refid="Etch.dependencies.jar.paths" />
+                <classpath>
+                    <pathelement location="${classesDirectory}/main" />
+                    <pathelement location="@{support}/lib/${etch-util.jar}" />
+                </classpath>
+            </javac>
+
+            <!-- test-resources -->
+            <copy todir="${classesDirectory}/test">
+                <fileset dir="${src}/test/resources">
+                    <include name="**" />
+                </fileset>
+            </copy>            
+
+        </sequential>
+    </macrodef>
+
+    <!-- MACRO: bundle-jars -->
+    <macrodef name="bundle-jars" >
+        <attribute name="dist" default="${Etch.dist}" />
+        <attribute name="support" default="${Etch.support}" />
+        <sequential>
+            <mkdir dir="@{dist}/lib" />
+            <mkdir dir="@{support}/lib" />
+
+            <!-- Copy 3rd party dependencies -->
+            <copy todir="@{dist}/lib" file="${Etch.dependency.velocity-dep.jar}" />
+            <copy todir="@{support}/lib" file="${Etch.dependency.velocity-dep.jar}" />
+
+            <!-- CREATE jars -->
+
+            <!-- Package up etch-compiler jar -->
+            <jar jarfile="@{support}/lib/${etch-compiler.jar}" >
+                <manifest>
+                    <attribute name="Copyright"    value="${Etch.copyrightNotice}" />
+                    <attribute name="Version"      value="${Etch.version}" />
+                    <attribute name="LongVersion"  value="${Etch.longversion}" />
+                    <attribute name="Build-Tag"    value="${Etch.buildTag}" />
+                    <attribute name="SVN-Revision" value="${Etch.runtime.revisionNumber}" />
+                    <attribute name="Class-Path"   value="${etch-util.jar}" />
+                    <attribute name="Main-Class"   value="etch.compiler.EtchMain" />
+                </manifest>
+                <metainf dir="${Etch.basedir}" >
+                    <include name="NOTICE.txt" />
+                    <include name="LICENSE.txt" />
+                </metainf>
+                <fileset dir="${classesDirectory}/main">
+                    <include name="org/apache/etch/compiler/**" />
+                    <!-- <include name="resources/**" /> -->
+                </fileset>
+            </jar>
+
+            <!-- placeholder -->
+            <jar jarfile="@{support}/lib/${etch-util.jar}" update="true" filesetmanifest="merge">
+               <manifest>
+                  <attribute name="Version" value="${Etch.version}" />
+               </manifest>   
+            </jar>
+
+            <!-- CREATE source archives -->
+
+            <!-- package up etch-compiler source -->
+            <zip destfile="@{support}/lib/${etch-compiler-src.zip}" >
+                <fileset dir="${src}/main/java" >
+                    <include name="org/apache/etch/compiler/**/*.java" />
+                </fileset>
+                <fileset dir="${src}/main/resources" >
+                    <include name="**/*.kwd" />
+                </fileset>
+            </zip>
+            
+            <mkdir dir="${target}/empty-dir" />           
+            <zip destfile="@{support}/lib/${etch-util-src.zip}" update="true" whenempty="create" basedir="${target}/empty-dir"/>
+
+            <!-- Copy batch-scripts -->
+            <mkdir dir="@{dist}/bin" />
+            <copy  file="${src}/main/scripts/etch.sh" tofile="@{dist}/bin/etch" />
+            <chmod file="@{dist}/bin/etch" perm="755" />
+            <copy  file="${src}/main/scripts/etch.bat" todir="@{dist}/bin" />
+
+        </sequential>
+    </macrodef>
+
+    <!-- MACRO: update-jars -->
+    <macrodef name="update-jars" >
+        <attribute name="dist" default="${Etch.dist}" />
+        <attribute name="support" default="${Etch.support}" />
+        <sequential>
+            <!-- repackage .jar -->
+            <mkdir dir="@{dist}/lib" />
+
+            <delete dir="${target}/tmp-compiler" quiet="true" />
+            <mkdir dir="${target}/tmp-compiler" />
+
+            <unjar src="@{support}/lib/${etch-util.jar}"     dest="${target}/tmp-compiler" />
+            <unjar src="@{support}/lib/${etch-compiler.jar}" dest="${target}/tmp-compiler" />
+
+            <jar jarfile="@{dist}/lib/${etch-compiler.jar}" update="true" filesetmanifest="merge" >
+                <fileset dir="${target}/tmp-compiler"  />
+            </jar>
+            
+            <!-- repackage .zip src -->
+            <mkdir dir="@{dist}/lib" />
+
+            <delete dir="${target}/tmp-compiler-src" quiet="true" />
+            <mkdir dir="${target}/tmp-compiler-src" />
+            
+            <unzip src="@{support}/lib/${etch-util-src.zip}" dest="${target}/tmp-compiler-src" />
+            <unzip src="@{support}/lib/${etch-compiler-src.zip}" dest="${target}/tmp-compiler-src" />
+            <zip destfile="@{dist}/lib/${etch-compiler-src.zip}" >
+                <fileset dir="${target}/tmp-compiler-src" />
+            </zip>
+            
+        </sequential>
+    </macrodef>
+
+    <!-- INIT TARGET -->
+    <!-- Modify this target to define project specific properties that can only be set at runtime -->
+    <target name="do-init">
+        <delete dir="${target}" failonerror="false" quiet="true" />
+        <mkdir dir="${target}" />
+        <mkdir dir="${generatedSrc}" />
+        <mkdir dir="${classesDirectory}" />
+        <mkdir dir="${resourcesDirectory}" />
+        <mkdir dir="${testResultsDirectory}" />
+    </target>
+
+    <!-- CLEAN TARGET -->
+    <target name="do-clean">
+        <delete dir="${target}" />
+    </target>
+
+    <!-- BUILD TARGET -->
+
+    <target name="generate-sources" >
+        <!-- Generate version info -->
+        <update-tokens filename="${src}/main/java/org/apache/etch/compiler/Version.java" />
+
+        <!-- Generate Parser -->
+        <mkdir dir="${generatedSrc}/main/javacc/java/org/apache/etch/compiler" />
+        <javacc
+            target="${src}/main/javacc/EtchGrammar.jj"
+            javacchome="${Etch.dependency.javacc.home}"
+            outputdirectory="${generatedSrc}/main/javacc/java/org/apache/etch/compiler"
+        />
+    </target>
+
+    <target name="compile-for-dist" >
+        <!-- Initialize target directories -->
+        <init-target />
+
+        <!-- Compile Source -->
+        <compile-sources support="${Etch.support}" />
+
+        <!-- Bundle Jars -->
+        <bundle-jars dist="${Etch.dist}" support="${Etch.support}" />
+        
+        <!-- Update Jars -->
+        <update-jars dist="${Etch.dist}" support="${Etch.support}" />
+    </target>
+
+    <!-- compile for unit-testing -->
+    <target name="compile-for-clover" if="Clover.enabled" >
+
+        <echo message="Rebuilding with clover" />
+
+        <!-- initialize-clover -->
+        <initialize-clover suffix="compiler">
+            <fileset dir="${src}/main/java">
+                <include name="**/*.java" />
+            </fileset>
+            <testsources dir="${src}/test/java">
+                <include name="**/*.java" />
+            </testsources>
+        </initialize-clover>
+
+        <!-- Initialize target directories -->
+        <init-target />
+
+        <!-- Compile Source -->
+        <compile-sources support="${Etch.support}" />
+
+        <!-- Bundle Jars -->
+        <bundle-jars dist="${Etch.clover-dist}" support="${Etch.clover-support}" />
+
+        <!-- Update Jars -->
+        <update-jars dist="${Etch.clover-dist}" support="${Etch.clover-support}" />
+
+    </target>
+
+    <target name="do-build" depends="generate-sources,compile-for-dist,compile-for-clover" />
+
+    <!-- TEST TARGET -->
+    <target name="do-test">
+
+        <!-- Run Unit Tests -->
+        <junit printsummary="yes" haltonfailure="no" dir="${classesDirectory}"
+            errorProperty="build.tests.fail" failureProperty="build.tests.fail">
+            <classpath>
+                <pathelement location="${classesDirectory}/main" />
+                <pathelement location="${classesDirectory}/test" />
+                <pathelement location="${Etch.dependency.junit.jar}" />
+                <pathelement location="${Etch.dependency.velocity-dep.jar}" />
+                <pathelement location="${Etch.SUPPORT}/lib/${etch-util.jar}" />
+                <!-- TODO: remove if clover not available -->
+                <pathelement location="${Etch.dependency.clover.jar}"/>
+            </classpath>
+            <formatter type="xml"/>
+            <batchtest fork="true" todir="${testResultsDirectory}">
+                <fileset dir="${src}/test/java">
+                    <include name="org/apache/etch/compiler/**/Test*.java" />
+                    <!-- TODO: Move TestEtch to Java binding -->
+                    <exclude name="**/TestEtch.java" />
+                </fileset>
+            </batchtest>
+        </junit>
+    </target>
+
+    <!-- POSTBUILD TARGET -->
+    <target name="do-postbuild">
+    </target>
+
+    <target name="do-publish" if="build.tests.fail">
+        <!-- Set flag file if any tests failed -->
+        <touch file="${Etch.runtime.tests.fail}"/>
+    </target>
+
+</project>
diff --git a/compiler/src/main/java/org/apache/etch/compiler/AbstractLogHandler.java b/compiler/src/main/java/org/apache/etch/compiler/AbstractLogHandler.java
new file mode 100644
index 0000000..a03f1f2
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/AbstractLogHandler.java
@@ -0,0 +1,201 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+import java.util.Stack;
+
+import org.apache.etch.util.Assertion;
+
+
+
+/**
+ * Abstract implementation of LogHandler. Subclasser must implement
+ * final disposition of the message.
+ */
+abstract public class AbstractLogHandler implements LogHandler
+{
+	protected AbstractLogHandler()
+	{
+		this( null );
+	}
+	
+	protected AbstractLogHandler( String initialPhase )
+	{
+		setPhase( initialPhase );
+	}
+	
+	private String phase;
+
+	private int errorCount;
+
+	private int warningCount;
+
+	private String source;
+
+	private int logLevel = LEVEL_INFO;
+
+	private Stack<LogHandler.History> history = new Stack<LogHandler.History>();
+
+	final public int getLevel()
+	{
+		return logLevel;
+	}
+
+	final public void setLevel( int level )
+	{
+		checkLevel( level );
+		logLevel = level;
+	}
+
+	final public String getPhase()
+	{
+		return phase;
+	}
+
+	final public void setPhase( String phase )
+	{
+		this.phase = phase;
+	}
+
+	final public boolean hasError()
+	{
+		return errorCount > 0;
+	}
+
+	final public int errorCount()
+	{
+		return errorCount;
+	}
+
+	final public boolean hasWarning()
+	{
+		return warningCount > 0;
+	}
+
+	final public int warningCount()
+	{
+		return warningCount;
+	}
+
+	final public void report( int level, String fmt, Object ... params )
+	{
+		report( level, null, fmt, params );
+	}
+
+	final public void report( int level, Integer lineNumber, String fmt,
+		Object ... params )
+	{
+		report( level, lineNumber, String.format( fmt, params ) );
+	}
+
+	final public void logMessage( int level, Token token, String msg )
+	{
+		report( level, token.beginLine, msg );
+	}
+
+	final public void report( int level, Integer lineNumber, String msg )
+	{
+		checkLevel( level );
+		
+		if (level == LEVEL_ERROR)
+			errorCount++;
+		
+		if (level == LEVEL_WARNING)
+			warningCount++;
+		
+		if (isInteresting( level ))
+			log( new Message( level, phase, source, lineNumber, msg.trim(),
+				getHistory() ) );
+	}
+
+	/**
+	 * Logs a message which has already been deemed interesting based on
+	 * its level. Subclasser might print the message or put it into a list.
+	 * @param message
+	 */
+	abstract protected void log( Message message );
+
+	private LogHandler.History[] getHistory()
+	{
+		if (history.isEmpty())
+			return null;
+		
+		return history.toArray( new LogHandler.History[history.size()] );
+	}
+
+	private void checkLevel( int level )
+	{
+		Assertion.check( LEVEL_IMPORTANT < LEVEL_INFO,
+			"LEVEL_IMPORTANT < LEVEL_INFO" );
+		
+		if (level < LEVEL_IMPORTANT || level > LEVEL_INFO)
+			throw new IllegalArgumentException(
+				"level < LEVEL_IMPORTANT || level > LEVEL_INFO" );
+	}
+
+	final public boolean isInteresting( int level )
+	{
+		Assertion.check( level >= LEVEL_IMPORTANT && level <= LEVEL_INFO,
+			"level >= LEVEL_IMPORTANT && level <= LEVEL_INFO" );
+		return level <= logLevel;
+	}
+
+	final public void pop( String oldSource )
+	{
+		if (oldSource == null || oldSource.length() == 0)
+			throw new IllegalArgumentException(
+				"oldSource is null or empty" );
+		
+		if (!oldSource.equals( source ))
+			throw new IllegalArgumentException(
+				"oldSource does not match last push" );
+		
+		if (!history.isEmpty())
+		{
+			LogHandler.History h = history.pop();
+			source = h.source;
+		}
+		else
+		{
+			source = null;
+		}
+	}
+
+	final public void push( String newSource, Integer lineNumberInOldSource )
+	{
+		if (newSource == null || newSource.length() == 0)
+			throw new IllegalArgumentException(
+				"newSource is null or empty" );
+		
+		if (source == null && lineNumberInOldSource != null)
+			throw new IllegalArgumentException(
+				"line number must be null for initial source" );
+		
+		if (source != null && lineNumberInOldSource == null)
+			throw new IllegalArgumentException(
+				"line number cannot be null for nested source" );
+		
+		if (lineNumberInOldSource != null)
+			history.push( new LogHandler.History( source, lineNumberInOldSource ) );
+		
+		source = newSource;
+	}
+}
\ No newline at end of file
diff --git a/compiler/src/main/java/org/apache/etch/compiler/Backend.java b/compiler/src/main/java/org/apache/etch/compiler/Backend.java
new file mode 100644
index 0000000..fe0b784
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/Backend.java
@@ -0,0 +1,689 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.apache.etch.compiler.ast.Message;
+import org.apache.etch.compiler.ast.MessageDirection;
+import org.apache.etch.compiler.ast.Module;
+import org.apache.etch.compiler.ast.Name;
+import org.apache.etch.compiler.ast.Named;
+import org.apache.etch.compiler.ast.Opt;
+import org.apache.etch.compiler.ast.ParamList;
+import org.apache.etch.compiler.ast.Service;
+import org.apache.etch.compiler.ast.TypeRef;
+import org.apache.etch.compiler.opt.Extern;
+import org.apache.etch.util.Assertion;
+
+
+/**
+ * Generic interface to language (or language/runtime) bindings.
+ */
+abstract public class Backend
+{
+	private final static String tmplPath1 = "org/apache/etch/compiler/";
+	private final static String tmplPath2 = "resources/org/apache/etch/compiler/";
+	
+	//////////////////////////
+	// WHAT DIRECTION GROUP //
+	//////////////////////////
+	
+	/**
+	 * Constant for option --what: generate both client and server files.
+	 */
+	public static final String WHAT_BOTH = "BOTH";
+	
+	/**
+	 * Constant for option --what: generate client files.
+	 */
+	public static final String WHAT_CLIENT = "CLIENT";
+	
+	/**
+	 * Constant for option --what: generate generate server files.
+	 */
+	public static final String WHAT_SERVER = "SERVER";
+
+	//////////////////////
+	// WHAT FILES GROUP //
+	//////////////////////
+	
+	/**
+	 * Constant for option --what: generate all files.
+	 */
+	public static final String WHAT_ALL = "ALL";
+	
+	/**
+	 * Constant for option --what: generate no files.
+	 */
+	public static final String WHAT_NONE = "NONE";
+	
+	/**
+	 * Constant for option --what: generate intf files.
+	 */
+	public static final String WHAT_INTF = "INTF";
+	
+	/**
+	 * Constant for option --what: generate main file.
+	 */
+	public static final String WHAT_MAIN = "MAIN";
+	
+	/**
+	 * Constant for option --what: generate impl files.
+	 */
+	public static final String WHAT_IMPL = "IMPL";
+
+	/////////////////////
+	// WHAT MISC GROUP //
+	/////////////////////
+	
+	/**
+	 * Constant for option --what: overwrite template files.
+	 */
+	public static final String WHAT_FORCE = "FORCE";
+	
+	/**
+	 * Constant for option --what: give help on what.
+	 */
+	public static final String WHAT_HELP = "HELP";
+	
+	/**
+	 * Constructs the Backend.
+	 * @throws Exception
+	 */
+	protected Backend()
+		throws Exception
+	{
+		String[] path = { tmplPath1, tmplPath2 };
+		global_kwd = getPath(path, "globalKeywords.kwd");
+	}
+
+	/**
+	 * Path to global keyword resource.
+	 */
+	protected final String global_kwd;
+
+	@Override
+	public String toString()
+	{
+		return getLang();
+	}
+
+	/**
+	 * Generates code for this binding of the idl.
+	 * @param module the module that we are generating code for.
+	 * @param options the options used to configure the compiler.
+	 * @throws Exception
+	 */
+	abstract public void generate( Module module, CmdLineOptions options )
+		throws Exception;
+
+	/**
+	 * Runs the generator for a particular file with the specified
+	 * output stream.
+	 */
+	public interface Gen
+	{
+		/**
+		 * @param pw
+		 * @throws Exception
+		 */
+		void run( PrintWriter pw ) throws Exception;
+	}
+
+	/**
+	 * Helper method.  Return true if the md is SERVER.
+	 * @param md
+	 * @return true if MessageDirection is SERVER.
+	 */
+	public boolean isServer(MessageDirection md)
+	{
+		if (md == null)
+			throw new NullPointerException( "md == null" );
+		return md == MessageDirection.SERVER;
+	}
+
+	/**
+	 * Helper method.  Return true if the md is CLIENT.
+	 * @param md
+	 * @return true if MessageDirection is CLIENT.
+	 */
+	public boolean isClient(MessageDirection md)
+	{
+		if (md == null)
+			throw new NullPointerException( "md == null" );
+		return md == MessageDirection.CLIENT;
+	}
+
+	/**
+	 * Helper methods. Return true if the md is BOTH.
+	 * @param md
+	 * @return true if MessageDirection is BOTH.
+	 */
+	public boolean isBoth( MessageDirection md )
+	{
+		if ( md == null )
+			throw new NullPointerException( "md == null" );
+		return md == MessageDirection.BOTH;
+	}
+
+	/**
+	 * Returns the correct path to a resource.
+	 * @param path the paths to try for opening the resources
+	 * @param fn the file name of the file to open
+	 * @return the correct path to a resource
+	 * @throws FileNotFoundException
+	 */
+	protected String getPath(String[] path, String fn)
+		throws FileNotFoundException
+	{
+		for (String p: path)
+		{
+			if (p == null)
+				continue;
+			
+			String s = p + fn;
+//			System.out.println( "trying "+s );
+			
+			try
+			{
+				URL temp = getClass().getClassLoader().getResource(s);
+				if (temp != null)
+						return s;
+			}
+			catch ( Exception e )
+			{
+				// ignore
+//				System.out.println( "ignoring "+e );
+			}
+		}
+		throw new FileNotFoundException(fn);
+	}
+
+	/**
+	 * Creates (or deletes) the specified file.
+	 * @param dir
+	 * @param fn
+	 * @param gen
+	 * @throws Exception
+	 */
+	protected void doFile( Output dir, String fn, LogHandler lh, Gen gen )
+		throws Exception
+	{
+		PrintWriter pw = new PrintWriter( dir.newOutputStream( fn ) );
+		try
+		{
+			gen.run( pw );
+		}
+		finally
+		{
+			pw.close();
+		}
+	}
+
+	/**
+	 * Augments the mapping from user defined reserved words to the reserved
+	 * words used by the compiler as parsed from a reserved word list stored in
+	 * a file located at the specified path.
+	 * @param filePath the path to the file containing reserved word mapping
+	 * @param wordMap
+	 * @throws FileNotFoundException
+	 * @throws IOException
+	 */
+	protected void mapWords(String filePath, Map<String, String> wordMap)
+		throws FileNotFoundException, IOException
+	{
+		String commentMarker = "#";
+		String valuePrefix = "x";
+		String keyValueDelimeter = "= \t";
+
+		// Open file for parsing or throw an FileNotFoundError if resources is
+		// unavailable.
+		BufferedReader fileReader = null;
+		try
+		{
+			// Assume file is internal to project:
+			// EG) org/apache/etch/compiler/globalKeywords
+			InputStream input = getClass().getClassLoader().getResourceAsStream(filePath);
+
+			// Otherwise it's external
+			// EG) ../foo/bar/someKeywords
+			if (null == input)
+				input = new FileInputStream(filePath);
+
+			//fileReader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(filePath)));
+			fileReader = new BufferedReader(new InputStreamReader(input));
+
+			String currentLine = fileReader.readLine();
+			while (null != currentLine)
+			{
+				// Strip trailing comments and padded whitespace
+				currentLine = currentLine.trim();
+				if (currentLine.contains(commentMarker))
+					currentLine = currentLine.substring(0, currentLine.indexOf(commentMarker));
+
+				// Skip blank lines
+				StringTokenizer currentTokens = new StringTokenizer(currentLine, keyValueDelimeter);
+				if (currentTokens.hasMoreTokens())
+				{
+					String key 	= currentTokens.nextToken();
+					String value;
+
+					if (currentTokens.hasMoreTokens())
+						value = currentTokens.nextToken();
+					else
+						value = Character.isUpperCase(key.codePointAt(0)) ?
+								valuePrefix.toUpperCase() + key :
+								valuePrefix + key;
+
+					wordMap.put(key, value);
+				}
+
+				currentLine = fileReader.readLine();
+			}
+		}
+
+		catch (NullPointerException e)
+		{
+			throw new FileNotFoundException(filePath);
+		}
+
+		finally
+		{
+			if (null != fileReader)
+				fileReader.close();
+		}
+	}
+
+	/**
+	 * @param what
+	 * @return the appropriate direction give --what command line options.
+	 */
+	protected MessageDirection getMessageDirection(Set<String> what)
+	{
+		if ( what.contains( WHAT_BOTH )  )
+			return MessageDirection.BOTH;
+		
+		if ( what.contains( WHAT_SERVER ) )
+			return MessageDirection.SERVER;
+		
+		if ( what.contains( WHAT_CLIENT ) )
+			return MessageDirection.CLIENT;
+
+		throw new IllegalArgumentException( "what not correctly specified" );
+	}
+	
+	/**
+	 * @param what
+	 * @return what modified to account for interaction of options.
+	 */
+	protected Set<String> populateWhat( Set<String> what ) throws Exception
+	{
+		checkOption( what );
+		
+		if (what.contains( WHAT_HELP ))
+			throw new Exception(
+				"specify what as one or more of "+whatHelp() );
+		
+		// direction group
+		
+		if (!what.contains( WHAT_CLIENT )
+			&& !what.contains( WHAT_SERVER )
+			&& !what.contains( WHAT_BOTH ) )
+		{
+			// default to BOTH if none of the direction group is present.
+			what.add( WHAT_BOTH );
+			what.add( WHAT_CLIENT );
+			what.add( WHAT_SERVER );
+		}
+		else if (what.contains( WHAT_BOTH ))
+		{
+			// BOTH implies CLIENT and SERVER
+			what.add( WHAT_CLIENT );
+			what.add( WHAT_SERVER );
+		}
+		else if (what.contains( WHAT_CLIENT ) && what.contains( WHAT_SERVER ))
+		{
+			// CLIENT and SERVER together implies BOTH
+			what.add( WHAT_BOTH );
+		}
+		
+		// there are three reasonable outcomes of the above logic:
+		// CLIENT
+		// SERVER
+		// BOTH, CLIENT, SERVER
+		Assertion.check(
+			   what.contains( WHAT_CLIENT ) && !what.contains( WHAT_SERVER ) && !what.contains( WHAT_BOTH )
+			|| !what.contains( WHAT_CLIENT ) && what.contains( WHAT_SERVER ) && !what.contains( WHAT_BOTH )
+			|| what.contains( WHAT_CLIENT ) && what.contains( WHAT_SERVER ) && what.contains( WHAT_BOTH )
+			, "what files is {CLIENT}, {SERVER}, OR {CLIENT,SERVER,BOTH}" );
+		
+		// files group
+		
+		if (!what.contains( WHAT_ALL )
+			&& !what.contains( WHAT_NONE )
+			&& !what.contains( WHAT_INTF )
+			&& !what.contains( WHAT_MAIN )
+			&& !what.contains( WHAT_IMPL ))
+		{
+			// default to INTF if none of the file group is present.
+			what.add( WHAT_INTF );
+		}
+		
+		if (what.contains( WHAT_ALL ))
+		{
+			what.add( WHAT_INTF );
+			what.add( WHAT_MAIN );
+			what.add( WHAT_IMPL );
+			what.remove( WHAT_ALL );
+	        what.remove( WHAT_NONE );
+		}
+		
+		if (what.contains( WHAT_NONE ))
+		{
+	        what.remove( WHAT_INTF );
+	        what.remove( WHAT_MAIN );
+	        what.remove( WHAT_IMPL );
+	        what.remove( WHAT_NONE );
+		}
+		
+		return what;
+	}
+
+	private void checkOption( Set<String> what ) throws Exception
+	{
+		Set<String> w = new HashSet<String>( what );
+		
+		// what direction group
+		w.remove( WHAT_CLIENT );
+		w.remove( WHAT_SERVER );
+		w.remove( WHAT_BOTH );
+		
+		// what files group
+		w.remove( WHAT_ALL );
+		w.remove( WHAT_NONE );
+		w.remove( WHAT_INTF );
+		w.remove( WHAT_MAIN );
+		w.remove( WHAT_IMPL );
+		
+		w.remove( WHAT_FORCE );
+		w.remove( WHAT_HELP );
+		
+		if (!w.isEmpty())
+			throw new Exception(
+				"bad what option value(s): "+w
+				+"; specify what as one or more of "
+				+ whatHelp() );
+	}
+	
+	private String whatHelp()
+	{
+		return WHAT_CLIENT
+			+", "
+			+WHAT_SERVER
+			+", "
+			+WHAT_BOTH
+			+", "
+			+WHAT_ALL
+			+", "
+			+WHAT_NONE
+			+", "
+			+WHAT_INTF
+			+", "
+			+WHAT_MAIN
+			+", "
+			+WHAT_IMPL
+			+", "
+			+WHAT_FORCE
+			+", "
+			+WHAT_HELP;
+	}
+
+
+	/**
+	 * @param vname
+	 * @return generic type vname into a binding appropriate
+	 * vname.
+	 */
+	abstract public String mtvname( String vname );
+
+	/**
+	 * @param vname
+	 * @return generic field vname into a binding appropriate
+	 * vname.
+	 */
+	abstract public String mfvname( String vname );
+
+	/**
+	 * @return the lang being compiled.
+	 */
+	abstract public String getLang();
+
+	/**
+	 * @param msg a Message with the async receiver property.
+	 * @return the name of the async receiver thread pool name to
+	 * use for this async receiver method.
+	 */
+	abstract public String asyncReceiverPoolName( Message msg );
+
+	/**
+	 * @param type
+	 * @param value
+	 * @return the value properly formatted for the specified type.
+	 * @throws IOException
+	 * @throws Exception
+	 */
+	abstract public String getTypeValue( TypeRef type, Token value )
+		throws IOException, Exception;
+
+	/**
+	 * @param n
+	 * @param isExcept
+	 * @return the properly formatted "toString()" format string.
+	 * @throws ParseException
+	 * @throws IOException
+	 */
+	abstract public String formatString( ParamList<Service> n,
+		boolean isExcept ) throws ParseException, IOException;
+
+	/**
+	 * @param type
+	 * @return type name appropriate for use as a structure
+	 * element or exception parameter or function parameter
+	 * or result.
+	 */
+	abstract public String getTypeName( TypeRef type );
+
+	/**
+	 * @param type the etch type
+	 * @return the fundamental native type for java. so etch
+	 * int -> java int, while etch string -> java String. this
+	 * is used when typing constants that don't want ref types.
+	 */
+	abstract public String getNativeTypeName( TypeRef type );
+
+	/**
+	 * Returns the external fully qualified name for the enum. This might
+	 * have to be modified over the normal fqname for the enum, which would
+	 * be moduleName+'.'+serviceName+'.'+enumName.
+	 * @param fqname
+	 * @param moduleName
+	 * @param serviceName
+	 * @param enumName
+	 * @return the external fqname.
+	 */
+	abstract public String enum_efqname( String fqname, String moduleName,
+		String serviceName, String enumName );
+
+	/**
+	 * Returns the external fully qualified name for the enum. This might
+	 * have to be modified over the normal fqname for the enum, which would
+	 * be moduleName+'.'+serviceName+'.'+enumName.
+	 * @param fqname
+	 * @param moduleName
+	 * @param serviceName
+	 * @param enumName
+	 * @return the external fqname.
+	 */
+	abstract public String struct_efqname( String fqname, String moduleName,
+		String serviceName, String enumName );
+
+	/**
+	 * Returns the external fully qualified name for the enum. This might
+	 * have to be modified over the normal fqname for the enum, which would
+	 * be moduleName+'.'+serviceName+'.'+enumName.
+	 * @param fqname
+	 * @param moduleName
+	 * @param serviceName
+	 * @param enumName
+	 * @return the external fqname.
+	 */
+	abstract public String except_efqname( String fqname, String moduleName,
+		String serviceName, String enumName );
+
+	/**
+	 * @param intf the interface of the constant.
+	 * @param name an id or qid which references a constant.
+	 * @return the qualified external name.
+	 */
+	abstract public String qualifyConstantName( Service intf, Token name );
+
+	/**
+	 * @param intf the interface of the enum.
+	 * @param name an id or qid which references an enum.
+	 * @return the qualified external name.
+	 */
+	abstract public String qualifyEnumName( Service intf, Token name );
+
+	/**
+	 * @param name an id or qid which references a parameter of
+	 * a method.
+	 * @return the qualified parameter name.
+	 */
+	abstract public String qualifyParameterName( Token name );
+
+	/**
+	 * @param named
+	 * @return the validator for the parameter.
+	 */
+	abstract public String getValidator( Named<?> named );
+
+	/**
+	 * Once a service is created, the binding may add default
+	 * items to it such as standard types, externs, etc.
+	 * @param service a newly created service, ready for
+	 * defaults.
+	 * @throws ParseException
+	 */
+	abstract public void addDefaults( Service service ) throws ParseException;
+
+	/**
+	 * Adds an extern declaration to the service.
+	 * @param service the server to be modified.
+	 * @param name the name of the type of the extern.
+	 * @param language the language binding of this specification.
+	 * @param xname the binding specific name of the type.
+	 * @param xnameImport the "import" of the type if needed.
+	 * @param serializer the binding specific name of the import/export helper.
+	 * @param serializerImport the "import" of the import/export helper if needed.
+	 * @throws ParseException
+	 */
+	protected void addExtern( Service service, Name name, Token language,
+		Token xname, Token xnameImport, Token serializer,
+		Token serializerImport ) throws ParseException
+	{
+		Map<String, Opt> opts = new HashMap<String, Opt>();
+		opts.put( "Extern."+language.image, new Extern( name, language, xname,
+			xnameImport, serializer, serializerImport ) );
+		service.addExtern( name, opts );
+	}
+
+	/**
+	 * Adds a built-in declaration to the service.
+	 * @param service
+	 * @param name
+	 * @param bindingName
+	 * @param allowSubclass
+	 * @throws ParseException
+	 */
+	protected void addBuiltin( Service service, Name name, String bindingName,
+		boolean allowSubclass ) throws ParseException
+	{
+		service.addBuiltin( name, bindingName, allowSubclass );
+	}
+
+	/**
+	 * Constructs a name (with associated Id token).
+	 * @param name
+	 * @return the Name with ID token.
+	 */
+	protected Name newName( String name )
+	{
+		Token t = newId( name );
+		return new Name( t, name );
+	}
+	
+	/**
+	 * Constructs an ID token.
+	 * @param id
+	 * @return the ID token.
+	 */
+	protected Token newId( String id )
+	{
+		return newToken( EtchGrammarConstants.ID, id );
+	}
+	
+	/**
+	 * Constructs a STR token.
+	 * @param s
+	 * @return the STR token.
+	 */
+	protected Token newString( String s )
+	{
+		return newToken( EtchGrammarConstants.STR, s );
+	}
+	
+	/**
+	 * Constructs a token of specified kind.
+	 * @param kind
+	 * @param image
+	 * @return the token.
+	 */
+	protected Token newToken( int kind, String image )
+	{
+		Token t = new Token();
+		t.kind = kind;
+		t.image = image;
+		return t;
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/CmdLineOptions.java b/compiler/src/main/java/org/apache/etch/compiler/CmdLineOptions.java
new file mode 100644
index 0000000..5b46908
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/CmdLineOptions.java
@@ -0,0 +1,220 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This class defines options to be passed to the Etch compiler.
+ */
+public class CmdLineOptions
+{
+	/**
+	 * Name of the environment variable which contributes to the include path.
+	 */
+	public final static String ETCH_INCLUDE_PATH = "ETCH_INCLUDE_PATH";
+	
+    /**
+     * Separators for items in the "what" list.
+     */
+    public static String WHAT_DELIMETER = ",;: ";
+	
+	/**
+	 * Constructs a new CmdLineOptions from an existing one.
+	 * @param other
+	 */
+	public CmdLineOptions( CmdLineOptions other )
+	{
+		includePath = new ArrayList<File>( other.includePath );
+		ignoreGlobalWordsList = other.ignoreGlobalWordsList;
+		ignoreLocalWordsList = other.ignoreLocalWordsList;
+		userWordsList = other.userWordsList;
+		outputDir = other.outputDir;
+		binding = other.binding;
+		what = new HashSet<String>( other.what );
+		mixinOutputDir = other.mixinOutputDir;
+		noMixinArtifacts = other.noMixinArtifacts;
+		noFlattenPackages = other.noFlattenPackages;
+		quiet = other.quiet;
+		templateOutputDir = other.templateOutputDir;
+		ignoreIncludePath = other.ignoreIncludePath;
+		testing = other.testing;
+		sourceFile = other.sourceFile;
+		// EPHEMERAL STUFF //
+		cl = other.cl;
+		lh = other.lh;
+		effectiveIncludePath = new ArrayList<File>( other.effectiveIncludePath );
+		output = other.output;
+		templateOutput = other.templateOutput;
+		mixinOutput = other.mixinOutput;
+		bindingClass = other.bindingClass;
+		backend = other.backend;
+	}
+	
+	/**
+	 * Constructs a new CmdLineOptions.
+	 */
+	public CmdLineOptions()
+	{
+		includePath = new ArrayList<File>();
+		what = new HashSet<String>();
+		effectiveIncludePath = new ArrayList<File>();
+	}
+	
+	/**
+	 * The list of paths to search for included or mixed in files (-I option).
+	 */
+	public List<File> includePath;
+
+	/**
+	 * Flag indicates whether to ignore the globally reserved word list (-g
+	 * option).
+	 */
+	public boolean ignoreGlobalWordsList;
+
+	/**
+	 * Flag indicates whether to ignore the locally reserved word list (-l
+	 * option).
+	 */
+	public boolean ignoreLocalWordsList;
+
+	/**
+	 * The path of the user-defined reserved words list (-W option).
+	 */
+	public File userWordsList;
+
+	/**
+	 * The destination directory of the generated files (-d option). If not
+	 * specified, the same directory of the source file.
+	 */
+	public File outputDir;
+
+	/**
+	 * The binding name. Example values are java, csharp, python, ruby, c, and
+	 * xml (-b option).
+	 */
+	public String binding;
+
+	/**
+	 * This specifies the file(s) we need to generate (-w option). Valid values
+	 * depend upon the binding, but examples include BOTH, SERVER, CLIENT, ALL,
+	 * INTF, IMPL, MAIN, NONE, and FORCE. HELP might give you some. Separate
+	 * values using one or more characters from ",;: " (e.g., "BOTH, INTF",
+	 * which is also the default for many bindings).
+	 */
+	public Set<String> what;
+
+	/**
+	 * The destination directory of the generated mixin files (-m option). If
+	 * not specified, and if {@link #noMixinArtifacts} allows, mixin artifacts
+	 * are generated into {@link #outputDir}.
+	 */
+	public File mixinOutputDir;
+
+	/**
+	 * Flag indicates that mixin artifacts should not be generated (-n option).
+	 * If false, mixin artifacts are generated into {@link #mixinOutputDir}.
+	 */
+	public boolean noMixinArtifacts;
+
+	/**
+	 * Flag indicates whether the module name should should be flattened to
+	 * produce a single directory or a directory tree (e.g., for csharp) (-f
+	 * option).
+	 */
+	public boolean noFlattenPackages;
+
+	/**
+	 * Flag indicates that the compiler should not report progress (-q option).
+	 */
+	public boolean quiet;
+
+	/**
+	 * Destination directory of the user editable template files (-t option).
+	 * If not specified, same as {@link #outputDir}.
+	 */
+	public File templateOutputDir;
+
+	/**
+	 * Ignore the ETCH_INCLUDE_PATH environment variable (-i option).
+	 */
+	public boolean ignoreIncludePath;
+
+	/**
+	 * We're just testing the compiler, don't write any files (--testing option).
+	 */
+	public boolean testing;
+
+	/**
+	 * The source file to compile.
+	 */
+	public File sourceFile;
+
+	/////////////////////
+	// EPHEMERAL STUFF //
+	/////////////////////
+
+	/**
+	 * The binding class loader.
+	 */
+	public ClassLoader cl;
+	
+	/**
+	 * Destination of various error or status messages.
+	 */
+	public LogHandler lh;
+
+	/**
+	 * Computed effective includePath, including parent dir of source file,
+	 * include path command line elements, and path elements from system
+	 * environment variable.
+	 */
+	public List<File> effectiveIncludePath;
+
+	/**
+	 * Output for service generated files.
+	 */
+	public Output output;
+
+	/**
+	 * Output for service user-editable generated files.
+	 */
+	public Output templateOutput;
+
+	/**
+	 * Output for mixed in artifacts.
+	 */
+	public Output mixinOutput;
+    
+	/**
+	 * The class which implements the binding.
+	 */
+	public Class<?> bindingClass;
+    
+	/**
+	 * The instance of bindingClass used to generated code.
+	 */
+	public Backend backend;
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ConsoleLogHandler.java b/compiler/src/main/java/org/apache/etch/compiler/ConsoleLogHandler.java
new file mode 100644
index 0000000..3d04f90
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ConsoleLogHandler.java
@@ -0,0 +1,128 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+import java.io.PrintStream;
+
+/**
+ * This class implements the LogHandler Interface for Compiler
+ * @author gsandhir
+ *
+ */
+public class ConsoleLogHandler extends AbstractLogHandler
+{
+	/**
+	 * Constructs the CompilerLogHandler and sets the initial phase.
+	 * @param phase
+	 */
+	public ConsoleLogHandler( String phase )
+	{
+		super( phase );
+	}
+	
+	/**
+	 * Constructs the CompilerLogHandler.
+	 */
+	public ConsoleLogHandler()
+	{
+		super();
+	}
+
+	@Override
+	protected void log( Message msg )
+	{
+		PrintStream ps = selectPrintStream( msg.level );
+		
+		// Etch : Level : Phase : Source [line Line] : msg
+		
+		ps.print( "Etch" );		
+		formatLevel( ps, msg.level );
+		formatPhase( ps, msg.phase );
+		formatSource( ps, msg.source, msg.lineNumber );
+		formatMsg( ps, msg.msg );
+		ps.println();
+		
+		formatHistory( msg.history );
+	}
+
+	private final static String SEP = " : ";
+
+	private void formatLevel( PrintStream ps, int level )
+	{
+		ps.print( SEP );
+		switch (level)
+		{
+			case LEVEL_INFO:
+				ps.print( "I" );
+				break;
+			case LEVEL_WARNING:
+				ps.print( "W" );
+				break;
+			case LEVEL_ERROR:
+				ps.print( "E" );
+				break;
+			default:
+				ps.print( "?" );
+				break;
+		}
+	}
+
+	private void formatPhase( PrintStream ps, String phase )
+	{
+		ps.print( SEP );
+		if (phase != null && phase.length() > 0)
+			ps.print( phase );
+	}
+
+	private void formatSource( PrintStream ps, String source, Integer lineNumber )
+	{
+		if (source == null)
+			throw new NullPointerException( "source == null" );
+		
+		ps.print( SEP );
+		if (lineNumber != null && lineNumber != 0)
+			ps.printf( "%s line %d", source, lineNumber.intValue() );
+		else
+			ps.print( source );
+	}
+	
+	private void formatMsg( PrintStream ps, String msg )
+	{
+		ps.print( SEP );
+		ps.print( msg );
+	}
+
+	private void formatHistory( History[] history )
+	{
+		// TODO implement formatHistory
+	}
+
+	private PrintStream selectPrintStream( int level )
+	{
+		switch (level)
+		{
+			case LEVEL_ERROR:
+				return System.err;
+			default:
+				return System.out;
+		}
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/EtchCompiler.java b/compiler/src/main/java/org/apache/etch/compiler/EtchCompiler.java
new file mode 100644
index 0000000..4362fe4
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/EtchCompiler.java
@@ -0,0 +1,622 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.apache.etch.compiler.ast.Module;
+import org.apache.etch.compiler.ast.Name;
+import org.apache.etch.compiler.ast.Opt;
+import org.apache.etch.compiler.ast.Service;
+
+
+/**
+ * The main driver of the compiler.
+ */
+public class EtchCompiler
+{
+    /**
+     * Instantiate a new compiler
+     * @param cl the class loader to use to load the binding
+     */
+    public EtchCompiler( ClassLoader cl )
+    {
+    	this.cl = cl;
+    }
+    
+    private final ClassLoader cl;
+    
+    /**
+     * Runs the compiler using the specified input options.
+     * @param clo
+     * @throws Exception 
+     */
+    public void run( CmdLineOptions clo ) throws Exception
+    {
+    	clo.cl = cl;
+    	
+    	if (clo.lh == null)
+    	{
+	    	clo.lh = new ConsoleLogHandler( "Command" );
+	    	clo.lh.setLevel(
+	    		clo.quiet ? LogHandler.LEVEL_WARNING : LogHandler.LEVEL_INFO );
+    	}
+    	
+    	if (!initBindingClass( clo ))
+    		return;
+    	
+    	if (!checkSourceFile( clo ))
+    		return;
+    	
+    	initOutput( clo );
+        clo.lh.push( clo.sourceFile.getName(), null );
+        
+        try
+        {
+			compile( clo );
+	    	
+			if (!clo.lh.hasError())
+			{
+		        clo.lh.report( LogHandler.LEVEL_INFO, "Saving Resources..." );
+		        
+		        saveOutput( clo );
+		        
+		        if (!clo.lh.hasError())
+		        	clo.lh.report( LogHandler.LEVEL_INFO, "Saving Resources Done." );
+		        else
+		        	clo.lh.report( LogHandler.LEVEL_INFO, "Saving Resources Failed." );
+			}
+			else
+				clo.lh.report( LogHandler.LEVEL_INFO, "Compile Failed." );
+	    }
+        catch ( Exception e )
+        {
+        	clo.lh.report( LogHandler.LEVEL_ERROR, "caught exception: %s", e );
+        	e.printStackTrace();
+        }
+        finally
+        {
+        	clo.lh.pop( clo.sourceFile.getName() );
+        }
+    }
+
+	private static boolean initBindingClass( CmdLineOptions clo )
+	{
+		if (clo.bindingClass != null)
+			return true;
+
+		String n = clo.binding;
+		
+		if (n == null || n.length() == 0)
+		{
+			clo.lh.report( LogHandler.LEVEL_ERROR,
+				"Binding not specified." );
+			return false;
+		}
+		
+		if (n.equalsIgnoreCase( "help" ))
+		{
+			// TODO find some way to list the bindings?
+			clo.lh.report( LogHandler.LEVEL_ERROR,
+				"Binding help not yet implemented." );
+			return false;
+		}
+		
+		if (n.equalsIgnoreCase( "null" ))
+		{
+			clo.bindingClass = NullCompiler.class;
+			return true;
+		}
+		
+		String cn = String.format( BINDING_FORMAT, n );
+		
+		try
+		{
+			clo.bindingClass = clo.cl.loadClass( cn );
+			return true;
+		}
+		catch ( ClassNotFoundException e )
+		{
+			clo.lh.report( LogHandler.LEVEL_ERROR,
+				"Binding '%s' could not be loaded; class '%s' not in classpath.",
+				n, cn );
+			return false;
+		}
+		catch ( RuntimeException e )
+		{
+			clo.lh.report( LogHandler.LEVEL_ERROR,
+				"Binding '%s' could not be loaded; class '%s' threw exception %s",
+				n, cn, e );
+			e.printStackTrace();
+			return false;
+		}
+	}
+	
+	private static boolean initBackend( CmdLineOptions clo )
+	{
+		try
+		{
+			clo.backend = (Backend) clo.bindingClass.newInstance();
+			return true;
+		}
+		catch ( Exception e )
+		{
+			clo.lh.report( LogHandler.LEVEL_ERROR,
+				"Binding '%s' could not be initialized; caught exception %s.",
+				clo.binding, e );
+			e.printStackTrace();
+			return false;
+		}
+	}
+    
+    private final static String BINDING_FORMAT = "org.apache.etch.bindings.%s.compiler.Compiler";
+
+	private static boolean checkSourceFile( CmdLineOptions clo )
+	{
+		File f = clo.sourceFile;
+		
+		if (!f.isFile())
+		{
+			clo.lh.report( LogHandler.LEVEL_ERROR,
+				"Source file '%s' does not exist or is not a file.", f );
+			return false;
+		}
+		
+		if (!f.getName().endsWith( ".etch" ))
+		{
+			clo.lh.report( LogHandler.LEVEL_ERROR,
+				"Source file '%s' must have .etch extension.", f );
+			return false;
+		}
+		
+		return true;
+	}
+
+	/**
+     * @param etchHome command line specified location for the etch.
+     * @return sets up the class loader based on information from
+     * our environment.
+     * @throws Exception
+     */
+    public static ClassLoader setupClassLoader( File etchHome )
+        throws Exception
+    {
+        // get the current class path...
+        
+        Set<String> mainClassPath = new HashSet<String>();
+        
+        ClassLoader cl = EtchMain.class.getClassLoader();
+        if (cl instanceof URLClassLoader)
+        {
+            for (URL u: ((URLClassLoader) cl).getURLs())
+            {
+                String s = u.toString();
+                if (s.startsWith( "file:" ) && s.endsWith( ".jar" ))
+                {
+                    File f = new File( u.toURI() );
+                    if (f.isFile() && f.canRead())
+                    {
+                        s = f.getCanonicalPath();
+                        mainClassPath.add( s );
+//                      System.out.println( "mainClassPath.add: "+s );
+                    }
+                }
+            }
+        }
+        
+        // search etch.home (if specified) for more jar files to add
+        // to a secondary class loader. exclude jar files on the main
+        // class path.
+        
+        String s = etchHome != null ? etchHome.getCanonicalPath() : null;
+        
+        if (s == null || s.length() == 0)
+        {
+        	// from java -Detch.home=...
+            s = System.getProperty( "etch.home" );
+        }
+
+        if (s == null || s.length() == 0)
+        {
+            s = System.getenv( "ETCH_HOME" );
+        }
+        
+        if (s != null && s.length() > 0)
+            s = s + File.separator + "lib";
+
+        //      System.out.println( "etch.home.lib = "+s );
+        if (s != null && s.length() > 0)
+        {
+            File d = new File( s );
+            
+            if (!d.isDirectory() || !d.canRead())
+            	throw new IOException( String.format(
+            		"Specified $ETCH_HOME/lib is not a directory: %s\n", s ) );
+
+            d = d.getCanonicalFile();
+            
+            MyURLClassLoader ncl = new MyURLClassLoader( new URL[] {}, cl );
+            for (File f: d.listFiles())
+            {
+                if (!f.isFile())
+                    continue;
+                String x = f.getCanonicalPath();
+                if (!x.endsWith( ".jar" ))
+                    continue;
+                if (!mainClassPath.contains( x ))
+                    ncl.addURL( f.toURI().toURL() );
+            }
+            cl = ncl;
+        }
+        return cl;
+    }
+    
+    private static class MyURLClassLoader extends URLClassLoader
+    {
+        /**
+         * This is just a class loader where we can hang more urls to
+         * search.
+         * @param urls
+         * @param parent
+         */
+        public MyURLClassLoader( URL[] urls, ClassLoader parent )
+        {
+            super( urls, parent );
+        }
+        
+        @Override
+        public void addURL( URL url )
+        {
+            super.addURL( url );
+        }
+    }
+    
+    // includePath
+
+    /**
+     * Initialize {@link CmdLineOptions#effectiveIncludePath} given the
+     * compilation we are about to perform.
+     * @param clo
+     */
+    private static void initIncludePath( CmdLineOptions clo ) throws IOException
+    {
+//    	System.out.println( "initIncludePath: sourceFile = "+clo.sourceFile );
+//    	System.out.println( "initIncludePath: includePath = "+clo.includePath );
+    	
+    	// includePath is composed of the source file's directory, then
+    	// the paths specifies by -I command line directives, then the
+    	// paths specified by the ETCH_INCLUDE_PATH environment variable.
+    	
+    	clo.effectiveIncludePath = new ArrayList<File>( );
+    	
+    	// add directory of source file.
+    	if (clo.sourceFile != null)
+    		clo.effectiveIncludePath.add(
+    			clo.sourceFile.getCanonicalFile().getParentFile() );
+    	
+    	for (File f: clo.includePath)
+    	{
+    		if (f.isDirectory())
+    			clo.effectiveIncludePath.add( f );
+    		else
+    			clo.lh.report( LogHandler.LEVEL_WARNING,
+            		"Include path element doesn't exist: %s", f );
+    	}
+    	
+    	if (!clo.ignoreIncludePath)
+    	{
+	        String s = System.getenv( CmdLineOptions.ETCH_INCLUDE_PATH );
+	        if (s != null)
+	        {
+	            StringTokenizer st = new StringTokenizer( s, File.pathSeparator );
+	            while (st.hasMoreTokens())
+	            {
+	                File f = new File( st.nextToken() );
+	                if (f.isDirectory())
+	                	clo.effectiveIncludePath.add( f );
+	                else
+	                	clo.lh.report( LogHandler.LEVEL_WARNING,
+	                		"Environment include path element doesn't exist: %s", f );
+	            }
+	        }
+    	}
+//    	System.out.println( "initIncludePath: effectiveIncludePath = "+clo.effectiveIncludePath );
+    }
+
+	private static Module compile( CmdLineOptions clo ) throws Exception
+	{
+		InputStream is = new BufferedInputStream( new FileInputStream( clo.sourceFile ) );
+    	try
+		{
+			return compile( clo, is );
+		}
+		finally
+		{
+			is.close();
+		}
+	}
+    
+    private static Module compile( CmdLineOptions clo, InputStream is ) throws Exception
+	{
+    	initIncludePath( clo );
+    	
+    	if (!initBackend( clo ))
+    		return null;
+    	
+    	if (clo.sourceFile != null)
+    		clo.lh.report( LogHandler.LEVEL_INFO, "Compiling %s...", clo.sourceFile );
+    	else
+    		clo.lh.report( LogHandler.LEVEL_INFO, "Compiling..." );
+    	
+    	final EtchGrammar parser = new EtchGrammar( clo.backend, is );
+        
+        final Module m;
+        
+        // Parse .etch source
+        try
+        {
+            m = parser.module( clo );
+            clo.lh.report( LogHandler.LEVEL_INFO, "Parsed Ok." );
+            
+            m.check();
+            clo.lh.report( LogHandler.LEVEL_INFO, "Checked Ok." );
+        }
+        catch ( ParseException e )
+        {
+            String fmt = e.getMessage();
+            clo.lh.report( LogHandler.LEVEL_ERROR,
+            	e.currentToken != null ? e.currentToken.beginLine : null,
+            		e.getMessage() );
+            // TODO better report of a ParseException
+            throw new Exception(e.currentToken + " " + fmt);
+        }
+        catch ( Exception e )
+        {
+            clo.lh.report( LogHandler.LEVEL_ERROR, "caught exception: %s", e );
+            // TODO better report of an Exception
+            throw e;
+        }
+        
+        // Code generation
+        
+        try
+        {
+            // TODO report work lists?
+        	clo.lh.report( LogHandler.LEVEL_INFO, "Generating Resources..." );
+            
+            // TODO integrate includePath with code generation.
+            clo.backend.generate( m, clo );
+
+            // Move generated code to target location
+            //   the parser will set 'isMixinPresent' if a "mixin" directive is in the .etch file
+            // TODO would be nice if the backend just put things in the right place from the start .. sigh re-factor later        
+            // moveGeneratedCode(options.outputDir, options.isMixinPresent, workingDirectory);
+        }
+        catch ( Exception e )
+        {
+            String fmt = e.getMessage();
+            // TODO better report of an Exception
+            e.printStackTrace();
+            throw new Exception(fmt);
+        }
+
+        // Complete
+
+        clo.lh.report( LogHandler.LEVEL_INFO, "Compile Done." );
+        return m;
+    }
+
+	private static void initOutput( CmdLineOptions clo )
+	{
+		clo.output = new FileOutput();
+		clo.templateOutput = new FileOutput();
+		clo.mixinOutput = clo.noMixinArtifacts ? new NullOutput() : new FileOutput();
+	}
+
+	private static void saveOutput( CmdLineOptions clo ) throws IOException
+	{
+		// TODO implement saveOutput
+//		clo.output.report( "output" );
+//		clo.templateOutput.report( "templateOutput" );
+//		clo.mixinOutput.report( "mixinOutput" );
+		
+		if (clo.testing)
+			return;
+		
+		// Destination directory of generated artifacts. Use source file's
+		// parent directory if not specified.
+		
+		File outputDir = clo.outputDir;
+		boolean noQualOutputDir = false;
+		if (outputDir == null)
+		{
+			outputDir = clo.sourceFile.getCanonicalFile().getParentFile();
+			noQualOutputDir = true;
+		}
+
+		// Destination directory of generated user-editable artifacts. Use
+		// outputDir if not specified.
+		
+		File templateOutputDir = clo.templateOutputDir;
+		boolean noQualTemplateOutputDir = false;
+		if (templateOutputDir == null)
+		{
+			templateOutputDir = outputDir;
+			noQualTemplateOutputDir = noQualOutputDir;
+		}
+		
+		// Destination directory of mixin generated artifacts. Use outputDir
+		// if not specified.
+		
+		File mixinOutputDir = clo.mixinOutputDir;
+		boolean noQualMixinOutputDir = false;
+		if (mixinOutputDir == null)
+		{
+			mixinOutputDir = outputDir;
+			noQualMixinOutputDir = noQualOutputDir;
+		}
+		
+		boolean force = clo.what.contains( Backend.WHAT_FORCE );
+
+		saveFiles( clo.output, outputDir, noQualOutputDir, clo.noFlattenPackages, true );
+		saveFiles( clo.templateOutput, templateOutputDir, noQualTemplateOutputDir, clo.noFlattenPackages, force );
+		saveFiles( clo.mixinOutput, mixinOutputDir, noQualMixinOutputDir, clo.noFlattenPackages, true );
+	}
+
+	private static void saveFiles( Output output, File outputDir,
+		boolean noQualOutputDir, boolean noFlattenPackages, boolean force )
+		throws IOException
+	{
+		output.saveFiles( outputDir, noQualOutputDir, noFlattenPackages, force );
+	}
+
+	/**
+	 * Parses a mixin which is within the specified service.
+	 * @param intf
+	 * @param n
+	 * @param opts
+	 * @return the constructed Mixin object, or null.
+	 * @throws Exception 
+	 */
+	public static Module parseModule( Service intf, Name n, Map<String,
+		Opt> opts ) throws Exception
+	{
+		CmdLineOptions clo = new CmdLineOptions( intf.getCmdLineOptions() );
+		
+		// find the mixin file
+		
+		String fn = n.name;
+		
+		// fn is something like a.b.c.d or perhaps just plain d.
+		//
+		// we will look for d.etch, a/b/c/d.etch, and a.b.c/d.etch.
+		//
+		// we can look in the same directory as the original source we are
+		// compiling (the working dir), or any of the include path directories.
+		
+		String module;
+		String file;
+		int i = fn.lastIndexOf( '.' );
+		if (i >= 0)
+		{
+			module = fn.substring( 0, i );
+			file = fn.substring( i+1 );
+		}
+		else
+		{
+			module = null;
+			file = fn;
+		}
+		
+		file = file + ".etch";
+		
+//		System.out.printf( "searching for mixin '%s' module '%s'\n", file, module );
+//		System.out.println( "includePath = "+clo.includePath );
+//		System.out.println( "effectiveIncludePath = "+clo.effectiveIncludePath );
+		
+		List<File> list = new ArrayList<File>();
+		
+		// look for the unqualified name
+		find( list, clo, null, file );
+		
+		if (module != null)
+		{
+			// look for the qualified name
+			find( list, clo, module, file );
+			find( list, clo, module.replace( '.', '/' ), file );
+		}
+		
+		if (list.isEmpty())
+			return null;
+		
+		File f = list.get( 0 );
+//		System.out.println( "mixing in = "+f );
+		
+		return parseModule0( clo, n, f );
+	}
+	
+	private static void find( List<File> list, CmdLineOptions clo, String path,
+		String file ) throws IOException
+	{
+		for (File d: clo.effectiveIncludePath)
+		{
+			File f = d;
+			
+			if (path != null)
+				f = new File( f, path );
+			
+			f = new File( f, file ).getCanonicalFile();
+			
+			if (f.isFile() && !list.contains( f ))
+				list.add( f );
+		}
+	}
+
+	/**
+	 * @param clo
+	 * @param n
+	 * @param f
+	 * @return the parsed module of the mixin.
+	 * @throws Exception
+	 */
+	public static Module parseModule0( CmdLineOptions clo, Name n, File f )
+		throws Exception
+	{
+		clo.sourceFile = f;
+		clo.output = clo.mixinOutput;
+		
+		clo.templateOutput = new NullOutput();
+		clo.what.remove( Backend.WHAT_MAIN );
+		clo.what.remove( Backend.WHAT_IMPL );
+		
+		if (clo.noMixinArtifacts)
+		{
+			clo.what.clear();
+			clo.what.add( Backend.WHAT_NONE );
+		}
+		
+		clo.lh.report( LogHandler.LEVEL_INFO, n.token.beginLine,
+			"Compiling mixin file: %s", n.name );
+		clo.lh.push( f.getName(), n.token.beginLine );
+		try
+		{
+			return compile( clo );
+		}
+		finally
+		{
+			clo.lh.pop( f.getName() );
+			clo.lh.report( LogHandler.LEVEL_INFO, n.token.beginLine,
+				"Done compiling mixin file: %s", n.name );
+		}
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/EtchHelper.java b/compiler/src/main/java/org/apache/etch/compiler/EtchHelper.java
new file mode 100644
index 0000000..4204277
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/EtchHelper.java
@@ -0,0 +1,686 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.etch.compiler.ast.Constant;
+import org.apache.etch.compiler.ast.Enumx;
+import org.apache.etch.compiler.ast.Except;
+import org.apache.etch.compiler.ast.Item;
+import org.apache.etch.compiler.ast.Message;
+import org.apache.etch.compiler.ast.Module;
+import org.apache.etch.compiler.ast.Name;
+import org.apache.etch.compiler.ast.Opt;
+import org.apache.etch.compiler.ast.ParamList;
+import org.apache.etch.compiler.ast.Parameter;
+import org.apache.etch.compiler.ast.Service;
+import org.apache.etch.compiler.ast.Struct;
+import org.apache.etch.compiler.ast.Thrown;
+
+
+/**
+ * Compiler support routines.
+ */
+public class EtchHelper
+{
+//	/** TODO static global variable lh in compiler needs to go away. */
+//	public static LogHandler lh;
+	
+//	/** TODO static global variable cl in compiler needs to go away. */
+//	public static CmdLineOptions cl;
+
+	/**
+	 * Parses and saves a module comment.
+	 * @param m
+	 * @param specialToken
+	 */
+	protected static void moduleComment( Module m, Token specialToken )
+	{
+		if (specialToken == null)
+			return;
+
+		List<String> list = deComment( specialToken.image );
+		if (list == null)
+			return;
+
+		m.setDescr( list );
+	}
+
+	/**
+	 * Parses and saves a service comment.
+	 * @param s
+	 * @param specialToken
+	 */
+	protected static void serviceComment( Service s, Token specialToken )
+	{
+		if (specialToken == null)
+			return;
+
+		List<String> list = deComment( specialToken.image );
+		if (list == null)
+			return;
+
+		s.setDescr( list );
+	}
+
+	/**
+	 * Processes the formal comment for a constant.
+	 * @param c
+	 * @param specialToken
+	 */
+	protected static void constantComment( Constant c, Token specialToken )
+	{
+		if (specialToken == null)
+			return;
+
+		List<String> list = deComment( specialToken.image );
+		if (list == null)
+			return;
+
+		c.setDescr( list );
+	}
+
+	/**
+	 * Processes the formal comment for an enum.
+	 * @param e
+	 * @param specialToken
+	 */
+	protected static void enumComment( Enumx e, Token specialToken )
+	{
+		if (specialToken == null)
+			return;
+
+		List<String> list = deComment( specialToken.image );
+		if (list == null)
+			return;
+
+		// TODO if the items are described in @item tags here
+		// add that to the appropriate item. This will look
+		// alot like paramListComment.
+
+		e.setDescr( list );
+	}
+
+	/**
+	 * Processes the formal comment for an enum item.
+	 * @param i
+	 * @param specialToken
+	 */
+	protected static void itemComment( Item i, Token specialToken )
+	{
+		if (specialToken == null)
+			return;
+
+		List<String> list = deComment( specialToken.image );
+		if (list == null)
+			return;
+
+		i.setDescr( list );
+	}
+
+	/**
+	 * Processes the formal comment for a parameter of a struct, exception,
+	 * or message.
+	 * @param p
+	 * @param specialToken
+	 */
+	protected static void parameterComment( Parameter p, Token specialToken )
+	{
+		if (specialToken == null)
+			return;
+
+		List<String> list = deComment( specialToken.image );
+		if (list == null)
+			return;
+
+		p.setDescr( list );
+	}
+
+	/**
+	 * Processes the formal comment for a thrown exception.
+	 * @param t
+	 * @param specialToken
+	 */
+	protected static void thrownComment( Thrown t, Token specialToken )
+	{
+		if (specialToken == null)
+			return;
+
+		List<String> list = deComment( specialToken.image );
+		if (list == null)
+			return;
+
+		t.setDescr( list );
+	}
+
+	/**
+	 * Processes the formal comment for a struct.
+	 * @param s
+	 * @param specialToken
+	 */
+	protected static void structComment( Struct s, Token specialToken )
+	{
+		paramListComment( s, specialToken, false );
+	}
+
+	/**
+	 * Processes the formal comment for an exception.
+	 * @param e
+	 * @param specialToken
+	 */
+	protected static void exceptComment( Except e, Token specialToken )
+	{
+		paramListComment( e, specialToken, false );
+	}
+
+	/**
+	 * Processes the formal comment for a message.
+	 * @param m
+	 * @param specialToken
+	 */
+	protected static void messageComment( Message m, Token specialToken )
+	{
+		paramListComment( m, specialToken, true );
+	}
+
+	/**
+	 * @param t
+	 * @throws IOException
+	 */
+	protected static void fixString( Token t ) throws ParseException
+	{
+		if (t.kind != EtchGrammarConstants.STR)
+			return;
+
+		try
+		{
+			t.image = unescapeStr( t.image );
+		}
+		catch ( IOException e)
+		{
+			throw new ParseException( String.format(
+				"Problem with string '%s' at line %d", e.getMessage(), t.beginLine ) );
+		}
+	}
+
+	private static String unescapeStr( String s ) throws IOException
+	{
+		// remove the quotes.
+
+		if (!s.startsWith( "\"" ) || !s.endsWith( "\"" ))
+			throw new IllegalArgumentException( "string image is not quoted" );
+
+		s = s.substring( 1, s.length()-1 );
+
+		StringReader rdr = new StringReader( s );
+		StringBuffer sb = new StringBuffer();
+
+		int c;
+		while ((c = rdr.read()) >= 0)
+		{
+			if (c != '\\')
+			{
+				sb.append( (char) c );
+				continue;
+			}
+
+			// c == '\\': two escape formats: uxxxx and k (k=["\trn])
+
+			c = rdr.read();
+			if (c == 'u')
+			{
+				// unicode escape (need for hex chars)
+				c = fromHex( rdr.read() );
+//				 System.out.println( "c1: "+c );
+				c = (c << 4) + fromHex( rdr.read() );
+//				 System.out.println( "c2: "+c );
+				c = (c << 4) + fromHex( rdr.read() );
+//				 System.out.println( "c3: "+c );
+				c = (c << 4) + fromHex( rdr.read() );
+//				 System.out.println( "c4: "+c );
+				sb.append( (char) c );
+			}
+			else switch (c)
+			{
+				// plain escape
+				case '"': sb.append( "\"" ); break;
+				case '\\': sb.append( "\\" ); break;
+				case 't': sb.append( "\t" ); break;
+				case 'r': sb.append( "\r" ); break;
+				case 'n': sb.append( "\n" ); break;
+				default: throw new IOException( "bad escape char: "+c );
+			}
+		}
+		return sb.toString();
+	}
+
+	private static int fromHex( int c ) throws IOException
+	{
+		if (c >= '0' && c <= '9') return c - '0';
+		if (c >= 'a' && c <= 'f') return c - 'a' + 10;
+		if (c >= 'A' && c <= 'F') return c - 'A' + 10;
+		throw new IOException( "bad hex char: "+c );
+	}
+
+	/**
+	 * Formal comment types (tags).
+	 */
+	enum Type
+	{
+		/**
+		 * The main body of the comment before any tags.
+		 */
+		Main,
+		/**
+		 * The type denoting an @param tag.
+		 */
+		Param,
+		/**
+		 * The type denoting an @return tag.
+		 */
+		Return,
+		/**
+		 * The type denoting an @throws tag.
+		 */
+		Throws,
+		/**
+		 * The type denoting an unrecognized tag.
+		 */
+		None
+	}
+
+	/**
+	 * Processes any saved message comment.
+	 * @param m
+	 */
+	private static void paramListComment( ParamList<Service> m,
+		Token specialToken, boolean isMessage )
+	{
+		if (specialToken == null)
+			return;
+
+		List<String> list = deComment( specialToken.image );
+		if (list == null)
+			return;
+
+//		System.out.println( list );
+
+		Type type = Type.Main;
+		String name = null;
+		for (String s: list)
+		{
+			String x = s;
+
+//			System.out.printf( "processing: %s\n", s );
+			if (s.startsWith( "@" ))
+			{
+				StringTokenizer st = new StringTokenizer( s, " \t" );
+				String k = st.nextToken();
+				if (k.equals( "@param" ))
+				{
+					type = Type.Param;
+					if (!st.hasMoreTokens())
+					{
+						System.out.printf( "*** warning: parameter name missing on @param at line %d\n", specialToken.beginLine );
+						return;
+					}
+					name = st.nextToken();
+					if (st.hasMoreTokens())
+						s = st.nextToken( "\r\n" ).trim();
+					else
+						s = "";
+				}
+				else if (k.equals( "@return" ))
+				{
+					type = Type.Return;
+					if (!isMessage || !((Message) m).hasReturn())
+					{
+						System.out.printf( "*** warning: @return used on non-message or void message at line %d\n", specialToken.beginLine );
+						return;
+					}
+					if (st.hasMoreTokens())
+						s = st.nextToken( "\r\n" ).trim();
+					else
+						s = "";
+				}
+				else if (k.equals( "@throws" ))
+				{
+					type = Type.Throws;
+					if (!isMessage)
+					{
+						System.out.printf( "*** warning: @throws used on non-message at line %d\n", specialToken.beginLine );
+						return;
+					}
+					if (!st.hasMoreTokens())
+					{
+						System.out.printf( "*** warning: exception name missing on @throws at line %d\n", specialToken.beginLine );
+						return;
+					}
+					name = st.nextToken();
+					if (st.hasMoreTokens())
+						s = st.nextToken( "\r\n" ).trim();
+					else
+						s = "";
+				}
+				else
+				{
+					type = Type.None;
+					System.out.printf( "*** warning: %s not understood in this context (%s): %s\n", k, m.name(), x );
+				}
+			}
+
+//			System.out.printf( "type %d\n", type );
+
+			if (type == Type.Main)
+			{
+				//System.out.printf( "adding to m.descr: %s\n", s );
+				m.descr().add( s );
+			}
+			else if (type == Type.Param)
+			{
+//				System.out.printf( "adding to p.descr (%s): %s\n", name, s );
+				Parameter p = m.getParameter( name );
+				if (p != null)
+					p.descr().add( s );
+				else
+					System.out.printf( "*** warning: cannot document parameter %s of %s\n", name, m.name() );
+			}
+			else if (type == Type.Return)
+			{
+//				System.out.printf( "adding to m.returnDescr: %s\n", s );
+				((Message) m).returnDescr().add( s );
+			}
+			else if (type == Type.Throws)
+			{
+//				System.out.printf( "adding to t.descr (%s): %s\n", name, s );
+				Thrown t = ((Message) m).getThrown( name );
+				if (t != null)
+					t.descr().add( s );
+				else
+					System.out.printf( "*** warning: cannot document thrown %s of %s\n", name, m.name() );
+			}
+			else if (type != Type.None)
+			{
+				System.out.printf( "*** warning: comment type %s not understood\n", type );
+			}
+		}
+	}
+
+	/**
+	 * Splits a formal comment into its lines, stripping
+	 * off the comment gunk.
+	 * @param s
+	 * @return an array of lines of the comment, without
+	 * the EOL characters and the comment gunk.
+	 */
+	protected static List<String> deComment( String s )
+	{
+		if (!s.startsWith( "/** " ) &&
+				!s.startsWith( "/**\t" ) &&
+				!s.startsWith( "/**\r" ) &&
+				!s.startsWith( "/**\n" ))
+			return null;
+
+		s = s.substring( 3 );
+
+		if (s.endsWith( "*/" ))
+			s = s.substring( 0, s.length() - 2 );
+
+		s = s.trim();
+
+		// now we have a bunch of lines that look like this:
+		// .*(\r\n\w[*](\W.*)?)*
+		// undo all that by chopping up into lines, then removing
+		// leading white space up to the * and then the space directly
+		// after the * if there is one.
+
+		List<String> list = new ArrayList<String>();
+
+		StringTokenizer st = new StringTokenizer( s, "\r\n", true );
+		while (st.hasMoreTokens())
+		{
+			String t = st.nextToken();
+			if (t.equals( "\r" ))
+			{
+				// ignore the EOL marks.
+			}
+			else if (t.equals( "\n" ))
+			{
+				// ignore the EOL marks.
+			}
+			else
+			// not an EOL marker...
+			{
+				t = t.trim();
+				// this is a line that looks like "*blah" or
+				// "* blah" or "*".
+				if (t.startsWith( "* " ))
+					list.add( t.substring( 2 ) );
+				else if (t.startsWith( "*" ))
+					list.add( t.substring( 1 ) );
+				else
+					list.add( t );
+			}
+		}
+		return list;
+	}
+
+	/**
+	 * @return the last saved comment.
+	 */
+	protected Token getComment()
+	{
+		Token comment = savedComment;
+		savedComment = null;
+		return comment;
+	}
+
+	private Token savedComment;
+
+	/**
+	 * Saves a comment to be used later. Only the
+	 * most recently saved comment will be available.
+	 * @param comment
+	 */
+	protected void saveComment( Token comment )
+	{
+		if (comment != null)
+			savedComment = comment;
+	}
+
+	/**
+	 * @param n the name of the opt.
+	 * @param list the list of opt arguments.
+	 * @return an Opt subclass
+	 * @throws ParseException
+	 */
+	protected Opt makeOpt( Name n, List<Token> list ) throws ParseException
+	{
+		String cn = "org.apache.etch.compiler.opt."+n.token.image;
+		Class<?> c;
+
+		try
+		{
+			c = Class.forName( cn );
+		}
+		catch ( NoClassDefFoundError e )
+		{
+			throw new ParseException( String.format(
+				"option class %s not found at line %d",
+				n, n.token.beginLine ) );
+		}
+		catch ( ClassNotFoundException e )
+		{
+			throw new ParseException( String.format(
+				"option class %s not found at line %d",
+				n, n.token.beginLine ) );
+		}
+
+		Class<?>[] params = { Name.class, Token[].class };
+
+		Constructor<?> k;
+
+		try
+		{
+			k = c.getConstructor( params );
+		}
+		catch ( SecurityException e )
+		{
+			throw new ParseException( String.format(
+				"security rules block access to the constructor of option class %s at line %d",
+				n, n.token.beginLine ) );
+		}
+		catch ( NoSuchMethodException e )
+		{
+			throw new ParseException( String.format(
+				"missing constructor for option class %s at line %d",
+				n, n.token.beginLine ) );
+		}
+
+		Object[] args = { n, list.toArray( new Token[list.size()] ) };
+
+		try
+		{
+			return (Opt) k.newInstance( args );
+		}
+		catch ( IllegalArgumentException e )
+		{
+			throw new ParseException( String.format(
+				"illegal argument to newInstance for option class %s at line %d: %s",
+				n, n.token.beginLine, e ) );
+		}
+		catch ( InstantiationException e )
+		{
+			throw new ParseException( String.format(
+				"cannot instantiate option class %s at line %d: %s",
+				n, n.token.beginLine, e ) );
+		}
+		catch ( IllegalAccessException e )
+		{
+			throw new ParseException( String.format(
+				"illegal access of constructor for option class %s at line %d: %s",
+				n, n.token.beginLine, e ) );
+		}
+		catch ( InvocationTargetException e )
+		{
+			if (e.getTargetException() instanceof ParseException)
+				throw (ParseException) e.getTargetException();
+
+			throw new ParseException( String.format(
+				"exception caught from constructor for option class %s at line %d: %s",
+				n, n.token.beginLine, e.getTargetException() ) );
+		}
+	}
+
+	protected void doStartService()
+	{
+	}
+
+	protected void doEndService(Service oServ)
+	{
+	}
+
+	/**
+	 * @param f name of the filename for the include.
+	 */
+	protected void doInclude( Token fileName, Service servobj) throws ParseException
+	{
+
+		//Get the Gramar Obj
+		EtchGrammar oGramar = (EtchGrammar) this;
+
+		servobj.getCmdLineOptions().lh.push( fileName.toString(), fileName.beginLine );
+
+		//System.out.println("------Start Do Include-------");
+
+		//Get the file name
+	  	String oStr = fileName.toString().replaceAll("\"", "");
+
+	 // 	System.out.println("Including " + oStr);
+	  	servobj.getCmdLineOptions().lh.report( LogHandler.LEVEL_INFO, "Including %s", oStr );
+
+	    //Create the input string and read it in
+		InputStream oStream = null;
+
+		// Search the etch path for the file
+		for (File f : servobj.getCmdLineOptions().effectiveIncludePath)
+		{
+			try
+			{
+				oStream = new java.io.FileInputStream(new File(f, oStr));
+				break;
+			}
+			catch (FileNotFoundException e)
+			{
+			}
+		}
+
+		if (oStream == null)
+			throw new ParseException(" Included File " + oStr + " Not Found\n");
+
+		//Keep for debugging
+		//StackInputStream oStStream = new StackInputStream(oStream);
+		SimpleCharStream curStream = null;
+		try
+		{
+			curStream = new SimpleCharStream(oStream, null, 1, 1);
+		}
+
+		catch ( UnsupportedEncodingException e )
+		{
+			throw new ParseException(" Included File " + oStr + " is not correctly encoded\n");
+
+		}
+
+		//Create a new token manager with the new include stream
+	    EtchGrammarTokenManager oTM = new EtchGrammarTokenManager(curStream);
+
+	    //Keep the old token manager
+	    EtchGrammarTokenManager oOldTM = oGramar.token_source;
+
+	    //Keep the old token
+	    Token token = oGramar.token;
+
+	    //reinit with the new token manager
+	    oGramar.ReInit( oTM );
+
+	    	//Proc the stream
+		oGramar.stmts( servobj );
+
+
+		//Put the old data back
+		oGramar.ReInit( oOldTM );
+		oGramar.token = token;
+		servobj.getCmdLineOptions().lh.pop( fileName.toString() );
+		//System.out.println("------End Do Include---------");
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/EtchMain.java b/compiler/src/main/java/org/apache/etch/compiler/EtchMain.java
new file mode 100644
index 0000000..a7ffd6e
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/EtchMain.java
@@ -0,0 +1,372 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+import java.io.File;
+import java.util.StringTokenizer;
+
+import org.apache.etch.util.cmd.CommandParser;
+import org.apache.etch.util.cmd.Option;
+import org.apache.etch.util.cmd.Parameter;
+import org.apache.etch.util.cmd.Program;
+
+
+/**
+ * The main command line interface for the etch compiler.
+ */
+public class EtchMain extends Program
+{
+	/**
+     * @param args
+     * @throws Exception 
+     */
+    public static void main( String[] args ) throws Exception
+    {
+    	new EtchMain().doMain( args );
+    }
+    
+    /**
+     * Runs the main program, parsing command line arguments and performing
+     * the action.
+     * @param args
+     * @throws Exception
+     */
+    public void doMain( String[] args ) throws Exception
+    {
+    	try
+    	{
+    		main( this, args );
+    	}
+        catch ( Throwable e )
+        {
+        	e.printStackTrace();
+            exit( 3, toString(), e.toString(), true );
+            return;
+        }
+    }
+
+    /**
+     * Constructs the etch parser / compiler driver.
+     */
+    public EtchMain()
+    {
+        // nothing to do.
+    }
+
+    @Override
+    public String toString()
+    {
+        return "etch";
+    }
+
+    @Override
+    protected void defineOptionsAndParameters( CommandParser cp )
+        throws Exception
+    {
+        cp.defineFileOption( "-d|--output-dir", "outputDir", "setOutputDir",
+            "output directory for compiler generated files",
+            Option.SINGLETON, null, null );
+
+        cp.defineFileOption( "-m|--mixin-output-dir", "outputDir", "setMixinOutputDir",
+            "output directory for compiler generated files for mixins",
+            Option.SINGLETON, null, null );
+
+        cp.defineFileOption( "-t|--template-output-dir", "outputDir", "setTemplateOutputDir",
+            "output directory for compiler generated user editable template files",
+            Option.SINGLETON, null, null );
+            
+        cp.defineStringOption( "-b|--binding", "binding", "setBinding",
+            "specifies a target language binding to generate",
+            Option.REQUIRED|Option.SINGLETON, null, null );
+
+        cp.defineStringOption( "-w|--what", "what", "addWhat",
+            "specifies what files to generate (depends upon binding, try -w help for more info; separate with '"+CmdLineOptions.WHAT_DELIMETER+"')",
+            Option.NONE, null, null );
+
+        cp.defineNullOption( "-g|--ignore-global-words-list", "ignoreGlobalWordsList",
+            "ignore the global reserved words list",
+            Option.SINGLETON );
+
+        cp.defineNullOption( "-l|--ignore-local-words-list", "ignoreLocalWordsList",
+            "ignore the local (binding-specific) reserved words list",
+            Option.SINGLETON );
+
+        cp.defineFileOption( "-W|--user-words-list", "wordList", "setUserWordsList",
+            "file name of a user-specified reserved words list",
+            Option.SINGLETON, null, null );
+
+        cp.defineStringOption( "-I|--include-path", "includePath", "addIncludePath",
+            "adds search directories for included or mixed in etch files (separate elements with system path separator '"+File.pathSeparator+"')",
+            Option.NONE, null, null );
+
+        cp.defineNullOption( "-i|--ignore-include-path", "ignoreIncludePath",
+            "ignore the "+CmdLineOptions.ETCH_INCLUDE_PATH+" environment variable",
+            Option.SINGLETON );
+
+        cp.defineNullOption( "-n|--no-mixin-artifacts", "noMixinArtifacts",
+            "mixin artifacts should not be generated",
+            Option.SINGLETON );
+
+        cp.defineNullOption( "-q|--quiet", "quiet",
+            "only report problems",
+            Option.SINGLETON );
+
+        cp.defineNullOption( "-v|--version", "doVersion",
+            "show the version and exit",
+            Option.SINGLETON );
+
+        cp.defineNullOption( "-f|--no-flatten-packages", "noFlattenPackages",
+            "namespace directory tree should not be flattened",
+            Option.SINGLETON );
+        
+        cp.defineNullOption( "--testing", "setTesting",
+        	"",
+        	Option.HIDDEN );
+
+        cp.defineFileParameter( "sourceFile", "setSourceFile",
+            "etch source file to compile", true, false, null );
+    }
+    
+    private final CmdLineOptions clo = new CmdLineOptions();
+
+    /**
+     * Sets the output directory of compiler generated files.
+     * @param cp
+     * @param option
+     * @param token
+     * @param value the output directory
+     */
+    public void setOutputDir( CommandParser cp, Option option, String token,
+        File value )
+    {
+        clo.outputDir = value;
+    }
+    
+    /**
+     * Sets the output directory for user editable template files.
+     * @param cp
+     * @param option
+     * @param token
+     * @param value the template output directory
+     */
+    public void setTemplateOutputDir( CommandParser cp, Option option, String token,
+        File value )
+    {
+    	clo.templateOutputDir = value;
+    }
+
+    /**
+     * Sets the binding.
+     * @param cp
+     * @param option
+     * @param token
+     * @param value the binding
+     */
+    public void setBinding( CommandParser cp, Option option, String token,
+        String value )
+    {
+    	clo.binding = value;
+    }
+
+    /**
+     * Adds to the set of what needs to be generated.
+     * @param cp
+     * @param option
+     * @param token
+     * @param value the list of what needs to be generated.
+     */
+    public void addWhat( CommandParser cp, Option option, String token,
+        String value )
+    {
+        StringTokenizer st = new StringTokenizer( value, CmdLineOptions.WHAT_DELIMETER );
+        while (st.hasMoreElements()) 
+        	clo.what.add(st.nextToken().toUpperCase());
+    }
+
+    /**
+     * Sets the ignore the globally reserved words list flag.
+     * @param cp
+     * @param option
+     * @param token
+     */
+    public void ignoreGlobalWordsList(CommandParser cp, Option option, String token)
+    {
+    	clo.ignoreGlobalWordsList = true;
+    }
+
+    /**
+     * Sets the ignore the locally reserved words list flag.
+     * @param cp
+     * @param option
+     * @param token
+     */
+    public void ignoreLocalWordsList(CommandParser cp, Option option, String token)
+    {
+    	clo.ignoreLocalWordsList = true;
+    }
+
+    /**
+     * Sets the file name of the user-defined reserved words list.
+     * @param cp
+     * @param option
+     * @param token
+     * @param value the file name of the user-defined reserved words list
+     */
+    public void setUserWordsList(CommandParser cp, Option option, String token,
+        File value)
+    {
+    	clo.userWordsList = value;
+    }
+
+    /**
+     * Adds to the include path.
+     * @param cp
+     * @param option
+     * @param token
+     * @param value path list to append to the current include path.
+     */
+    public void addIncludePath( CommandParser cp, Option option, String token,
+        String value )
+    {
+        StringTokenizer includeTokens = new StringTokenizer(value,
+            File.pathSeparator);
+
+        while(includeTokens.hasMoreTokens())
+        {
+            File temp = new File(includeTokens.nextToken());
+            clo.includePath.add(temp);
+        }
+    }
+
+    /**
+     * Sets the ignore the include path from the environment flag.
+     * @param cp
+     * @param option
+     * @param token
+     */
+    public void ignoreIncludePath(CommandParser cp, Option option,
+        String token)
+    {
+    	clo.ignoreIncludePath = true;
+    }
+
+    /**
+     * Sets the quiet flag.
+     * @param cp
+     * @param option
+     * @param token
+     */
+    public void quiet( CommandParser cp, Option option, String token )
+    {
+    	clo.quiet = true;
+    }
+
+    /**
+     * Shows the version and exits.
+     * @param cp
+     * @param option
+     * @param token
+     * @return false so that we stop.
+     */
+    public boolean doVersion( CommandParser cp, Option option, String token )
+    {
+        System.out.println(String.format("Etch version is %s", Version.VERSION));
+        return false;
+    }
+
+    /**
+     * Sets the suppress mixin artifacts flag.
+     * @param cp
+     * @param option
+     * @param token
+     */
+    public void noMixinArtifacts( CommandParser cp, Option option, String token )
+    {
+    	clo.noMixinArtifacts = true;
+    }
+
+    /**
+     * Sets the output directory for mixins.
+     * @param cp
+     * @param option
+     * @param token
+     * @param value the output directory for mixin
+     */
+    public void setMixinOutputDir( CommandParser cp, Option option, String token,
+        File value )
+    {
+    	clo.mixinOutputDir = value;
+    }
+
+    /**
+     * Sets the no flatten packages flag.
+     * @param cp
+     * @param option
+     * @param token
+     */
+    public void noFlattenPackages( CommandParser cp, Option option, String token )
+    {
+    	clo.noFlattenPackages = true;
+    }
+    
+    /**
+     * Sets the hidden testing flag.
+     * @param cp
+     * @param option
+     * @param token
+     */
+    public void setTesting( CommandParser cp, Option option, String token )
+    {
+    	clo.testing = true;
+    	clo.lh = new ListLogHandler();
+    	testingClo = clo;
+    }
+    
+    /**
+     * If --testing is on the command line, the CmdLineOptions is saved
+     * here for reference by unit testing programs.
+     */
+    public CmdLineOptions testingClo;
+
+    /**
+     * Sets the etch source file to compile.
+     * @param cp the command parser
+     * @param param
+     * @param value path of etch file to compile
+     */
+    public void setSourceFile( CommandParser cp, Parameter param, File value )
+    {
+    	clo.sourceFile = value;
+    }
+
+    @Override
+    protected void run() throws Exception
+    {
+        // Instantiate a new compiler instance and run it.
+    	ClassLoader cl = EtchCompiler.setupClassLoader( null );
+        EtchCompiler etchCompiler = new EtchCompiler( cl );
+        
+        etchCompiler.run( clo );
+        
+        if (clo.lh.hasError())
+        	exit( 3, "EtchMain", "errors during compile", false );
+    }
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/FileOutput.java b/compiler/src/main/java/org/apache/etch/compiler/FileOutput.java
new file mode 100644
index 0000000..45f6f54
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/FileOutput.java
@@ -0,0 +1,179 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * File/directory based implementation of Output container.
+ */
+public class FileOutput implements Output
+{
+	/**
+	 * Constructs top-level Output, no package.
+	 */
+	public FileOutput()
+	{
+		this( null );
+	}
+	
+	/**
+	 * Constructs mid-level Output with package name.
+	 * @param pn
+	 */
+	public FileOutput( String pn )
+	{
+		this.pn = pn;
+	}
+	
+	private final String pn;
+	
+	public void report( String what )
+	{
+		report( what, "" );
+	}
+	
+	private void report( String what, String indent )
+	{
+		if (pn != null)
+			System.out.printf( "%spackage %s", indent, pn );
+		else
+			System.out.printf( "%s%s", indent, what );
+		System.out.println();
+		
+		String sindent = indent+"  ";
+		
+		for (Map.Entry<String, ByteArrayOutputStream> me: files.entrySet())
+			report( sindent, me.getKey(), me.getValue() );
+		
+		for (FileOutput p: packages.values())
+			p.report( what, sindent );
+	}
+
+	private void report( String indent, String fn, ByteArrayOutputStream value )
+	{
+		System.out.printf( "%sfile %s %d", indent, fn, value.size() );
+		System.out.println();
+	}
+
+	public OutputStream newOutputStream( String fn )
+	{
+		ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		files.put( fn, baos );
+		return baos;
+	}
+	
+	private final Map<String, ByteArrayOutputStream> files =
+		new HashMap<String, ByteArrayOutputStream>();
+
+	public Output newPackage( String pn )
+	{
+		FileOutput p = packages.get( pn );
+		if (p == null)
+		{
+			p = new FileOutput( pn );
+			packages.put( pn, p );
+		}
+		return p;
+	}
+	
+	private final Map<String, FileOutput> packages = new HashMap<String, FileOutput>();
+
+	public void saveFiles( File outputDir, boolean noQualOutputDir,
+		boolean noFlattenPackages, boolean force ) throws IOException
+	{
+		saveFiles( outputDir, noQualOutputDir, noFlattenPackages, force, null );
+	}
+
+	private void saveFiles( File outputDir, boolean noQualOutputDir,
+		boolean noFlattenPackages, boolean force, String pkg ) throws IOException
+	{
+		if (pn != null)
+		{
+			if (pkg != null)
+				pkg += '.' + pn;
+			else
+				pkg = pn;
+		}
+
+//		System.out.printf(
+//			"saveFiles: outputDir %s, noQualOutputDir %s, noFlattenPackages %s, force %s, pkg %s\n",
+//			outputDir, noQualOutputDir, noFlattenPackages, force, pkg );
+		
+		for (Map.Entry<String, ByteArrayOutputStream> me: files.entrySet())
+			saveFile( outputDir, noQualOutputDir, noFlattenPackages, force, pkg, me.getKey(), me.getValue() );
+		
+		for (FileOutput p: packages.values())
+			p.saveFiles( outputDir, noQualOutputDir, noFlattenPackages, force, pkg );
+	}
+
+	private void saveFile( File outputDir, boolean noQualOutputDir,
+		boolean noFlattenPackages, boolean force, String pkg, String fn,
+		ByteArrayOutputStream value ) throws IOException
+	{
+//		System.out.printf(
+//			"saveFile: outputDir %s, noQualOutputDir %s, noFlattenPackages %s, force %s, pkg %s, fn %s, size %d\n",
+//			outputDir, noQualOutputDir, noFlattenPackages, force, pkg, fn, value.size() );
+		
+		if (pkg != null && !noQualOutputDir)
+		{
+			if (noFlattenPackages)
+				pkg = pkg.replace( '.', File.separatorChar );
+			outputDir = new File( outputDir, pkg );
+		}
+		
+		File f = new File( outputDir, fn ).getCanonicalFile();
+		
+		if (f.isFile() && !force)
+		{
+			System.out.printf( "*** existing file not overwritten: %s\n", f );
+			return;
+		}
+		
+		f.getParentFile().mkdirs();
+		
+		FileOutputStream fos = new FileOutputStream( f );
+		try
+		{
+			value.writeTo( fos );
+		}
+		catch ( IOException e )
+		{
+			fos.close();
+			f.delete();
+			IOException x = new IOException( "error writing "+f );
+			x.initCause( e );
+			throw x;
+		}
+		finally
+		{
+			fos.close();
+		}
+		
+//		System.out.printf( "wrote file %s, size %d\n", f, value.size() );
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ListLogHandler.java b/compiler/src/main/java/org/apache/etch/compiler/ListLogHandler.java
new file mode 100644
index 0000000..8e47196
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ListLogHandler.java
@@ -0,0 +1,39 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * LogHandler which accumulates messages in a list.
+ */
+public class ListLogHandler extends AbstractLogHandler
+{
+	/** list of accumulated messages */
+	public List<Message> msgs = new ArrayList<Message>();
+
+	@Override
+	protected void log( Message message )
+	{
+		msgs.add( message );
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/LogHandler.java b/compiler/src/main/java/org/apache/etch/compiler/LogHandler.java
new file mode 100644
index 0000000..3b1f11d
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/LogHandler.java
@@ -0,0 +1,226 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+
+/**
+ * This Interface is used for Logging messages. It helps provide a consistent
+ * way of printing and reporting Error, Info and Warning messages.
+ * @author gsandhir
+ *
+ */
+public interface LogHandler
+{
+	/**
+	 * A message which is always printed, but doesn't affect compilation.
+	 * Also usually formatted without level, phase, source, line number, or
+	 * history information.
+	 */
+	public static final int LEVEL_IMPORTANT = 0;
+	
+	/**
+	 * An error level message. Also causes compiler to exit with an error code.
+	 */
+	public static final int LEVEL_ERROR = 1;
+	
+	/**
+	 * A warning level message.
+	 */
+	public static final int LEVEL_WARNING = 2;
+	
+	/**
+	 * An information level message.
+	 */
+	public static final int LEVEL_INFO = 3;
+	
+	/**
+	 * Formats and reports a message without a line number.
+	 * @param level
+	 * @param fmt
+	 * @param params
+	 */
+	public void report( int level, String fmt, Object ... params );
+	
+	/**
+	 * Formats and reports a message with perhaps a line number.
+	 * @param level
+	 * @param lineNumber
+	 * @param fmt
+	 * @param params
+	 */
+	public void report( int level, Integer lineNumber, String fmt,
+		Object ... params );
+	
+	/**
+	 * This method is used to either store or print messages
+	 * @param level indicates ERROR, WARNING or INFO
+	 * @param token indicates the token at which the error occurred
+	 * @param msg String message
+	 * @deprecated use {@link #report(int, Integer, String)} instead.
+	 */
+	@Deprecated
+	public void logMessage( int level, Token token, String msg );
+	
+	/**
+	 * Reports a pre-formatted message perhaps with a line number.
+	 * @param level
+	 * @param lineNumber
+	 * @param msg
+	 */
+	public void report( int level, Integer lineNumber, String msg );
+	
+	/**
+	 * Determines if a message is interesting given its level.
+	 * @param level
+	 * @return true if a message is interesting given its level.
+	 */
+	public boolean isInteresting( int level );
+	
+	/**
+	 * Pushes a new source on the stack.
+	 * @param newSource new source name being read.
+	 * @param lineNumberInOldSource line number in old source which caused the new
+	 * source to be read. This should be null for the top level source.
+	 */
+	public void push( String newSource, Integer lineNumberInOldSource );
+	
+	/**
+	 * Removes the source that was added by the last push method.
+	 * It behaves exactly like the pop method in Stacks
+	 * @param oldSource the source name we just finished reading. This was
+	 * previously passed as the argument to the last push.
+	 */
+	public void pop( String oldSource );
+	
+	/**
+	 * @return true if an error has been reported.
+	 */
+	public boolean hasError();
+	
+	/**
+	 * @return count of errors that have been reported.
+	 */
+	public int errorCount();
+	
+	/**
+	 * @return true if a warning has been reported.
+	 */
+	public boolean hasWarning();
+	
+	/**
+	 * @return count of warnings that have been reported.
+	 */
+	public int warningCount();
+
+	/**
+	 * Gets the level of logging.
+	 * @return the current level of logging. Only messages with level less than
+	 * or equal to this value will be logged.
+	 */
+	public int getLevel();
+	
+	/**
+	 * Sets the level of logging. Only messages with level less than
+	 * or equal to this value will be logged.
+	 * @param level the level of logging
+	 */
+	public void setLevel( int level );
+	
+	/**
+	 * @return the current phase of processing. The initial value is null.
+	 */
+	public String getPhase();
+	
+	/**
+	 * Sets the current phase of processing.
+	 * @param phase may be null.
+	 */
+	public void setPhase( String phase );
+	
+	/**
+	 * Final condensation of the information of a report.
+	 */
+	public static class Message
+	{
+		/**
+		 * @param level
+		 * @param phase
+		 * @param source
+		 * @param lineNumber
+		 * @param msg
+		 * @param history
+		 */
+		public Message( int level, String phase, String source,
+			Integer lineNumber, String msg, History[] history )
+		{
+			this.level = level;
+			this.phase = phase;
+			this.source = source;
+			this.lineNumber = lineNumber;
+			this.msg = msg;
+			this.history = history;
+		}
+		
+		/** the level of the report */
+		public final int level;
+		
+		/** the phase of processing when the report was made */
+		public final String phase;
+		
+		/** the current input source */
+		public final String source;
+		
+		/** the line number of the source which caused the report (if any) */
+		public final Integer lineNumber;
+		
+		/** the text of the report */
+		public final String msg;
+		
+		/** the history of sources previous to source / lineNumber above */
+		public final History[] history;
+	}
+
+	/**
+	 * Record of the input streams previous to the last one pushed.
+	 */
+	public static class History
+	{
+		/**
+		 * @param source
+		 * @param lineNumber
+		 */
+		public History( String source, int lineNumber )
+		{
+			this.source = source;
+			lineNum = lineNumber;
+		}
+		
+		/**
+		 * The source of the input stream (file, stdin, etc.)
+		 */
+		public final String source;
+		
+		/**
+		 * The line number of the source which caused a new source to be pushed.
+		 */
+		public final int lineNum;
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/NullCompiler.java b/compiler/src/main/java/org/apache/etch/compiler/NullCompiler.java
new file mode 100644
index 0000000..2710aed
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/NullCompiler.java
@@ -0,0 +1,172 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+import java.io.IOException;
+
+import org.apache.etch.compiler.ast.Message;
+import org.apache.etch.compiler.ast.Module;
+import org.apache.etch.compiler.ast.Named;
+import org.apache.etch.compiler.ast.ParamList;
+import org.apache.etch.compiler.ast.Service;
+import org.apache.etch.compiler.ast.TypeRef;
+
+
+/**
+ * Compiler which doesn't generated any code.
+ */
+public class NullCompiler extends Backend
+{
+	/**
+	 * Constructs the NullCompiler.
+	 * @throws Exception
+	 */
+	public NullCompiler() throws Exception
+	{
+		// TODO Auto-generated constructor stub
+	}
+
+	@Override
+	public void addDefaults( Service service ) throws ParseException
+	{
+		addBuiltin( service, newName( "List" ), "", true );
+		addBuiltin( service, newName( "Map" ), "", true );
+		addBuiltin( service, newName( "Set" ), "", true );
+		addBuiltin( service, newName( "Datetime" ), "", false );
+	}
+
+	@Override
+	public String asyncReceiverPoolName( Message msg )
+	{
+		// ignore
+		return null;
+	}
+
+	@Override
+	public String enum_efqname( String fqname, String moduleName,
+		String serviceName, String enumName )
+	{
+		// ignore
+		return null;
+	}
+
+	@Override
+	public String except_efqname( String fqname, String moduleName,
+		String serviceName, String enumName )
+	{
+		// ignore
+		return null;
+	}
+
+	@Override
+	public String formatString( ParamList<Service> n, boolean isExcept )
+		throws ParseException, IOException
+	{
+		// ignore
+		return null;
+	}
+
+	@Override
+	public void generate( Module module, CmdLineOptions options )
+		throws Exception
+	{
+		// ignore
+	}
+
+	@Override
+	public String getLang()
+	{
+		// ignore
+		return null;
+	}
+
+	@Override
+	public String getNativeTypeName( TypeRef type )
+	{
+		// ignore
+		return null;
+	}
+
+	@Override
+	public String getTypeName( TypeRef type )
+	{
+		// ignore
+		return null;
+	}
+
+	@Override
+	public String getTypeValue( TypeRef type, Token value ) throws IOException,
+		Exception
+	{
+		// ignore
+		return null;
+	}
+
+	@Override
+	public String getValidator( Named<?> named )
+	{
+		// ignore
+		return null;
+	}
+
+	@Override
+	public String mfvname( String vname )
+	{
+		// ignore
+		return null;
+	}
+
+	@Override
+	public String mtvname( String vname )
+	{
+		// ignore
+		return null;
+	}
+
+	@Override
+	public String qualifyConstantName( Service intf, Token name )
+	{
+		// ignore
+		return null;
+	}
+
+	@Override
+	public String qualifyEnumName( Service intf, Token name )
+	{
+		// ignore
+		return null;
+	}
+
+	@Override
+	public String qualifyParameterName( Token name )
+	{
+		// ignore
+		return null;
+	}
+
+	@Override
+	public String struct_efqname( String fqname, String moduleName,
+		String serviceName, String enumName )
+	{
+		// ignore
+		return null;
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/NullOutput.java b/compiler/src/main/java/org/apache/etch/compiler/NullOutput.java
new file mode 100644
index 0000000..f5dde71
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/NullOutput.java
@@ -0,0 +1,60 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Implementation of Output which does nothing.
+ */
+public class NullOutput implements Output
+{
+	public OutputStream newOutputStream( String fn )
+	{
+		return new OutputStream()
+		{
+			@Override
+			public void write( int b ) throws IOException
+			{
+				// ignore, we don't want the output.
+			}
+		};
+	}
+
+	public Output newPackage( String pn )
+	{
+		// ignore, we don't care what the package is.
+		return this;
+	}
+	
+	public void report( String what )
+	{
+		// ignore, nothing to report.
+	}
+
+	public void saveFiles( File outputDir, boolean noQualOutputDir,
+		boolean noFlattenPackages, boolean force )
+	{
+		// ignore, nothing to save.
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/Output.java b/compiler/src/main/java/org/apache/etch/compiler/Output.java
new file mode 100644
index 0000000..fec2a13
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/Output.java
@@ -0,0 +1,64 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Interface of an output container for the compiler.
+ */
+public interface Output
+{
+	/**
+	 * Creates an OutputStream for the output file.
+	 * @param fn
+	 * @return a new OutputStream for the output file.
+	 */
+	public OutputStream newOutputStream( String fn );
+
+	/**
+	 * Creates a new Output to hold the output for the package.
+	 * @param pn
+	 * @return a new Output.
+	 */
+	public Output newPackage( String pn );
+	
+	/**
+	 * Reports on the contents of the Output.
+	 * @param what
+	 */
+	public void report( String what );
+
+	/**
+	 * Saves the files in this output container.
+	 * @param outputDir the directory for the output files.
+	 * @param noQualOutputDir if true do not qualify the file name with the
+	 * module name.
+	 * @param noFlattenPackages if true do not flatten the directory structure
+	 * implied by the module name.
+	 * @param force if true always overwrite files.
+	 * @throws IOException 
+	 */
+	public void saveFiles( File outputDir, boolean noQualOutputDir,
+		boolean noFlattenPackages, boolean force ) throws IOException;
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/StackInputStream.java b/compiler/src/main/java/org/apache/etch/compiler/StackInputStream.java
new file mode 100644
index 0000000..61d2f15
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/StackInputStream.java
@@ -0,0 +1,102 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Input stream to support include in the etch compiler.
+ */
+public class StackInputStream extends InputStream
+{
+	static int nOnce = 0;
+	
+	private InputStream mainStream = null;
+	private InputStream includeStream = null;
+	private InputStream currentStream = null;
+
+	/**
+	 * Constructs the StackInputStream.
+	 * @param in1
+	 */
+	public StackInputStream(InputStream in1)
+	{
+		mainStream = in1;
+		currentStream = mainStream;
+	}
+
+	/**
+	 * @param in2
+	 */
+	public void setStreamTwo(InputStream in2)
+	{
+		includeStream = in2;
+	}
+
+	/**
+	 * @param val
+	 */
+	public void ActivateStream(int val)
+	{
+		if(val == 0)
+		{
+			currentStream = mainStream;
+		}
+		else if(val == 1)
+		{
+			currentStream = includeStream;
+		}
+	}
+	
+	@Override
+	public int read()
+	{
+		int val = 0;
+		try
+		{
+			val = currentStream.read();
+		}
+		catch ( IOException e )
+		{
+			e.printStackTrace();
+		}
+		
+		if(val == -1 && nOnce == 0 && includeStream != null)
+		{
+			System.out.println("------Stack Reset To Stream 0 >>>> " + val);
+			ActivateStream(1);
+			try
+			{
+				val = currentStream.read();
+			}
+			catch ( IOException e )
+			{
+				e.printStackTrace();
+			}
+			nOnce = 1;
+		}
+		
+	
+		System.out.println("------Stack Read >>>> " + val);
+		return val;
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/Version.java b/compiler/src/main/java/org/apache/etch/compiler/Version.java
new file mode 100644
index 0000000..de23cb0
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/Version.java
@@ -0,0 +1,30 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+/**
+ * The version info of the Etch frontend (parser)
+ */
+public interface Version
+{
+	/** The version of the Etch frontend (parser) */
+	public String VERSION = "Apache Etch 1.1.0-incubating (LOCAL-0)";
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/Version.java.tmpl b/compiler/src/main/java/org/apache/etch/compiler/Version.java.tmpl
new file mode 100644
index 0000000..4ec667c
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/Version.java.tmpl
@@ -0,0 +1,27 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+/**
+ * The version info of the Etch frontend (parser)
+ */
+public interface Version
+{
+	/** The version of the Etch frontend (parser) */
+	public String VERSION = "Apache Etch @EtchLongVersion@ (@EtchBuildTag@)";
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/AbstractTreeWalker.java b/compiler/src/main/java/org/apache/etch/compiler/ast/AbstractTreeWalker.java
new file mode 100644
index 0000000..c7ecaa2
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/AbstractTreeWalker.java
@@ -0,0 +1,134 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+/**
+ * An implementation of tree walker that does nothing. Useful for
+ * instances where you want to look at a few things during a tree
+ * walk but don't want to look at everything.
+ */
+public class AbstractTreeWalker implements TreeWalker
+{
+	public void doExtern( Extern extern )
+	{
+		// ignore.
+	}
+
+	public void doItem( Item item )
+	{
+		// ignore.
+	}
+
+	public void doMixin( Mixin mixin )
+	{
+		// ignore.
+	}
+
+	public void doThrown( Thrown thrown )
+	{
+		// ignore.
+	}
+
+	public void doTypeRef( TypeRef ref )
+	{
+		// ignore.
+	}
+
+	public void postConstant( Constant constant )
+	{
+		// ignore.
+	}
+
+	public void postEnum( Enumx enumx )
+	{
+		// ignore.
+	}
+
+	public void postExcept( Except except )
+	{
+		// ignore.
+	}
+
+	public void postMessage( Message message )
+	{
+		// ignore.
+	}
+
+	public void postModule( Module module )
+	{
+		// ignore.
+	}
+
+	public void postParameter( Parameter parameter )
+	{
+		// ignore.
+	}
+
+	public void postService( Service service )
+	{
+		// ignore.
+	}
+
+	public void postStruct( Struct struct )
+	{
+		// ignore.
+	}
+
+	public void preConstant( Constant constant )
+	{
+		// ignore.
+	}
+
+	public void preEnum( Enumx enumx )
+	{
+		// ignore.
+	}
+
+	public void preExcept( Except except )
+	{
+		// ignore.
+	}
+
+	public void preMessage( Message message )
+	{
+		// ignore.
+	}
+
+	public void preModule( Module module )
+	{
+		// ignore.
+	}
+
+	public void preParameter( Parameter parameter )
+	{
+		// ignore.
+	}
+
+	public void preService( Service service )
+	{
+		// ignore.
+	}
+
+	public void preStruct( Struct struct )
+	{
+		// ignore.
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/AsyncReceiverMode.java b/compiler/src/main/java/org/apache/etch/compiler/ast/AsyncReceiverMode.java
new file mode 100644
index 0000000..c0b192e
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/AsyncReceiverMode.java
@@ -0,0 +1,51 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+/**
+ * Flag that controls how the message receiver dispatches
+ * and runs the implementation method.
+ */
+public enum AsyncReceiverMode
+{
+	/**
+	 * Async receiver mode is disabled. The message runs synchronously.
+	 */
+	NONE,
+	
+	/**
+	 * Async receiver queued mode. The message is queued to a thread pool.
+	 */
+	QUEUED,
+	
+	/**
+	 * Async receiver queued mode. The message is queued to a thread pool.
+	 * This is an alias for QUEUED.
+	 * @deprecated use queued instead.
+	 */
+	@Deprecated
+	POOL,
+	
+	/**
+	 * Async receiver free mode. THe message runs on a free thread.
+	 */
+	FREE
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Builtin.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Builtin.java
new file mode 100644
index 0000000..7d78b00
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Builtin.java
@@ -0,0 +1,119 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.ParseException;
+
+
+/**
+ * A built-in declaration from the binding.
+ */
+public class Builtin extends ParamList<Service>
+{
+	/**
+	 * Constructs the Builtin.
+	 *
+	 * @param intf
+	 * @param name
+	 * @param bindingName
+	 * @param allowSubclass
+	 */
+	public Builtin( Service intf, Name name, String bindingName,
+		boolean allowSubclass )
+	{
+		super( intf, name, null );
+		this.bindingName = bindingName;
+		this.allowSubclass = allowSubclass;
+	}
+	
+	private final String bindingName;
+	
+	private final boolean allowSubclass;
+	
+	@Override
+	public String toString()
+	{
+		return String.format( "built-in %s( %s )", name(), bindingName );
+	}
+
+	@Override
+	public Service service()
+	{
+		return parent();
+	}
+
+	@Override
+	public void check()
+	{
+		// nothing to do.
+	}
+	
+	/**
+	 * @return the binding name of this built-in. For example,
+	 * Map's binding name for java is java.util.Map<Object, Object>
+	 */
+	public String bindingName()
+	{
+		return bindingName;
+	}
+
+	/**
+	 * @return whether this type allows subclassing or whether the
+	 * classes must match exactly.
+	 */
+	public boolean allowSubclass()
+	{
+		return allowSubclass;
+	}
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%sbuiltin %s: %s\n", indent, name(), bindingName );
+	}
+
+	@Override
+	public String fqname()
+	{
+		return bindingName;
+	}
+
+	@Override
+	public void treewalk( TreeWalker walker ) throws ParseException
+	{
+		// nothing to do.
+	}
+
+	@Override
+	public String vname( Backend helper )
+	{
+		return null;
+	}
+
+	/**
+	 * @return the name of the builtin class.
+	 */
+	public String className()
+	{
+		return bindingName;
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Constant.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Constant.java
new file mode 100644
index 0000000..f1e771d
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Constant.java
@@ -0,0 +1,313 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import java.util.Map;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.Token;
+
+
+/**
+ * A named constant declaration from the etch idl.
+ */
+public class Constant extends Named<Service>
+{
+	/**
+	 * Constructs the Constant.
+	 *
+	 * @param intf
+	 * @param name
+	 * @param nOpts
+	 * @param type
+	 * @param value
+	 */
+	public Constant( Service intf, Name name, Map<String, Opt> nOpts,
+		TypeRef type, Token value )
+	{
+		super( intf, name, nOpts );
+		this.type = type;
+		this.value = value;
+	}
+	
+	private final TypeRef type;
+	
+	private final Token value;
+	
+	/**
+	 * @return the type of this constant.
+	 */
+	public TypeRef type()
+	{
+		return type;
+	}
+	
+	/**
+	 * @return the value of this constant.
+	 */
+	public Token value()
+	{
+		return value;
+	}
+	
+	@Override
+	public String vname( Backend helper )
+	{
+		return null;
+	}
+	
+	@Override
+	public String fqname()
+	{
+		return null;
+	}
+	
+//	@Override
+//	public Integer id()
+//	{
+//		return null;
+//	}
+	
+	@Override
+	public String toString()
+	{
+		return String.format( "const %s %s = %s", type, name().name, value );
+	}
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%sconst %s %s = %s\n", indent, type, name().name, value );
+		
+		String sIndent = indent+"  ";
+		
+		for (String s: descr())
+			System.out.printf( "%sdescr %s\n", sIndent, s );
+	}
+
+	@Override
+	public void check() throws ParseException
+	{
+		checkConstantName( name() );
+		
+		// types: boolean, byte, short, int, long, float, double, string
+		// values: true, false, integer, octal, hex, binary, decimal, str
+		
+		switch (type.type().kind)
+		{
+			case EtchGrammarConstants.BOOLEAN:
+				if (!isBoolean( value ))
+					incompatValueForType( type, value );
+				break;
+			case EtchGrammarConstants.BYTE:
+				if (!isByte( value ))
+					incompatValueForType( type, value );
+				break;
+			case EtchGrammarConstants.SHORT:
+				if (!isShort( value ))
+					incompatValueForType( type, value );
+				break;
+			case EtchGrammarConstants.INT:
+				if (!isInt( value ))
+					incompatValueForType( type, value );
+				break;
+			case EtchGrammarConstants.LONG:
+				if (!isLong( value ))
+					incompatValueForType( type, value );
+				break;
+			case EtchGrammarConstants.FLOAT:
+				if (!isFloat( value ))
+					incompatValueForType( type, value );
+				break;
+			case EtchGrammarConstants.DOUBLE:
+				if (!isDouble( value ))
+					incompatValueForType( type, value );
+				break;
+			case EtchGrammarConstants.STRING:
+				if (!isString( value ))
+					incompatValueForType( type, value );
+				break;
+			default:
+				throw new ParseException( "unknown type "+type.type() );
+		}
+	}
+
+	private void incompatValueForType( TypeRef t, Token v ) throws ParseException
+	{
+		throw new ParseException( String.format(
+			"incompatible value for type %s at line %d: %s",
+			type.type(), value.beginLine, value ) );
+	}
+
+	private boolean isBoolean( Token v )
+	{
+		if (v.kind == EtchGrammarConstants.TRUE)
+			return true;
+		if (v.kind == EtchGrammarConstants.FALSE)
+			return true;
+		return false;
+	}
+
+	private boolean isByte( Token v )
+	{
+		if (v.kind == EtchGrammarConstants.INTEGER)
+			return checkByte( v.image, 10 );
+		if (v.kind == EtchGrammarConstants.OCTAL)
+			return v.image.startsWith( "0" ) && checkByte( v.image.substring( 1 ), 8 );
+		if (v.kind == EtchGrammarConstants.HEX)
+			return v.image.toLowerCase().startsWith( "0x" ) && checkByte( v.image.substring( 2 ), 16 );
+		if (v.kind == EtchGrammarConstants.BINARY)
+			return v.image.toLowerCase().startsWith( "0b" ) && checkByte( v.image.substring( 2 ), 2 );
+		return false;
+	}
+
+	private boolean checkByte( String s, int radix )
+	{
+		if (radix == 10)
+			return checkNumber( s, radix, -128, 127 );
+		return checkNumber( s, radix, 0, 255 );
+	}
+
+	private boolean isShort( Token v )
+	{
+		if (v.kind == EtchGrammarConstants.INTEGER)
+			return checkShort( v.image, 10 );
+		if (v.kind == EtchGrammarConstants.OCTAL)
+			return v.image.startsWith( "0" ) && checkShort( v.image.substring( 1 ), 8 );
+		if (v.kind == EtchGrammarConstants.HEX)
+			return v.image.toLowerCase().startsWith( "0x" ) && checkShort( v.image.substring( 2 ), 16 );
+		if (v.kind == EtchGrammarConstants.BINARY)
+			return v.image.toLowerCase().startsWith( "0b" ) && checkShort( v.image.substring( 2 ), 2 );
+		return false;
+	}
+
+	private boolean checkShort( String s, int radix )
+	{
+		if (radix == 10)
+			return checkNumber( s, radix, -32768, 32767 );
+		return checkNumber( s, radix, 0, 65535 );
+	}
+
+	private boolean isInt( Token v )
+	{
+		if (v.kind == EtchGrammarConstants.INTEGER)
+			return checkInt( v.image, 10 );
+		if (v.kind == EtchGrammarConstants.OCTAL)
+			return v.image.startsWith( "0" ) && checkInt( v.image.substring( 1 ), 8 );
+		if (v.kind == EtchGrammarConstants.HEX)
+			return v.image.toLowerCase().startsWith( "0x" ) && checkInt( v.image.substring( 2 ), 16 );
+		if (v.kind == EtchGrammarConstants.BINARY)
+			return v.image.toLowerCase().startsWith( "0b" ) && checkInt( v.image.substring( 2 ), 2 );
+		return false;
+	}
+
+	private boolean checkInt( String s, int radix )
+	{
+		if (radix == 10)
+			return checkNumber( s, radix, -2147483648, 2147483647 );
+		return checkNumber( s, radix, 0, 4294967295L );
+	}
+
+	private boolean isLong( Token v )
+	{
+		if (v.kind == EtchGrammarConstants.INTEGER)
+			return checkLong( v.image, 10 );
+		if (v.kind == EtchGrammarConstants.OCTAL)
+			return v.image.startsWith( "0" ) && checkLong( v.image.substring( 1 ), 8 );
+		if (v.kind == EtchGrammarConstants.HEX)
+			return v.image.toLowerCase().startsWith( "0x" ) && checkLong( v.image.substring( 2 ), 16 );
+		if (v.kind == EtchGrammarConstants.BINARY)
+			return v.image.toLowerCase().startsWith( "0b" ) && checkLong( v.image.substring( 2 ), 2 );
+		return false;
+	}
+
+	private boolean checkLong( String s, int radix )
+	{
+		if (radix == 10)
+			return checkNumber( s, radix, -9223372036854775808L, 9223372036854775807L );
+		return checkNumber( s, radix, 0, -1L );
+	}
+
+	private boolean checkNumber( String s, int radix, long min, long max )
+	{
+		// TODO this needs to work better for non-decimal radix
+		try
+		{
+			long l = Long.parseLong( s, radix );
+			return l >= min && l <= max;
+		}
+		catch ( NumberFormatException e )
+		{
+			return false;
+		}
+	}
+
+	private boolean isFloat( Token v )
+	{
+		// TODO implement some sort of float value checking...
+		if (v.kind == EtchGrammarConstants.INTEGER)
+			return true;
+		if (v.kind == EtchGrammarConstants.OCTAL)
+			return true;
+		if (v.kind == EtchGrammarConstants.HEX)
+			return true;
+		if (v.kind == EtchGrammarConstants.BINARY)
+			return true;
+		if (v.kind == EtchGrammarConstants.DECIMAL)
+			return true;
+		return false;
+	}
+
+	private boolean isDouble( Token v )
+	{
+		// TODO implement some sort of double value checking...
+		if (v.kind == EtchGrammarConstants.INTEGER)
+			return true;
+		if (v.kind == EtchGrammarConstants.OCTAL)
+			return true;
+		if (v.kind == EtchGrammarConstants.HEX)
+			return true;
+		if (v.kind == EtchGrammarConstants.BINARY)
+			return true;
+		if (v.kind == EtchGrammarConstants.DECIMAL)
+			return true;
+		return false;
+	}
+
+	private boolean isString( Token v )
+	{
+		if (v.kind == EtchGrammarConstants.STR)
+			return true;
+		return false;
+	}
+
+	@Override
+	public void treewalk( TreeWalker walker ) throws ParseException
+	{
+		walker.preConstant( this );
+		
+		type.treewalk( walker );
+		
+		walker.postConstant( this );
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Enumx.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Enumx.java
new file mode 100644
index 0000000..028efdf
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Enumx.java
@@ -0,0 +1,151 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.ParseException;
+
+
+/**
+ * An enumeration (named set of named constants) declaration from the etch idl.
+ */
+public class Enumx extends Named<Service> implements Iterable<Item>
+{
+	/**
+	 * Constructs the Enumx.
+	 *
+	 * @param intf
+	 * @param name
+	 * @param nOpts
+	 */
+	public Enumx( Service intf, Name name, Map<String, Opt> nOpts )
+	{
+		super( intf, name, nOpts );
+		
+		moduleName = intf.parent().name().name;
+		serviceName = intf.name().name;
+		enumName = name.name;
+
+		fqname = moduleName+'.'+serviceName+'.'+enumName;
+		vname = fqname.replace( '.', '_' );
+	}
+	
+	private final String moduleName;
+	
+	private final String serviceName;
+	
+	private final String enumName;
+	
+	private final String vname;
+	
+	private final String fqname;
+	
+	@Override
+	public String vname( Backend helper )
+	{
+		return helper.mtvname( vname );
+	}
+	
+	@Override
+	public String fqname()
+	{
+		return fqname;
+	}
+	
+	@Override
+	public String efqname( Backend helper )
+	{
+		return helper.enum_efqname( fqname, moduleName, serviceName, enumName );
+	}
+
+	/**
+	 * Adds a item to the enumeration.
+	 * @param name
+	 * @return the item added.
+	 * @throws ParseException
+	 */
+	public Item addItem( Name name ) throws ParseException
+	{
+		list.check( name );
+		Item i = new Item( this, name );
+		list.add( i.name(), i );
+		return i;
+	}
+	
+	private final NameList<Item> list = new NameList<Item>();
+
+	@Override
+	public String toString()
+	{
+		return String.format( "enum %s %s", name(), list );
+	}
+	
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%senum %s\n", indent, name() );
+		
+		String sIndent = indent+"  ";
+		
+		for (String s: descr())
+			System.out.printf( "%sdescr %s\n", sIndent, s );
+		
+		for (Item i: list)
+			i.dump( sIndent );
+	}
+
+	@Override
+	public void check()
+	{
+		checkTypeName( name() );
+		
+		for (Item i: list)
+			i.check();
+	}
+
+	public Iterator<Item> iterator()
+	{
+		return list.iterator();
+	}
+
+	/**
+	 * @param name
+	 * @return the enum item.
+	 */
+	public Item getItem( String name )
+	{
+		return list.get( name );
+	}
+
+	@Override
+	public void treewalk( TreeWalker walker ) throws ParseException
+	{
+		walker.preEnum( this );
+		
+		for (Item i: this)
+			i.treewalk( walker );
+		
+		walker.postEnum( this );
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Except.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Except.java
new file mode 100644
index 0000000..729a934
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Except.java
@@ -0,0 +1,242 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.opt.Unchecked;
+
+
+/**
+ * An exception declaration from the etch idl.
+ */
+public class Except extends ParamList<Service>
+{
+	/**
+	 * Constructs the Except.
+	 *
+	 * @param intf
+	 * @param name
+	 * @param opts
+	 */
+	public Except( Service intf, Name name, Map<String, Opt> opts )
+	{
+		super( intf, name, opts );
+		
+		moduleName = intf.parent().name().name;
+		serviceName = intf.name().name;
+		exceptName = name.name;
+
+		fqname = moduleName+'.'+serviceName+'.'+exceptName;
+		vname = fqname.replace( '.', '_' );
+	}
+	
+	private final String moduleName;
+	
+	private final String serviceName;
+	
+	private final String exceptName;
+	
+	private final String vname;
+	
+	private final String fqname;
+
+	@Override
+	public String vname( Backend helper )
+	{
+		return helper.mtvname( vname );
+	}
+
+	@Override
+	public String fqname()
+	{
+		return fqname;
+	}
+	
+	@Override
+	public String efqname( Backend helper )
+	{
+		return helper.enum_efqname( fqname, moduleName, serviceName, exceptName );
+	}
+
+	@Override
+	public String toString()
+	{
+		return String.format( "except %s (%s)", name(), getParameters() );
+	}
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%sexception %s\n", indent, name() );
+		
+		String sIndent = indent+"  ";
+		
+		for (String s: descr())
+			System.out.printf( "%sdescr %s\n", sIndent, s );
+		
+		for (Parameter p: this)
+			p.dump( sIndent );
+	}
+
+	@Override
+	public void check() throws ParseException
+	{
+		checkTypeName( name() );
+		
+		for (Parameter p: this)
+			p.check();
+		
+		if (hasExtends())
+		{
+			Named<?> n = parent().get( xtnds.name );
+
+			if (n == null)
+				throw new ParseException( String.format(
+					"exception %s extends %s not defined at line %d",
+					name(), xtnds.name(), xtnds.token.beginLine ) );
+			
+			if (!(n instanceof Except))
+				throw new ParseException( String.format(
+					"exception %s extends %s not an exception at line %d",
+					name(), xtnds.name(), xtnds.token.beginLine ) );
+			
+			Except s = this;
+			while (s != null && s.hasExtends())
+			{
+				s = s.getExtends();
+				if (s == this)
+					throw new ParseException( String.format(
+						"exception %s extends %s creates loop at line %d",
+						name(), xtnds.name(), xtnds.token.beginLine ) );
+			}
+			
+			s = getExtends();
+			for (Parameter p: this)
+			{
+				Parameter x = s.getParameter( p.name().name );
+				if (x != null)
+					throw new ParseException( String.format(
+						"exception %s extends %s hides parameter %s from %s at line %d",
+						name(), xtnds.name(), x.name(), x.parent().name(),
+						xtnds.token.beginLine ) );
+			}
+		}
+	}
+	
+	@Override
+	public Parameter getParameter( String n )
+	{
+		Parameter p = super.getParameter( n );
+		if (p == null && hasExtends())
+			p = getExtends().getParameter( n );
+		return p;
+	}
+	
+	/**
+	 * @return the list of all parameters including those from superclasses.
+	 * They are returned in declaration order, starting with those from the
+	 * base class.
+	 */
+	public List<Parameter> getAllParameters()
+	{
+		if (hasExtends())
+		{
+			List<Parameter> list = new ArrayList<Parameter>();
+			list.addAll( getExtends().getAllParameters() );
+			list.addAll( getParameters() );
+			return list;
+		}
+		return getParameters();
+	}
+	
+	/**
+	 * @return true if any parameters are declared in this or a super.
+	 */
+	public boolean hasAnyParameters()
+	{
+		return hasParameters() ||
+			hasExtends() && getExtends().hasAnyParameters();
+	}
+
+	@Override
+	public Service service()
+	{
+		return parent();
+	}
+	
+	/**
+	 * @return returns true if this is an unchecked exception.
+	 */
+	public boolean isUnchecked()
+	{
+		Unchecked u = (Unchecked) getOpt( "Unchecked" );
+		return u != null && u.isUnchecked();
+	}
+
+	@Override
+	public void treewalk( TreeWalker walker ) throws ParseException
+	{
+		walker.preExcept( this );
+		
+		for (Parameter p: this)
+			p.treewalk( walker );
+		
+		if (hasExtends())
+			getExtends().treewalk( walker );
+		
+		walker.postExcept( this );
+	}
+	
+	/**
+	 * @return true if this exception extends another.
+	 */
+	public boolean hasExtends()
+	{
+		return xtnds != null;
+	}
+	
+	/**
+	 * @return the exception that this one extends or null.
+	 */
+	public Except getExtends()
+	{
+		if (xtnds == null)
+			return null;
+		
+		return (Except) parent().get( xtnds.name );
+	}
+
+	/**
+	 * Sets the extends attribute of this exception.
+	 * @param xtnds
+	 */
+	public void setExtends( Name xtnds )
+	{
+		this.xtnds = xtnds;
+	}
+	
+	private Name xtnds;
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Extern.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Extern.java
new file mode 100644
index 0000000..fae18f8
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Extern.java
@@ -0,0 +1,166 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import java.util.Map;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.ParseException;
+
+
+/**
+ * An extern declaration from the etch idl.
+ */
+public class Extern extends ParamList<Service>
+{
+	/**
+	 * @param intf
+	 * @param name
+	 * @param opts
+	 */
+	public Extern( Service intf, Name name, Map<String, Opt> opts )
+	{
+		super( intf, name, opts );
+
+		vname = intf.parent().name().name.replace( '.', '_' )+'_'+intf.name()+'_'+name;
+		fqname = intf.parent().name().name+'.'+intf.name().name+'.'+name.name;
+	}
+	
+	private final String vname;
+	
+	private final String fqname;
+
+	@Override
+	public Service service()
+	{
+		return parent();
+	}
+
+	@Override
+	public void check() throws ParseException
+	{
+		checkTypeName( name() );
+		
+		// nothing to do
+	}
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%sextern %s\n", indent, name() );
+	}
+
+	@Override
+	public String fqname()
+	{
+		return fqname;
+	}
+
+	@Override
+	public String efqname( Backend helper )
+	{
+		String lang = helper.getLang();
+		org.apache.etch.compiler.opt.Extern opt = (org.apache.etch.compiler.opt.Extern) getOpt( "Extern."+lang );
+		if (opt == null)
+			return null;
+		return opt.xname.image;
+	}
+
+	@Override
+	public String vname( Backend helper )
+	{
+		return helper.mtvname( vname );
+	}
+	
+	/**
+	 * @param helper
+	 * @return the extern's serializer's name.
+	 */
+	public String sname( Backend helper )
+	{
+		String lang = helper.getLang();
+		org.apache.etch.compiler.opt.Extern opt = (org.apache.etch.compiler.opt.Extern) getOpt( "Extern."+lang );
+		if (opt == null)
+			// TODO need to throw the right thing...
+			throw new UnsupportedOperationException( String.format(
+				"no extern type defined for binding %s: %s at line %d",
+				lang, name().name, name().token.beginLine ) );
+		return opt.serializer.image;
+	}
+	
+	/**
+	 * @param helper
+	 * @return true if the extern needs an import.
+	 */
+	public boolean hasImport( Backend helper )
+	{
+		String lang = helper.getLang();
+		org.apache.etch.compiler.opt.Extern opt = (org.apache.etch.compiler.opt.Extern) getOpt( "Extern."+lang );
+		if (opt == null)
+			return false;
+		return opt.xnameImport.image.length() > 0;
+	}
+	
+	/**
+	 * @param helper
+	 * @return the extern's import.
+	 */
+	public String getImport( Backend helper )
+	{
+		String lang = helper.getLang();
+		org.apache.etch.compiler.opt.Extern opt = (org.apache.etch.compiler.opt.Extern) getOpt( "Extern."+lang );
+		if (opt == null)
+			return null;
+		return opt.xnameImport.image;
+	}
+
+	/**
+	 * @param helper
+	 * @return true if the extern's serializer needs an import.
+	 */
+	public boolean hasSerializerImport( Backend helper )
+	{
+		String lang = helper.getLang();
+		org.apache.etch.compiler.opt.Extern opt = (org.apache.etch.compiler.opt.Extern) getOpt( "Extern."+lang );
+		if (opt == null)
+			return false;
+		return opt.serializerImport.image.length() > 0;
+	}
+
+	/**
+	 * @param helper
+	 * @return the extern's serializer's import.
+	 */
+	public String getSerializerImport( Backend helper )
+	{
+		String lang = helper.getLang();
+		org.apache.etch.compiler.opt.Extern opt = (org.apache.etch.compiler.opt.Extern) getOpt( "Extern."+lang );
+		if (opt == null)
+			return null;
+		return opt.serializerImport.image;
+	}
+
+	@Override
+	public void treewalk( TreeWalker walker ) throws ParseException
+	{
+		walker.doExtern( this );
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Item.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Item.java
new file mode 100644
index 0000000..02c21bb
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Item.java
@@ -0,0 +1,87 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.ParseException;
+
+
+/**
+ * An enumeration item declaration from the etch idl.
+ */
+public class Item extends Named<Enumx>
+{
+	/**
+	 * Constructs the Item.
+	 *
+	 * @param enumx
+	 * @param name
+	 */
+	public Item( Enumx enumx, Name name )
+	{
+		super( enumx, name, null );
+		
+		vname = name.name;
+	}
+	
+	private final String vname;
+	
+	@Override
+	public String vname( Backend helper )
+	{
+		return helper.mfvname( vname );
+	}
+	
+	@Override
+	public String fqname()
+	{
+		return null;
+	}
+	
+	@Override
+	public String toString()
+	{
+		return name().toString();
+	}
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%sitem %s\n", indent, name().name );
+		
+		String sIndent = indent+"  ";
+		
+		for (String s: descr())
+			System.out.printf( "%sdescr %s\n", sIndent, s );
+	}
+
+	@Override
+	public void check()
+	{
+		checkConstantName( name() );
+	}
+
+	@Override
+	public void treewalk( TreeWalker walker ) throws ParseException
+	{
+		walker.doItem( this );
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Message.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Message.java
new file mode 100644
index 0000000..d01c8ef
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Message.java
@@ -0,0 +1,471 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.opt.AsyncReceiver;
+import org.apache.etch.compiler.opt.Authorize;
+import org.apache.etch.compiler.opt.Direction;
+import org.apache.etch.compiler.opt.Oneway;
+import org.apache.etch.compiler.opt.Timeout;
+
+
+/**
+ * Description of Message.
+ */
+public class Message extends ParamList<Service>
+{
+	/**
+	 * Constructs the Message.
+	 * @param intf
+	 * @param name
+	 * @param nOpts
+	 * @param type
+	 */
+	public Message( Service intf, Name name, Map<String, Opt> nOpts, TypeRef type )
+	{
+		super( intf, name, nOpts );
+
+		md = getMessageDirection();
+		this.type = type;
+	}
+
+	private MessageDirection md;
+
+	private final TypeRef type;
+	
+	/**
+	 * @return the suffix of this message's interface given the direction.
+	 */
+	public String suffix()
+	{
+		return MsgDirHelper.getSuffix( md );
+	}
+	
+	/**
+	 * @return the vname of this message (the fully qualified name with "_" instead of ".").
+	 */
+	public String mkVname()
+	{
+		Service intf = parent();
+		Name name = name();
+		return intf.parent().name().name.replace( '.', '_' )+'_'+intf.name()+'_'+name.name;
+	}
+	
+	/**
+	 * @return the fully qualified name of this message.
+	 */
+	public String mkFqName()
+	{
+		Service intf = parent();
+		Name name = name();
+		return intf.parent().name().name+'.'+intf.name().name+'.'+name.name;
+	}
+
+	/**
+	 * @return the direction of this message.
+	 */
+	public MessageDirection msgDir()
+	{
+		return md;
+	}
+
+	/**
+	 * Sets the message direction of this message.
+	 * @param md
+	 */
+	public void setMsgDir( MessageDirection md )
+	{
+		this.md = md;
+	}
+
+	/**
+	 * @param other
+	 * @return true if this message's direction equals other.
+	 */
+	public boolean isMsgDir( MessageDirection other )
+	{
+		return md == other;
+	}
+
+	/**
+	 *
+	 * @return trus if this message's direction is both
+	 */
+	public boolean isMsgDirBoth()
+	{
+		return md == MessageDirection.BOTH;
+	}
+
+	/**
+	 * @return the message direction per the Direction opt.
+	 */
+	public MessageDirection getMessageDirection()
+	{
+		Opt o = getOpt( "Direction" );
+
+		if (o == null)
+			return MessageDirection.SERVER;
+
+		Direction d = (Direction) o;
+		return d.getMessageDirection();
+	}
+
+	/**
+	 * @return the message timeout per the Timeout opt.
+	 */
+	public int getTimeout()
+	{
+		Opt o = getOpt( "Timeout" );
+
+		if (o == null)
+			return 0;
+
+		Timeout t = (Timeout) o;
+		return t.timeout();
+	}
+
+	/**
+	 * @return the type of this message.
+	 */
+	public TypeRef type()
+	{
+		return type;
+	}
+
+	@Override
+	public String vname( Backend helper )
+	{
+		return helper.mtvname( mkVname() );
+	}
+
+	/**
+	 * @return the fully qualified name of this message.
+	 */
+	@Override
+	public String fqname()
+	{
+		return mkFqName();
+	}
+
+//	/**
+//	 * @return the id of this message.
+//	 */
+//	@Override
+//	public Integer id()
+//	{
+//		return mkId();
+//	}
+
+	@Override
+	public String toString()
+	{
+		return String.format( "message %s %s %s (%s) throws %s", md, type, name(), getParameters(), thrown );
+	}
+
+	/**
+	 * @return the message description.
+	 */
+	public List<String> returnDescr()
+	{
+		return returnDescr;
+	}
+
+	/**
+	 * @param returnDescr
+	 */
+	public void setReturnDescr( List<String> returnDescr )
+	{
+		this.returnDescr = returnDescr;
+	}
+
+	private List<String> returnDescr = new ArrayList<String>();
+
+	/**
+	 * @return the message used to return a result from a call.
+	 */
+	public Message getResultMessage()
+	{
+		return resultMessage;
+	}
+
+	/**
+	 * @param resultMessage
+	 */
+	public void setResultMessage( Message resultMessage )
+	{
+		this.resultMessage = resultMessage;
+	}
+
+	private Message resultMessage;
+
+	/**
+	 * @return true if this is a message which contributes to the
+	 * types and fields but should not appear in the interface
+	 * (because it is a response message)
+	 */
+	public boolean isHidden()
+	{
+		return name().name.startsWith( RESULT_MESSAGE_NAME_PREFIX );
+	}
+
+	/**
+	 * @return the expected name of a result message.
+	 */
+	public Name getResultMessageName()
+	{
+		return new Name( null, RESULT_MESSAGE_NAME_PREFIX+name().name );
+	}
+
+	/**
+	 * The name of the parameter of a result message.
+	 */
+	public static final String RESULT_PARAM_NAME = "result";
+
+	/**
+	 * The prefix to apply to the name of a result message.
+	 */
+	public static final String RESULT_MESSAGE_NAME_PREFIX = "_result_";
+
+	/**
+	 * @return the name of the result parameter.
+	 */
+	public Name getResultParamName()
+	{
+		return new Name( null, RESULT_PARAM_NAME );
+	}
+
+	/**
+	 * @return the result parameter.
+	 */
+	public Parameter getResultParam()
+	{
+		return getParameter( RESULT_PARAM_NAME );
+	}
+
+	/**
+	 * @return true if this is a call (i.e., returns a value.
+	 */
+	public boolean hasReturn()
+	{
+		return type.type().kind != EtchGrammarConstants.VOID;
+	}
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%smethod %s %s %s\n", indent, md, type, name().name );
+
+		String sIndent = indent+"  ";
+
+		for (String s: descr())
+			System.out.printf( "%sdescr %s\n", sIndent, s );
+
+		for (Opt o: opts())
+			o.dump( sIndent );
+
+		for (Parameter p: this)
+			p.dump( sIndent );
+
+		if (hasReturn())
+			System.out.printf( "%sreturnDescr %s\n", sIndent, returnDescr );
+
+		for (Thrown n: thrown)
+			n.dump( sIndent );
+	}
+
+	/**
+	 * Adds a name to the list of exceptions thrown by this message.
+	 * @param n
+	 * @return the representation object for a thrown exception.
+	 * @throws ParseException
+	 */
+	public Thrown addThrown( Name n ) throws ParseException
+	{
+		if (isOneway())
+			throw new ParseException( String.format(
+				"Oneway message cannot throw exception at line %d", n.token.beginLine ) );
+
+		thrown.check( n );
+		Thrown t = new Thrown( this, n );
+		thrown.add( n, t );
+		return t;
+	}
+
+	/**
+	 * @param n
+	 * @return any thrown exception by the specified name.
+	 */
+	public Thrown getThrown( String n )
+	{
+		return thrown.get( n );
+	}
+
+	private final NameList<Thrown> thrown = new NameList<Thrown>();
+
+	/**
+	 * @return true if this message has thrown exceptions.
+	 */
+	public boolean hasThrown()
+	{
+		return !thrown.list().isEmpty();
+	}
+
+	/**
+	 * @return the async receiver mode.
+	 */
+	public AsyncReceiverMode getAsyncReceiver()
+	{
+		AsyncReceiver ar = (AsyncReceiver) getOpt( "AsyncReceiver" );
+
+		if (ar == null)
+			return AsyncReceiverMode.NONE;
+
+		return ar.getMode();
+	}
+
+	/**
+	 * @return true if this method is marked to have an asynchronous
+	 * receiver.
+	 */
+	public boolean isAsyncReceiver()
+	{
+		return getAsyncReceiver() != AsyncReceiverMode.NONE;
+	}
+
+	/**
+	 * @return true if this method is marked to have a queued asynchronous
+	 * receiver.
+	 */
+	public boolean isQueuedAsyncReceiver()
+	{
+		return getAsyncReceiver() == AsyncReceiverMode.QUEUED;
+	}
+
+	/**
+	 * @return true if this method is marked to have a free asynchronous
+	 * receiver.
+	 */
+	public boolean isFreeAsyncReceiver()
+	{
+		return getAsyncReceiver() == AsyncReceiverMode.FREE;
+	}
+
+	/**
+	 * @return true if this is a oneway message which does not wait
+	 * for any response from the other end.
+	 */
+	public boolean isOneway()
+	{
+		Oneway oneway = (Oneway) getOpt( "Oneway" );
+		return oneway != null && oneway.isOneway();
+	}
+
+	/**
+	 * @return true if this message requires authorization.
+	 */
+	public Authorize getAuth()
+	{
+		return (Authorize) getOpt( "Authorize" );
+	}
+
+	/**
+	 * @return true if this message requires authorization.
+	 */
+	public boolean hasAuth()
+	{
+		Authorize auth = getAuth();
+		return auth != null && auth.hasAuth();
+	}
+
+	@Override
+	public void check() throws ParseException
+	{
+		checkMessageName( name() );
+		
+		type.check( parent() );
+
+		for (Parameter p: this)
+			p.check();
+
+		for (Thrown n: thrown)
+			n.check();
+
+		Authorize auth = getAuth();
+		if (auth != null)
+			auth.check( parent(), this );
+	}
+
+	@Override
+	public Service service()
+	{
+		return parent();
+	}
+
+	/**
+	 * @return the list of thrown exceptions.
+	 */
+	public NameList<Thrown> thrown()
+	{
+		return thrown;
+	}
+
+	/**
+	 * @return the request message of this result message.
+	 */
+	public Message getRequestMessage()
+	{
+		return reqMsg;
+	}
+
+	/**
+	 * Sets the request message of this result message.
+	 * @param reqMsg
+	 */
+	public void setRequestMessage( Message reqMsg )
+	{
+		this.reqMsg = reqMsg;
+	}
+
+	private Message reqMsg;
+
+	@Override
+	public void treewalk( TreeWalker walker ) throws ParseException
+	{
+		walker.preMessage( this );
+
+		walker.doTypeRef( type );
+
+		for (Parameter p: this)
+			p.treewalk( walker );
+
+		for (Thrown n: thrown)
+			n.treewalk( walker );
+
+		walker.postMessage( this );
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/MessageDirection.java b/compiler/src/main/java/org/apache/etch/compiler/ast/MessageDirection.java
new file mode 100644
index 0000000..e97b2bc
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/MessageDirection.java
@@ -0,0 +1,42 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+/**
+ * The message direction is whether the message is from client to
+ * server or server to client or both.
+ */
+public enum MessageDirection
+{
+	/**
+	 * This message is used by the client to invoke the server.
+	 */
+	SERVER,
+	/**
+	 * This message is used by the server to invoke the client.
+	 */
+	CLIENT,
+	/**
+	 * This message may be used by either the client or server to invoke the other.
+	 */
+	BOTH
+}
+
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Mixin.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Mixin.java
new file mode 100644
index 0000000..85c99c3
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Mixin.java
@@ -0,0 +1,93 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import java.util.Map;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.ParseException;
+
+
+/**
+ * A mixin declaration from the etch idl.
+ */
+public class Mixin extends Named<Service>
+{
+	/**
+	 * Constructs the Mixin.
+	 *
+	 * @param intf
+	 * @param name
+	 * @param nOpts
+	 * @param mod
+	 */
+	public Mixin( Service intf, Name name, Map<String, Opt> nOpts, Module mod )
+	{
+		super( intf, name, nOpts );
+		this.mod = mod;
+	}
+	
+	private final Module mod;
+	
+	/**
+	 * @return the mixed in module.
+	 */
+	public Module getModule()
+	{
+		return mod;
+	}
+	
+	@Override
+	public String vname( Backend helper )
+	{
+		return null;
+	}
+	
+	@Override
+	public String fqname()
+	{
+		return mod.iterator().next().fqname();
+	}
+	
+//	@Override
+//	public Integer id()
+//	{
+//		return null;
+//	}
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%smixin %s\n", indent, name().name );
+	}
+
+	@Override
+	public void check() throws ParseException
+	{
+		// nothing to do.
+	}
+
+	@Override
+	public void treewalk( TreeWalker walker ) throws ParseException
+	{
+		walker.doMixin( this );
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Module.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Module.java
new file mode 100644
index 0000000..58d1431
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Module.java
@@ -0,0 +1,121 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.CmdLineOptions;
+import org.apache.etch.compiler.ParseException;
+
+
+/**
+ * A module declaration from the etch idl.
+ */
+public class Module extends Named<Module> implements Iterable<Service>
+{
+	/**
+	 * Constructs the Module.
+	 *
+	 * @param name this is the moral equivalent of a java package. It is
+	 * a dotted name list like "com.cisco.cuae.media".
+	 * @param cmdLineOptions our command line options.
+	 */
+	public Module( Name name, CmdLineOptions cmdLineOptions )
+	{
+		super( null, name, null, cmdLineOptions );
+	}
+	
+	@Override
+	public String vname( Backend helper )
+	{
+		return null;
+	}
+	
+	@Override
+	public String fqname()
+	{
+		return name().name;
+	}
+	
+//	@Override
+//	public Integer id()
+//	{
+//		return null;
+//	}
+
+	/**
+	 * @param n
+	 * @param opts
+	 * @return the created service.
+	 * @throws ParseException
+	 */
+	public Service addService( Name n, Map<String, Opt> opts ) throws ParseException
+	{
+		services.check( n );
+		Service i = new Service( this, n, opts );
+		services.add( i.name(), i );
+		return i;
+	}
+	
+	private NameList<Service> services = new NameList<Service>();
+
+
+	public Iterator<Service> iterator()
+	{
+		return services.iterator();
+	}
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%smodule %s;\n", indent, name() );
+		
+		String sIndent = indent+"  ";
+		
+		for (String s: descr())
+			System.out.printf( "%sdescr %s\n", sIndent, s );
+		
+		for (Service i: this)
+			i.dump( sIndent );
+	}
+
+	@Override
+	public void check() throws ParseException
+	{
+		checkModuleName( name() );
+		
+		for (Service i: this)
+			i.check();
+	}
+
+	@Override
+	public void treewalk( TreeWalker walker ) throws ParseException
+	{
+		walker.preModule( this );
+		
+		for (Service s: this)
+			s.treewalk( walker );
+		
+		walker.postModule( this );
+	}
+}
\ No newline at end of file
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/MsgDirHelper.java b/compiler/src/main/java/org/apache/etch/compiler/ast/MsgDirHelper.java
new file mode 100644
index 0000000..c2bdc8a
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/MsgDirHelper.java
@@ -0,0 +1,43 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+/**
+ * Some helpful methods used in conjuction with MessageDirection.
+ */
+public class MsgDirHelper
+{
+	/**
+	 * @param mc
+	 * @return the appropriate suffix for a message name given the
+	 * message direction.
+	 */
+	public static String getSuffix( MessageDirection mc )
+	{
+		switch (mc)
+		{
+			case CLIENT: return "Client";
+			case SERVER: return "Server";
+			case BOTH: return "";
+			default: throw new IllegalArgumentException( "unknown message direction "+mc );
+		}
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Name.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Name.java
new file mode 100644
index 0000000..4c15c87
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Name.java
@@ -0,0 +1,66 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import org.apache.etch.compiler.Token;
+
+/**
+ * A name of a thing from the etch idle. If the token is present,
+ * it can be used to identify the line number of the name.
+ */
+public class Name
+{
+	/**
+	 * Constructs the Name.
+	 *
+	 * @param token
+	 * @param name
+	 */
+	public Name( Token token, String name )
+	{
+		this.token = token;
+		this.name = name;
+	}
+	
+	/**
+	 * The original source of the name. Used to get the line number.
+	 */
+	public final Token token;
+	
+	/**
+	 * The name.
+	 */
+	public final String name;
+	
+	/**
+	 * @return the string of this name.
+	 */
+	public String name()
+	{
+		return name;
+	}
+
+	@Override
+	public String toString()
+	{
+		return name;
+	}
+}
\ No newline at end of file
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/NameList.java b/compiler/src/main/java/org/apache/etch/compiler/ast/NameList.java
new file mode 100644
index 0000000..67753db
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/NameList.java
@@ -0,0 +1,112 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.etch.compiler.ParseException;
+
+
+/**
+ * Abstraction of a list of named items. The items may be retreived in
+ * order added or by name.
+ * @param <T>
+ */
+public class NameList<T> implements Iterable<T>
+{
+	/**
+	 * Checks the name before it is added to the name list.
+	 * @param name
+	 * @throws ParseException
+	 */
+	public void check( Name name ) throws ParseException
+	{
+		if (map.containsKey( name.name ))
+			throw new ParseException( String.format(
+				"duplicate name (%s) at line %d", name.name, name.token.beginLine ) );
+	}
+
+	@Override
+	public String toString()
+	{
+		return list.toString();
+	}
+	
+	/**
+	 * @param name
+	 * @return the named item, or null.
+	 */
+	public T get( String name )
+	{
+		return map.get( name );
+	}
+
+	/**
+	 * Adds the named item to the name list.
+	 * @param name
+	 * @param n
+	 * @throws ParseException
+	 */
+	public void add( Name name, T n ) throws ParseException
+	{
+		check( name );
+		map.put( name.name, n );
+		list.add( n );
+	}
+
+	public Iterator<T> iterator()
+	{
+		return list.iterator();
+	}
+
+	private Map<String, T> map = new HashMap<String, T>();
+	
+	private List<T> list = new ArrayList<T>();
+
+	/**
+	 * @return the name list.
+	 */
+	public List<T> list()
+	{
+		return list;
+	}
+
+	/**
+	 * @return true if the namelist is empty.
+	 */
+	public boolean isEmpty()
+	{
+		return list.isEmpty();
+	}
+
+	/**
+	 * @param name
+	 * @return true if the namelist contains the specified name.
+	 */
+	public boolean has( String name )
+	{
+		return map.containsKey( name );
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Named.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Named.java
new file mode 100644
index 0000000..72f0447
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Named.java
@@ -0,0 +1,308 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.CmdLineOptions;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.Token;
+
+
+/**
+ * Abstraction of a named item from the etch idl.
+ * @param <P> the parent type of this item.
+ */
+abstract public class Named<P extends Named<?>>
+{
+	/**
+	 * Constructs the Named.
+	 *
+	 * @param parent
+	 * @param name
+	 * @param nOpts
+	 */
+	public Named( P parent, Name name, Map<String, Opt> nOpts )
+	{
+		this( parent, name, nOpts, null );
+	}
+	
+	/**
+	 * Constructs the Named.
+	 *
+	 * @param parent
+	 * @param name
+	 * @param nOpts
+	 * @param cmdLineOptions 
+	 */
+	public Named( P parent, Name name, Map<String, Opt> nOpts,
+		CmdLineOptions cmdLineOptions )
+	{
+		this.parent = parent;
+		this.name = name;
+		this.nOpts = nOpts;
+		this.cmdLineOptions = cmdLineOptions;
+	}
+	
+	private final P parent;
+	
+	private final Name name;
+	
+	private final Map<String, Opt> nOpts;
+	
+	private final CmdLineOptions cmdLineOptions;
+	
+	/**
+	 * @return the parent of this item.
+	 */
+	public P parent()
+	{
+		return parent;
+	}
+	
+	/**
+	 * @return the name of this item.
+	 */
+	public Name name()
+	{
+		return name;
+	}
+	
+	/**
+	 * @param n the opt name to check.
+	 * @return true if the opt is present here or in the parent.
+	 */
+	public boolean hasOpt( String n )
+	{
+		return getOpt( n ) != null;
+	}
+	
+	/**
+	 * @return the command line options of us, or those of the parent.
+	 */
+	public CmdLineOptions getCmdLineOptions()
+	{
+		if (cmdLineOptions != null)
+			return cmdLineOptions;
+		
+		return parent != null ? parent.getCmdLineOptions() : null;
+	}
+	
+	/**
+	 * @param n the name of the opt.
+	 * @return the opt if found. if this named does not define
+	 * it, search the parent.
+	 */
+	public Opt getOpt( String n )
+	{
+		Opt opt = null;
+		if (nOpts != null)
+			opt = nOpts.get( n );
+		if (opt == null && parent != null)
+			opt = parent.getOpt( n );
+		return opt;
+	}
+	
+	/**
+	 * @return the opts of this named thing.
+	 */
+	public Collection<Opt> opts()
+	{
+		return nOpts.values();
+	}
+	
+	/**
+	 * @param helper backend to help with name formats
+	 * @return the variable name of this named.
+	 */
+	abstract public String vname( Backend helper );
+	
+	/**
+	 * @return the fully qualified name of this named (as used in Type
+	 * declaration).
+	 */
+	abstract public String fqname();
+
+	/**
+	 * @param helper
+	 * @return the fully qualified enum, struct, or extern name to use
+	 * when refering to the item in code. most probably the same as fqname
+	 * except for extern.
+	 */
+	public String efqname( Backend helper )
+	{
+		return fqname();
+	}
+	
+	/**
+	 * @return true if there is a description.
+	 */
+	public boolean hasDescr()
+	{
+		return descr != null && !descr.isEmpty();
+	}
+	
+	/**
+	 * @return the module description.
+	 */
+	public List<String> descr()
+	{
+		return descr;
+	}
+
+	/**
+	 * @param descr
+	 */
+	public void setDescr( List<String> descr )
+	{
+		this.descr = descr;
+	}
+	
+	private List<String> descr = new ArrayList<String>();
+
+	/**
+	 * Dumps the item nicely formatted.
+	 * @param indent
+	 */
+	abstract public void dump( String indent );
+
+	/**
+	 * Checks the item for being fully defined.
+	 * @throws ParseException
+	 */
+	abstract public void check() throws ParseException;
+
+	protected void checkModuleName( Name name )
+	{
+		boolean ok = true;
+		
+		StringTokenizer st = new StringTokenizer( name.name, "." );
+		while (ok && st.hasMoreTokens())
+			ok = startsWithLower( st.nextToken() );
+		
+		if (!ok)
+			warn(
+				"module element name should start with lowercase",
+				name.name, name.token );
+	}
+
+	protected void checkConstantName( Name name )
+	{
+		if (!name.name.toUpperCase().equals( name.name ))
+			warn(
+				"constant name should be all uppercase",
+				name.name, name.token );
+	}
+
+	protected void checkTypeName( Name name )
+	{
+		if (!startsWithUpper( name.name ))
+			warn(
+				"type name should start with uppercase",
+				name.name, name.token );
+	}
+
+	protected void checkParamName( Name name )
+	{
+		if (!startsWithLower( name.name ))
+			warn(
+				"parameter name should start with lowercase",
+				name.name, name.token );
+	}
+
+	protected void checkMessageName( Name name )
+	{
+		if (!startsWithLower( name.name ))
+			warn(
+				"message name should start with lowercase",
+				name.name, name.token );
+	}
+	
+	private void warn( String msg, String name, Token token )
+	{
+		// TODO turn on warnings for naming conventions.
+//		System.err.printf( "Warning: %s: %s at line %d\n",
+//			msg, name, token != null ? token.beginLine : 0 );
+	}
+	
+	private boolean startsWithLower( String s )
+	{
+		return Character.isLowerCase( s.charAt( 0 ) ) || s.charAt( 0 ) == '_';
+	}
+
+	private boolean startsWithUpper( String s )
+	{
+		return Character.isUpperCase( s.charAt( 0 ) );
+	}
+	
+	/**
+	 * Walks the tree from the top to the bottom, visiting every node.
+	 * @param walker called with each and every node under this one.
+	 * @throws ParseException
+	 */
+	abstract public void treewalk( TreeWalker walker ) throws ParseException;
+	
+	/**
+	 * @return true if this is a constant.
+	 */
+	public boolean isConstant() { return this instanceof Constant; }
+	
+	/**
+	 * @return true if this is an enum.
+	 */
+	public boolean isEnumx() { return this instanceof Enumx; }
+	
+	/**
+	 * @return true if this is a struct.
+	 */
+	public boolean isStruct() { return this instanceof Struct; }
+	
+	/**
+	 * @return true if this is an extern.
+	 */
+	public boolean isExtern() { return this instanceof Extern; }
+	
+	/**
+	 * @return true if this is a built-in.
+	 */
+	public boolean isBuiltin() { return this instanceof Builtin; }
+	
+	/**
+	 * @return true if this is an exception.
+	 */
+	public boolean isExcept() { return this instanceof Except; }
+	
+	/**
+	 * @return true if this is a message.
+	 */
+	public boolean isMessage() { return this instanceof Message; }
+	
+	/**
+	 * @return true if this is a Mixin
+	 */
+	
+	public boolean isMixin() { return this instanceof Mixin; }
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Opt.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Opt.java
new file mode 100644
index 0000000..e9222fa
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Opt.java
@@ -0,0 +1,100 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.etch.compiler.ParseException;
+
+
+/**
+ * Abstract base class of annotations from the etch idl.
+ */
+abstract public class Opt
+{
+	/**
+	 * Constructs the Opt.
+	 *
+	 * @param name the name of this opt. must be unique.
+	 * @param lineno the line number of this opt.
+	 */
+	public Opt( String name, int lineno )
+	{
+		this.name = name;
+		this.lineno = lineno;
+	}
+	
+	private final String name;
+	
+	private final int lineno;
+	
+	private final Set<Class<?>> types = new HashSet<Class<?>>();
+	
+	/**
+	 * @param type adds the specified type to the set of constructs
+	 * to which this opt may be attached. generally only called from
+	 * the constructor of an opt.
+	 */
+	public void addType( Class<?> type )
+	{
+		types.add( type );
+	}
+
+	/**
+	 * @return the name of this option.
+	 */
+	public String name()
+	{
+		return name;
+	}
+	
+	/**
+	 * @return the line number of this opt.
+	 */
+	public int lineno()
+	{
+		return lineno;
+	}
+
+	/**
+	 * Dumps the option nicely formatted.
+	 * @param indent
+	 */
+	abstract public void dump( String indent );
+
+	@Override
+	abstract public String toString();
+
+	/**
+	 * @param type the type of construct to which the opt is attached.
+	 * @throws ParseException
+	 */
+	public void check( Class<?> type ) throws ParseException
+	{
+		if (types != null)
+		{
+			if (!types.contains( type ))
+				throw new ParseException( String.format(
+					"option %s not allowed here, line %d", this, lineno) );
+		}
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/OptList.java b/compiler/src/main/java/org/apache/etch/compiler/ast/OptList.java
new file mode 100644
index 0000000..4b3b98a
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/OptList.java
@@ -0,0 +1,46 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import java.util.Collection;
+
+/**
+ * A list of options (annotations, e.g., @Timeout, @Oneway)
+ */
+public interface OptList
+{
+	/**
+	 * @return the collected options.
+	 */
+	public Collection<Opt> opts();
+	
+	/**
+	 * @param name
+	 * @return true if the item has the specified option.
+	 */
+	public boolean hasOpt( String name );
+	
+	/**
+	 * @param name
+	 * @return the specified option.
+	 */
+	public Opt getOpt( String name );
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/ParamList.java b/compiler/src/main/java/org/apache/etch/compiler/ast/ParamList.java
new file mode 100644
index 0000000..936a93e
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/ParamList.java
@@ -0,0 +1,178 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.opt.ToString.FieldItem;
+import org.apache.etch.compiler.opt.ToString.FmtItem;
+import org.apache.etch.compiler.opt.ToString.StringItem;
+
+
+/**
+ * Abstract base class of service elements which have parameter lists
+ * from the etch idl. This includes struct, exception, and message
+ * elements.
+ * @param <P> the type of the parent object.
+ */
+abstract public class ParamList<P extends Named<?>> extends Named<P>
+	implements Iterable<Parameter>
+{
+	/**
+	 * Constructs the ParamList.
+	 *
+	 * @param parent
+	 * @param name
+	 * @param opts
+	 */
+	public ParamList( P parent, Name name, Map<String, Opt> opts )
+	{
+		super( parent, name, opts );
+	}
+
+	/**
+	 * @param rt
+	 * @param n
+	 * @return the parameter that was added.
+	 * @throws ParseException
+	 */
+	public Parameter addParameter( Name n, TypeRef rt ) throws ParseException
+	{
+//		if (rt.type().kind == EtchGrammarConstants.VOID)
+//			throw new IllegalArgumentException( "bad parameter type "+rt+" for name "+n );
+		
+		list.check( n );
+		Parameter p = new Parameter( this, n, rt );
+		list.add( n, p );
+		return p;
+	}
+	
+	/**
+	 * @param n
+	 * @return true if the specified parameter name is defined by this element.
+	 */
+	public boolean hasParameter( String n )
+	{
+		return list.has( n );
+	}
+
+	/**
+	 * @param n the parameter name to get.
+	 * @return the parameter with the specified name, or null.
+	 */
+	public Parameter getParameter( String n )
+	{
+		return list.get( n );
+	}
+	
+	/**
+	 * @return a list containing the parameters in order.
+	 */
+	public List<Parameter> getParameters()
+	{
+		return list.list();
+	}
+	
+	private NameList<Parameter> list = new NameList<Parameter>();
+
+	public Iterator<Parameter> iterator()
+	{
+		return list.iterator();
+	}
+	
+	/**
+	 * @return true if this element defines any parameters.
+	 */
+	public boolean hasParameters()
+	{
+		return !list.isEmpty();
+	}
+
+	/**
+	 * @return the service that we are part of.
+	 */
+	abstract public Service service();
+
+	/**
+	 * @param isExcept
+	 * @param hasExtends
+	 * @return a list of format items for this element.
+	 */
+	public List<FmtItem> mkFormatList( boolean isExcept, boolean hasExtends )
+	{
+		List<FmtItem> fmts = new ArrayList<FmtItem>();
+		
+		if (!isExcept)
+			fmts.add( new StringItem( name().name+"(" ) );
+
+		if (hasExtends)
+		{
+			fmts.add( new FieldItem( isExcept ? "super.getMessage()" : "super.toString()" ) );
+			fmts.add( new StringItem( "; " ) );
+		}
+		
+		boolean first = true;
+		for (Parameter p: list)
+		{
+			if (first)
+			{
+				first = false;
+				fmts.add( new StringItem( p.name().name+"=" ) );
+			}
+			else
+			{
+				fmts.add( new StringItem( "; "+p.name().name+"=" ) );
+			}
+			fmts.add( new FieldItem( p.name().name ) );
+		}
+		
+		if (!isExcept)
+			fmts.add( new StringItem( ")" ) );
+
+		return fmts;
+	}
+
+	/**
+	 * Checks the format items for this element.
+	 * @param lineno
+	 * @param fmts
+	 * @throws ParseException
+	 */
+	public void checkFormatList( int lineno, List<FmtItem> fmts )
+		throws ParseException
+	{
+		for (FmtItem i: fmts)
+		{
+			if (i instanceof FieldItem)
+			{
+				FieldItem fi = (FieldItem) i;
+				if (!hasParameter( fi.value() ))
+					throw new ParseException( String.format(
+						"ToString: format list specifies parameter (%s) which does not exist at line %d",
+						fi.value(), lineno ) );
+			}
+		}
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Parameter.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Parameter.java
new file mode 100644
index 0000000..08142ab
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Parameter.java
@@ -0,0 +1,105 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.ParseException;
+
+
+/**
+ * A parameter declaration from the etch idl. A parameter can be
+ * a field of a struct or exception, or a parameter of a message.
+ */
+public class Parameter extends Named<ParamList<?>>
+{
+	/**
+	 * Constructs the Parameter.
+	 *
+	 * @param pl
+	 * @param rt
+	 * @param name
+	 */
+	public Parameter( ParamList<?> pl, Name name, TypeRef rt )
+	{
+		super( pl, name, null );
+		type = rt;
+		vname = name.name;
+	}
+	
+	private final TypeRef type;
+	
+	private final String vname;
+	
+	/**
+	 * @return the type of this parameter.
+	 */
+	public TypeRef type()
+	{
+		return type;
+	}
+	
+	@Override
+	public String vname( Backend helper )
+	{
+		return helper.mfvname( vname );
+	}
+
+	@Override
+	public String fqname()
+	{
+		return name().name;
+	}
+	
+	@Override
+	public String toString()
+	{
+		return type+" "+name().name;
+	}
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%sparam %s %s\n", indent, type, name().name );
+		
+		String sIndent = indent+"  ";
+		
+		for (String s: descr())
+			System.out.printf( "%sdescr %s\n", sIndent, s );
+	}
+
+	@Override
+	public void check() throws ParseException
+	{
+		checkParamName( name() );
+		
+		type.check( parent().service() );
+	}
+
+	@Override
+	public void treewalk( TreeWalker walker ) throws ParseException
+	{
+		walker.preParameter( this );
+		
+		type.treewalk( walker );
+		
+		walker.postParameter( this );
+	}
+}
\ No newline at end of file
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/ReservedWordChecker.java b/compiler/src/main/java/org/apache/etch/compiler/ast/ReservedWordChecker.java
new file mode 100644
index 0000000..2bc6176
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/ReservedWordChecker.java
@@ -0,0 +1,166 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.apache.etch.compiler.LogHandler;
+import org.apache.etch.compiler.Token;
+
+
+/**
+ * Checks the abstract syntax tree for uses of reserved words.
+ */
+public class ReservedWordChecker extends AbstractTreeWalker
+{
+	/**
+	 * Constructs the reserved word checker with the word list.
+	 * @param words the reserved word list including translations.
+	 * @param rewrite flag which indicates we should attempt to rewrite
+	 * the word.
+	 * @param lh 
+	 */
+	public ReservedWordChecker( Map<String, String> words, boolean rewrite, LogHandler lh )
+	{
+		if (rewrite)
+			throw new IllegalArgumentException( "rewrite not supported yet" );
+		
+		this.words = words;
+		this.rewrite = rewrite;
+		this.lh = lh;
+	}
+	
+	private final Map<String, String> words;
+	
+	private final boolean rewrite;
+	
+	private LogHandler lh;
+
+	/**
+	 * @return true if the tree walk was ok, false if there
+	 * were collisions which were not edited away.
+	 */
+	public boolean ok()
+	{
+		return ok;
+	}
+	
+	private boolean ok = true;
+	
+	@Override
+	public void preModule( Module module )
+	{
+		Name name = module.name();
+		StringTokenizer st = new StringTokenizer( name.name, "." );
+		while (st.hasMoreTokens())
+		{
+			String s = st.nextToken();
+			if (words.containsKey( s ))
+			{
+				whine( "module name component", name.token );
+				break;
+			}
+		}
+	}
+	
+	@Override
+	public void preService( Service service )
+	{
+		Name name = service.name();
+		if (words.containsKey( name.name ))
+			whine( "service name", name.token );
+	}
+	
+	@Override
+	public void preConstant( Constant constant )
+	{
+		Name name = constant.name();
+		if (words.containsKey( name.name ))
+			whine( "constant name", name.token );
+	}
+	
+	@Override
+	public void preEnum( Enumx enumx )
+	{
+		Name name = enumx.name();
+		if (words.containsKey( name.name ))
+			whine( "enum name", name.token );
+	}
+	
+	@Override
+	public void doItem( Item item )
+	{
+		Name name = item.name();
+		if (words.containsKey( name.name ))
+			whine( "enum item name", name.token );
+	}
+	
+	@Override
+	public void preStruct( Struct struct )
+	{
+		Name name = struct.name();
+		if (words.containsKey( name.name ))
+			whine( "struct name", name.token );
+	}
+	
+	@Override
+	public void doExtern( Extern extern )
+	{
+		Name name = extern.name();
+		if (words.containsKey( name.name ))
+			whine( "extern name", name.token );
+	}
+	
+	@Override
+	public void preExcept( Except except )
+	{
+		Name name = except.name();
+		if (words.containsKey( name.name ))
+			whine( "exception name", name.token );
+	}
+	
+	@Override
+	public void preMessage( Message message )
+	{
+		Name name = message.name();
+		if (words.containsKey( name.name ))
+			whine( "message name", name.token );
+	}
+	
+	@Override
+	public void preParameter( Parameter parameter )
+	{
+		Name name = parameter.name();
+		if (words.containsKey( name.name ))
+			whine( "parameter name", name.token );
+	}
+
+	private void whine( String what, Token token )
+	{
+		String msg = String.format( "Etch: %s '%s' is a reserved word at line %d\n", what, token.image, token.beginLine);
+		if (rewrite)
+			lh.report( LogHandler.LEVEL_WARNING, token.beginLine, msg );
+		else
+			lh.report( LogHandler.LEVEL_ERROR, token.beginLine, msg );
+		ok = rewrite;
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Service.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Service.java
new file mode 100644
index 0000000..9918d45
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Service.java
@@ -0,0 +1,566 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.EtchCompiler;
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.Token;
+
+
+
+/**
+ * Declaration of a service from the etch idl.
+ */
+public class Service extends Named<Module> implements OptList, Iterable<Named<?>>
+{
+	/**
+	 * Constructs the service.
+	 *
+	 * @param module
+	 * @param name
+	 * @param opts
+	 */
+	public Service( Module module, Name name, Map<String, Opt> opts )
+	{
+		super( module, name, opts );
+	}
+	
+	@Override
+	public String vname( Backend helper )
+	{
+		return null;
+	}
+	
+	@Override
+	public String fqname()
+	{
+		return parent().fqname() + '.' + name().name;
+	}
+	
+//	@Override
+//	public Integer id()
+//	{
+//		return null;
+//	}
+
+	/**
+	 * Adds a mixin declaration.
+	 * 
+	 * @param n
+	 * @param nOpts
+	 * @return the added mixin.
+	 * @throws ParseException
+	 */
+	public Mixin addMixin( Name n, Map<String, Opt> nOpts )
+		throws ParseException
+	{
+		optsCheck( Mixin.class, nOpts );
+		
+		try
+		{
+			Module module = EtchCompiler.parseModule( this, n, nOpts );
+			if (module == null)
+				throw new ParseException( String.format(
+					"could not find mixin '%s' at line %d",
+					n.name, n.token.beginLine ) );
+			
+			Mixin mixin = new Mixin( this, n, nOpts, module );
+			nameList.add( n, mixin );
+			return mixin;
+		}
+		catch ( ParseException e )
+		{
+			throw e;
+		}
+		catch ( Exception e )
+		{
+			throw new ParseException( String.format(
+				"could not find mixin '%s' at line %d: %s",
+				n.name, n.token.beginLine, e ) );
+		}
+	}
+	
+	/**
+	 * Adds a constant declaration.
+	 * @param n
+	 * @param nOpts
+	 * @param tr
+	 * @param value
+	 * @return the added constant.
+	 * @throws ParseException
+	 */
+	public Constant addConstant( Name n, Map<String, Opt> nOpts, TypeRef tr, Token value ) throws ParseException
+	{
+		nameList.check( n );
+		optsCheck( Constant.class, nOpts );
+		Constant c = new Constant( this, n, nOpts, tr, value );
+		nameList.add( n, c );
+		return c;
+	}
+
+	private void optsCheck( Class<?> type, Map<String, Opt> nOpts ) throws ParseException
+	{
+		for (Opt opt: nOpts.values())
+			optCheck( type, opt );
+	}
+
+	private void optCheck( Class<?> type, Opt opt ) throws ParseException
+	{
+		opt.check( type );
+	}
+
+	/**
+	 * Adds an enumeration declaration.
+	 * @param n
+	 * @param nOpts
+	 * @return the added enumx.
+	 * @throws ParseException
+	 */
+	public Enumx addEnum( Name n, Map<String, Opt> nOpts ) throws ParseException
+	{
+		nameList.check( n );
+		optsCheck( Enumx.class, nOpts );
+		Enumx e = new Enumx( this, n, nOpts );
+		nameList.add( n, e );
+		return e;
+	}
+
+	/**
+	 * Adds a struct declaration.
+	 * @param n
+	 * @param nOpts
+	 * @return the added struct.
+	 * @throws ParseException
+	 */
+	public Struct addStruct( Name n, Map<String, Opt> nOpts ) throws ParseException
+	{
+		nameList.check( n );
+		optsCheck( Struct.class, nOpts );
+		Struct s = new Struct( this, n, nOpts );
+		nameList.add( n, s );
+		return s;
+	}
+
+	/**
+	 * Adds an extern declaration.
+	 * @param n
+	 * @param nOpts
+	 * @return the added extern.
+	 * @throws ParseException
+	 */
+	public Extern addExtern( Name n, Map<String, Opt> nOpts ) throws ParseException
+	{
+		nameList.check( n );
+		optsCheck( Extern.class, nOpts );
+		Extern s = new Extern( this, n, nOpts );
+		nameList.add( n, s );
+		return s;
+	}
+
+	/**
+	 * Adds a built-in declaration.
+	 * @param n
+	 * @param bindingName
+	 * @param allowSubclass
+	 * @return the Builtin that was added.
+	 * @throws ParseException
+	 */
+	public Builtin addBuiltin( Name n, String bindingName, boolean allowSubclass )
+		throws ParseException
+	{
+		nameList.check( n );
+		Builtin b = new Builtin( this, n, bindingName, allowSubclass );
+		nameList.add( n, b );
+		return b;
+	}
+
+	/**
+	 * Adds an exception declaration.
+	 * @param n
+	 * @param nOpts
+	 * @return the added exception.
+	 * @throws ParseException
+	 */
+	public Except addExcept( Name n, Map<String, Opt> nOpts ) throws ParseException
+	{
+		nameList.check( n );
+		optsCheck( Except.class, nOpts );
+		Except e = new Except( this, n, nOpts );
+		nameList.add( n, e );
+		return e;
+	}
+
+	/**
+	 * Adds a message declaration.
+	 * @param n
+	 * @param rt
+	 * @param nOpts
+	 * @return the added message.
+	 * @throws ParseException
+	 */
+	public Message addMessage( Name n, Map<String, Opt> nOpts, TypeRef rt ) throws ParseException
+	{
+		nameList.check( n );
+		optsCheck( Message.class, nOpts );
+		Message m = new Message( this, n, nOpts, rt );
+		nameList.add( n, m );
+		
+		if (!m.isOneway())
+			addResultMessage( m );
+		else if (m.hasReturn())
+			throw new ParseException( String.format(
+				"Oneway message cannot have a non-void return type at line %d", n.token.beginLine ) );
+		
+		return m;
+	}
+	
+	/**
+	 * @param reqMsg
+	 * @throws ParseException
+	 */
+	public void addResultMessage( Message reqMsg ) throws ParseException
+	{
+		if (reqMsg.getResultMessage() != null)
+			return;
+		
+		Name rmName = reqMsg.getResultMessageName();
+
+		Token rmType = new Token();
+		rmType.kind = EtchGrammarConstants.VOID;
+		rmType.image = "void";
+		TypeRef rmTypeRef = new TypeRef( this, rmType );
+		
+		nameList.check( rmName );
+		Message rm = new Message( this, rmName, new HashMap<String, Opt>(),
+			rmTypeRef );
+		rm.setMsgDir( getResultMessageDirection( reqMsg.msgDir() ) );
+		nameList.add( rmName, rm );
+		
+		rm.addParameter( reqMsg.getResultParamName(), reqMsg.type() );
+		
+		reqMsg.setResultMessage( rm );
+		rm.setRequestMessage( reqMsg );
+	}
+
+	/**
+	 * @param md
+	 * @return message direction opposite to the supplied message direction.
+	 */
+	public MessageDirection getResultMessageDirection( MessageDirection md )
+	{
+		switch (md)
+		{
+			case CLIENT: return MessageDirection.SERVER;
+			case SERVER: return MessageDirection.CLIENT;
+			case BOTH: return MessageDirection.BOTH;
+			default: throw new IllegalArgumentException( "unknown message direction "+md );
+		}
+	}
+
+	public Iterator<Named<?>> iterator()
+	{
+		return nameList.iterator();
+	}
+	
+	/**
+	 * @param recursive if true, recurse into mixed in services, too.
+	 * @return an iterator over all the methods of this service.
+	 */
+	public Iterator<Named<?>> messages( boolean recursive )
+	{
+		List<Named<?>> list = new ArrayList<Named<?>>();
+		getMessages( list, recursive );
+		return list.iterator();
+	}
+	
+	private void getMessages( List<Named<?>> list, boolean recursive )
+	{
+		for (Named<?> n: nameList)
+		{
+			if (n.isMessage())
+				list.add( n );
+			else if (recursive && n.isMixin())
+				((Mixin) n).getModule().iterator().next().getMessages( list, recursive );
+		}
+	}
+
+	/**
+	 * @param recursive if true, recurse into mixed in services, too
+	 * @return an iterator over all the structs of this service
+	 */
+	public Iterator<Named<?>> structs( boolean recursive )
+	{
+		List<Named<?>> list = new ArrayList<Named<?>>();
+		getStructs( list, recursive );
+		return list.iterator();
+	}
+	
+	private void getStructs( List<Named<?>> list, boolean recursive )
+	{
+		for ( Named<?> n: nameList )
+		{
+			if ( n.isStruct() )
+				list.add(n);
+			else if ( recursive && n.isMixin() )
+				((Mixin)n).getModule().iterator().next().getStructs( list, recursive );
+		}
+	}
+	
+	/**
+	 * @param recursive if true, recurse into mixed in services, too
+	 * @return an iterator over all the enums of this service
+	 */
+	public Iterator<Named<?>> enums( boolean recursive )
+	{
+		List<Named<?>> list = new ArrayList<Named<?>>();
+		getEnums( list, recursive );
+		return list.iterator();
+	}
+	
+	private void getEnums( List<Named<?>> list, boolean recursive )
+	{
+		for ( Named<?> n: nameList )
+		{
+			if ( n.isEnumx() )
+				list.add(n);
+			else if ( recursive && n.isMixin() )
+				((Mixin)n).getModule().iterator().next().getEnums( list, recursive );
+		}
+	}
+	
+	/**
+	 * @param recursive if true, recurse into mixed in services, too
+	 * @return an iterator over all the externs of this service
+	 */
+	public Iterator<Named<?>> externs( boolean recursive )
+	{
+		List<Named<?>> list = new ArrayList<Named<?>>();
+		getExterns( list, recursive );
+		return list.iterator();
+	}
+	
+	private void getExterns( List<Named<?>> list, boolean recursive )
+	{
+		for ( Named<?> n: nameList )
+		{
+			if ( n.isExtern() )
+				list.add(n);
+			else if ( recursive && n.isMixin() )
+				((Mixin)n).getModule().iterator().next().getExterns( list, recursive );
+		}
+	}
+	
+	/**
+	 * @param recursive if true, recurse into mixed in services, too
+	 * @return an iterator over all the constants of this service
+	 */
+	public Iterator<Named<?>> constants( boolean recursive )
+	{
+		List<Named<?>> list = new ArrayList<Named<?>>();
+		getConstants( list, recursive );
+		return list.iterator();
+	}
+	
+	private void getConstants( List<Named<?>> list, boolean recursive )
+	{
+		for ( Named<?> n: nameList )
+		{
+			if ( n.isConstant() )
+				list.add(n);
+			else if ( recursive && n.isMixin() )
+				((Mixin)n).getModule().iterator().next().getConstants( list, recursive );
+		}
+	}
+	
+	/**
+	 * @param recursive if true, recurse into mixed in services, too
+	 * @return an iterator over all the exceptions of this service
+	 */
+	public Iterator<Named<?>> exceptions( boolean recursive )
+	{
+		List<Named<?>> list = new ArrayList<Named<?>>();
+		getExceptions( list, recursive );
+		return list.iterator();
+	}
+	
+	private void getExceptions( List<Named<?>> list, boolean recursive )
+	{
+		for ( Named<?> n: nameList )
+		{
+			if ( n.isExcept() )
+				list.add(n);
+			else if ( recursive && n.isMixin() )
+				((Mixin)n).getModule().iterator().next().getExceptions( list, recursive );
+		}
+	}
+	
+	private final NameList<Named<?>> nameList = new NameList<Named<?>>();
+
+	/**
+	 * @param mc
+	 * @return true if some of that type exists.
+	 */
+	public boolean hasMessageDirection( MessageDirection mc )
+	{
+		for (Named<?> n: this)
+		{
+			//System.out.printf( "hasMessageDirection (%s): %s\n", mc, n );
+			
+			if (!(n instanceof Message))
+			{
+				if (mc == MessageDirection.BOTH)
+					return true;
+				
+				continue;
+			}
+			
+			Message m = (Message) n;
+			if (m.msgDir() == mc && !m.isHidden())
+				return true;
+		}
+		return false;
+	}
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%sservice %s\n", indent, name() );
+		
+		String sIndent = indent+"  ";
+		
+		for (String s: descr())
+			System.out.printf( "%sdescr %s\n", sIndent, s );
+		
+		for (Opt o: opts())
+			o.dump( sIndent );
+		
+		for (Named<?> m: this)
+			m.dump( sIndent );
+	}
+
+	@Override
+	public void check() throws ParseException
+	{
+		checkTypeName( name() );
+		
+		for (Named<?> n: this)
+			n.check();
+	}
+
+	/**
+	 * Gets the named thing from the service.
+	 * @param name
+	 * @return the named thing, or null.
+	 */
+	public Named<?> get( String name )
+	{
+		List<Named<?>> list = new ArrayList<Named<?>>();
+	
+		Named<?> named = nameList.get( name );
+		if (named != null)
+		{
+			/*System.out.println( "resolved to "+named );
+			return named;*/
+			list.add(named);
+		}
+		
+		if (isQualifiedName( name ))
+		{
+			String x = getSimpleName( name );
+			// System.out.println( "trying "+x );
+			named = nameList.get( x );
+			if (named != null)
+			{
+				String y = named.fqname();
+				if (name.equals( y ))
+				{
+					list.add(named);
+				}
+			}
+		}
+
+
+		for (Named<?> n : this)
+		{
+			if (n.isMixin())
+			{
+
+				named = ((Mixin) n).getModule().iterator().next().get( name );
+				
+				if (named != null)
+				//	return named;
+				{
+					boolean exists = false;
+					Iterator<Named<?>> it = list.iterator();
+					while ( it.hasNext())
+					{
+						if ( ((Named<?>)it.next()).fqname().equals( named.fqname() ) )
+						{
+							exists = true;
+						}
+					}
+					
+					if ( !exists )
+						list.add(named);
+				}
+
+			}
+		}
+
+		if (list.size() == 1 )
+			return list.get( 0 );
+
+
+		return null;
+	}
+
+	private boolean isQualifiedName( String name )
+	{
+		return name.lastIndexOf( '.' ) >= 0;
+	}
+
+	private String getSimpleName( String name )
+	{
+		return name.substring( name.lastIndexOf( '.' )+1 );
+	}
+
+	/**
+	 * @param walker called with each and every node under this one.
+	 */
+	@Override
+	public void treewalk( TreeWalker walker ) throws ParseException
+	{
+		walker.preService( this );
+		
+		for (Named<?> n: this)
+			n.treewalk( walker );
+		
+		walker.postService( this );
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Struct.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Struct.java
new file mode 100644
index 0000000..94e5d89
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Struct.java
@@ -0,0 +1,232 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.ParseException;
+
+
+/**
+ * A struct declaration from the etch idl.
+ */
+public class Struct extends ParamList<Service>
+{
+	/**
+	 * Constructs the Struct.
+	 *
+	 * @param intf
+	 * @param name
+	 * @param opts
+	 */
+	public Struct( Service intf, Name name, Map<String, Opt> opts )
+	{
+		super( intf, name, opts );
+		
+		moduleName = intf.parent().name().name;
+		serviceName = intf.name().name;
+		structName = name.name;
+
+		fqname = moduleName+'.'+serviceName+'.'+structName;
+		vname = fqname.replace( '.', '_' );
+	}
+	
+	private final String moduleName;
+	
+	private final String serviceName;
+	
+	private final String structName;
+	
+	private final String vname;
+	
+	private final String fqname;
+
+	@Override
+	public String vname( Backend helper )
+	{
+		return helper.mtvname( vname );
+	}
+
+	@Override
+	public String fqname()
+	{
+		return fqname;
+	}
+	
+	@Override
+	public String efqname( Backend helper )
+	{
+		return helper.enum_efqname( fqname, moduleName, serviceName, structName );
+	}
+
+	@Override
+	public String toString()
+	{
+		return String.format( "struct %s (%s)", name(), getParameters() );
+	}
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%sstruct %s\n", indent, name() );
+		
+		String sIndent = indent+"  ";
+		
+		for (String s: descr())
+			System.out.printf( "%sdescr %s\n", sIndent, s );
+		
+		for (Parameter p: this)
+			p.dump( sIndent );
+	}
+
+	@Override
+	public void check() throws ParseException
+	{
+		checkTypeName( name() );
+		
+		for (Parameter p: this)
+			p.check();
+		
+		if (hasExtends())
+		{
+			Named<?> n = parent().get( xtnds.name );
+			
+			if (n == null)
+				throw new ParseException( String.format(
+					"struct %s extends %s not defined at line %d",
+					name(), xtnds.name(), xtnds.token.beginLine ) );
+			
+			if (!(n instanceof Struct))
+				throw new ParseException( String.format(
+					"struct %s extends %s not a struct at line %d",
+					name(), xtnds.name(), xtnds.token.beginLine ) );
+			
+			Struct s = this;
+			while (s != null && s.hasExtends())
+			{
+				s = s.getExtends();
+				if (s == this)
+					throw new ParseException( String.format(
+						"struct %s extends %s creates loop at line %d",
+						name(), xtnds.name(), xtnds.token.beginLine ) );
+			}
+			
+			s = getExtends();
+			for (Parameter p: this)
+			{
+				Parameter x = s.getParameter( p.name().name );
+				if (x != null)
+					throw new ParseException( String.format(
+						"struct %s extends %s hides parameter %s from %s at line %d",
+						name(), xtnds.name(), x.name(), x.parent().name(),
+						xtnds.token.beginLine ) );
+			}
+		}
+	}
+	
+	@Override
+	public Parameter getParameter( String n )
+	{
+		Parameter p = super.getParameter( n );
+		if (p == null && hasExtends())
+			p = getExtends().getParameter( n );
+		return p;
+	}
+	
+	/**
+	 * @return the list of all parameters including those from superclasses.
+	 * They are returned in declaration order, starting with those from the
+	 * base class.
+	 */
+	public List<Parameter> getAllParameters()
+	{
+		if (hasExtends())
+		{
+			List<Parameter> list = new ArrayList<Parameter>();
+			list.addAll( getExtends().getAllParameters() );
+			list.addAll( getParameters() );
+			return list;
+		}
+		return getParameters();
+	}
+	
+	/**
+	 * @return true if this struct or any extended struct has a parameter.
+	 */
+	public boolean hasAnyParameters()
+	{
+		return hasParameters() ||
+			hasExtends() && getExtends().hasAnyParameters();
+	}
+
+	@Override
+	public Service service()
+	{
+		return parent();
+	}
+
+	@Override
+	public void treewalk( TreeWalker walker ) throws ParseException
+	{
+		walker.preStruct( this );
+		
+		for (Parameter p: this)
+			p.treewalk( walker );
+		
+		if (hasExtends())
+			getExtends().treewalk( walker );
+		
+		walker.postStruct( this );
+	}
+	
+	/**
+	 * @return true if this struct extends another.
+	 */
+	public boolean hasExtends()
+	{
+		return xtnds != null;
+	}
+	
+	/**
+	 * @return the struct that this one extends or null.
+	 */
+	public Struct getExtends()
+	{
+		if (xtnds == null)
+			return null;
+		
+		return (Struct) parent().get( xtnds.name );
+	}
+
+	/**
+	 * Sets the extends attribute of this exception.
+	 * @param xtnds
+	 */
+	public void setExtends( Name xtnds )
+	{
+		this.xtnds = xtnds;
+	}
+	
+	private Name xtnds;
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/Thrown.java b/compiler/src/main/java/org/apache/etch/compiler/ast/Thrown.java
new file mode 100644
index 0000000..6c88bb6
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/Thrown.java
@@ -0,0 +1,108 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import org.apache.etch.compiler.Backend;
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.ParseException;
+
+
+/**
+ * A thrown exception reference from the etch idl.
+ */
+public class Thrown extends Named<Message>
+{
+	/**
+	 * Constructs the Thrown.
+	 *
+	 * @param mthd
+	 * @param name
+	 */
+	public Thrown( Message mthd, Name name )
+	{
+		super( mthd, name, null );
+	}
+
+	@Override
+	public String vname( Backend helper )
+	{
+		return null;
+	}
+
+	@Override
+	public String fqname()
+	{
+		return null;
+	}
+
+	/**
+	 * @return the named exception.
+	 */
+	public Named<?> getNamed()
+	{
+		if (name().token.kind != EtchGrammarConstants.ID && name().token.kind != EtchGrammarConstants.QID)
+			return null;
+		
+		return parent().service().get( name().token.image );
+	}
+	
+//	@Override
+//	public Integer id()
+//	{
+//		return null;
+//	}
+
+	@Override
+	public String toString()
+	{
+		return name().name;
+	}
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%sthrows %s\n", indent, name() );
+		
+		String sIndent = indent+"  ";
+		
+		for (String s: descr())
+			System.out.printf( "%sdescr %s\n", sIndent, s );
+	}
+
+	@Override
+	public void check() throws ParseException
+	{
+		Named<?> n = getNamed();
+		
+		if (n == null)
+			throw new ParseException( String.format(
+				"undefined exception %s at line %d", name().token.image, name().token.beginLine ) );
+
+		if (!(n instanceof Except))
+			throw new ParseException( String.format(
+				"%s not an exception at line %d", name().token.image, name().token.beginLine ) );
+	}
+
+	@Override
+	public void treewalk( TreeWalker walker ) throws ParseException
+	{
+		walker.doThrown( this );
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/TreeWalker.java b/compiler/src/main/java/org/apache/etch/compiler/ast/TreeWalker.java
new file mode 100644
index 0000000..09aff3a
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/TreeWalker.java
@@ -0,0 +1,153 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+/**
+ * Interfaces used by the tree walker to report what it finds.
+ */
+public interface TreeWalker
+{
+	/**
+	 * Reports a module, before we visit the children of the module.
+	 * @param module
+	 */
+	public void preModule( Module module );
+	
+	/**
+	 * Reports a module, after we visit the children of the module.
+	 * @param module
+	 */
+	public void postModule( Module module );
+
+	/**
+	 * Reports a service, before we visit the children of the service.
+	 * @param service
+	 */
+	public void preService( Service service );
+	
+	/**
+	 * Reports a service, after we visit the children of the service.
+	 * @param service
+	 */
+	public void postService( Service service );
+	
+	/**
+	 * Reports a mixin.
+	 * @param mixin
+	 */
+	public void doMixin( Mixin mixin );
+	
+	/**
+	 * Reports a constant, before we visit the children of the constant.
+	 * @param constant
+	 */
+	public void preConstant( Constant constant );
+	
+	/**
+	 * Reports a constant, after we visit the children of the constant.
+	 * @param constant
+	 */
+	public void postConstant( Constant constant );
+	
+	/**
+	 * Reports an enum, before we visit the children of the enum.
+	 * @param enumx
+	 */
+	public void preEnum( Enumx enumx );
+	
+	/**
+	 * Reports an enum, after we visit the children of the enum.
+	 * @param enumx
+	 */
+	public void postEnum( Enumx enumx );
+	
+	/**
+	 * Reports an item of an enum.
+	 * @param item
+	 */
+	public void doItem( Item item );
+	
+	/**
+	 * Reports a struct, before we visit the children of the struct.
+	 * @param struct
+	 */
+	public void preStruct( Struct struct );
+	
+	/**
+	 * Reports a struct, after we visit the children of the struct.
+	 * @param struct
+	 */
+	public void postStruct( Struct struct );
+	
+	/**
+	 * Reports an extern.
+	 * @param extern
+	 */
+	public void doExtern( Extern extern );
+	
+	/**
+	 * Reports an except, before we visit the children of the except.
+	 * @param except
+	 */
+	public void preExcept( Except except );
+	
+	/**
+	 * Reports an except, after we visit the children of the except.
+	 * @param except
+	 */
+	public void postExcept( Except except );
+	
+	/**
+	 * Reports a message, before we visit the children of the message.
+	 * @param message
+	 */
+	public void preMessage( Message message );
+	
+	/**
+	 * Reports a message, after we visit the children of the message.
+	 * @param message
+	 */
+	public void postMessage( Message message );
+	
+	/**
+	 * Reports a parameter, before we visit the children of the parameter.
+	 * @param parameter
+	 */
+	public void preParameter( Parameter parameter );
+	
+	/**
+	 * Reports a parameter, after we visit the children of the parameter.
+	 * @param parameter
+	 */
+	public void postParameter( Parameter parameter );
+	
+	/**
+	 * Reports a thrown exception of a message.
+	 * @param thrown
+	 */
+	public void doThrown( Thrown thrown );
+	
+	/**
+	 * Reports a type reference.
+	 * @param ref
+	 */
+	public void doTypeRef( TypeRef ref );
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/ast/TypeRef.java b/compiler/src/main/java/org/apache/etch/compiler/ast/TypeRef.java
new file mode 100644
index 0000000..2bfdbed
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/ast/TypeRef.java
@@ -0,0 +1,238 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.ast;
+
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.Token;
+
+/**
+ * A type reference from the etch idl.
+ */
+public class TypeRef
+{
+	/**
+	 * Constructs the TypeRef.
+	 * @param intf 
+	 *
+	 * @param type
+	 */
+	public TypeRef( Service intf, Token type )
+	{
+		this.intf = intf;
+		this.type = type;
+	}
+	
+	private final Service intf;
+	
+	private final Token type;
+	
+	/**
+	 * @return the parent object of this reference.
+	 */
+	public Service intf()
+	{
+		return intf;
+	}
+	
+	/**
+	 * @return the token of the type.
+	 */
+	public Token type()
+	{
+		return type;
+	}
+
+	/**
+	 * Sets the number of dimensions of an array type.
+	 * @param d the number of dimensions of an array type.
+	 */
+	public void setDim( int d )
+	{
+		dim = d;
+	}
+	
+	private int dim;
+
+	@Override
+	public String toString()
+	{
+		StringBuffer sb = new StringBuffer( type.image );
+		for (int i = 0; i < dim; i++)
+			sb.append( "[]" );
+		return sb.toString();
+	}
+	
+	/**
+	 * @param i
+	 * @return the named type.
+	 */
+	public Named<?> getNamed( Service i )
+	{
+		if (isBuiltin())
+			return null;
+		
+		return i.get( type.image );
+	}
+
+	/**
+	 * Checks the referenced type to make sure it is defined.
+	 * @param i
+	 * @throws ParseException
+	 */
+	public void check( Service i ) throws ParseException
+	{
+		if (isBuiltin())
+			return;
+
+		Named<?> n = getNamed( i );
+		
+		if (n == null)
+			throw new ParseException( String.format(
+				"undefined or ambiguous type %s at line %d", type.image, type.beginLine ) );
+
+		if (n instanceof Enumx)
+			return;
+		
+		if (n instanceof Struct)
+			return;
+		
+		if (n instanceof Extern)
+			return;
+		
+		if (n instanceof Builtin)
+			return;
+		
+		throw new ParseException( String.format(
+			"%s not a type at line %d", type.image, type.beginLine ) );
+	}
+	
+	/**
+	 * Call the tree walker on our sub-elements.
+	 * @param walker
+	 */
+	public void treewalk( TreeWalker walker )
+	{
+		walker.doTypeRef( this );
+	}
+
+	/**
+	 * @return true if the referenced type is builtin (currently all builtins
+	 * use keywords to reference them).
+	 */
+	public boolean isBuiltin()
+	{
+		return type.kind != EtchGrammarConstants.ID
+			&& type.kind != EtchGrammarConstants.QID;
+	}
+
+	/**
+	 * @return the dimensionality of this type reference.
+	 */
+	public int dim()
+	{
+		return dim;
+	}
+
+	/**
+	 * @return true if this type reference is an array.
+	 */
+	public boolean isArray()
+	{
+		return dim > 0;
+	}
+	
+	/**
+	 * @return true if this type reference is a scalar boolean.
+	 */
+	public boolean isBoolean()
+	{
+		return type.kind == EtchGrammarConstants.BOOLEAN && !isArray();
+	}
+
+	/**
+	 * @return true if this type reference is a scalar integral type.
+	 */
+	public boolean isIntegral()
+	{
+		if (isArray())
+			return false;
+
+		if (type.kind == EtchGrammarConstants.BYTE)
+			return true;
+		
+		if (type.kind == EtchGrammarConstants.SHORT)
+			return true;
+		
+		if (type.kind == EtchGrammarConstants.INT)
+			return true;
+		
+		if (type.kind == EtchGrammarConstants.LONG)
+			return true;
+		
+		return false;
+	}
+
+	/**
+	 * @return true if this type reference is a scalar floating type.
+	 */
+	public boolean isFloating()
+	{
+		if (isArray())
+			return false;
+
+		if (type.kind == EtchGrammarConstants.FLOAT)
+			return true;
+		
+		if (type.kind == EtchGrammarConstants.DOUBLE)
+			return true;
+		
+		return false;
+	}
+
+	/**
+	 * @return true if this type reference is a scalar string type.
+	 */
+	public boolean isString()
+	{
+		if (isArray())
+			return false;
+
+		if (type.kind == EtchGrammarConstants.STRING)
+			return true;
+		
+		return false;
+	}
+	
+	/**
+	 * @return true if this type reference is a scalar object type.
+	 */
+	public boolean isObject()
+	{
+		if (isArray())
+			return false;
+
+		if (type.kind == EtchGrammarConstants.OBJECT)
+			return true;
+		
+		return false;
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/opt/AsyncReceiver.java b/compiler/src/main/java/org/apache/etch/compiler/opt/AsyncReceiver.java
new file mode 100644
index 0000000..96bcefa
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/opt/AsyncReceiver.java
@@ -0,0 +1,101 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.opt;
+
+import java.util.EnumSet;
+
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.Token;
+import org.apache.etch.compiler.ast.AsyncReceiverMode;
+import org.apache.etch.compiler.ast.Message;
+import org.apache.etch.compiler.ast.Name;
+import org.apache.etch.compiler.ast.Opt;
+import org.apache.etch.compiler.ast.Service;
+
+
+/**
+ * Option which sets the async mode of the message receiver.
+ */
+public class AsyncReceiver extends Opt
+{
+	/**
+	 * Constructs the AsyncReceiver.
+	 *
+	 * @param name
+	 * @param args
+	 * @throws ParseException
+	 */
+	@SuppressWarnings("deprecation")
+	public AsyncReceiver( Name name, Token... args ) throws ParseException
+	{
+		super( name.name, name.token.beginLine );
+		addType( Message.class );
+		addType( Service.class );
+		
+		if (args.length != 1)
+			throw new ParseException( String.format( "AsyncReceiver args length != 1" ) );
+		
+		Token arg = args[0];
+		if (arg.kind != EtchGrammarConstants.ID)
+			throw new ParseException( String.format( "AsyncReceiver arg should be identifier: "+arg.image ) );
+		
+		try
+		{
+			AsyncReceiverMode m = AsyncReceiverMode.valueOf( arg.image.toUpperCase() );
+			if (m == AsyncReceiverMode.POOL)
+			{
+				System.out.printf(
+					"WARNING: deprecated AsyncReceiver mode POOL should be changed to QUEUED at line %d\n",
+					arg.beginLine );
+				m = AsyncReceiverMode.QUEUED;
+			}
+			mode = m;
+		}
+		catch ( IllegalArgumentException e )
+		{
+			throw new ParseException( String.format(
+				"AsyncReceiver arg should be one of: "+EnumSet.allOf( AsyncReceiverMode.class ) ) );
+		}
+	}
+	
+	private final AsyncReceiverMode mode;
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%s@AsyncReceiver( %s )\n", indent, mode );
+	}
+
+	@Override
+	public String toString()
+	{
+		return String.format( "@AsyncReceiver( %s )", mode );
+	}
+
+	/**
+	 * @return the async receiver mode.
+	 */
+	public AsyncReceiverMode getMode()
+	{
+		return mode;
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/opt/Authorize.java b/compiler/src/main/java/org/apache/etch/compiler/opt/Authorize.java
new file mode 100644
index 0000000..b587899
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/opt/Authorize.java
@@ -0,0 +1,780 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.opt;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.Token;
+import org.apache.etch.compiler.ast.Constant;
+import org.apache.etch.compiler.ast.Enumx;
+import org.apache.etch.compiler.ast.Item;
+import org.apache.etch.compiler.ast.Message;
+import org.apache.etch.compiler.ast.Name;
+import org.apache.etch.compiler.ast.Named;
+import org.apache.etch.compiler.ast.Opt;
+import org.apache.etch.compiler.ast.Parameter;
+import org.apache.etch.compiler.ast.Service;
+import org.apache.etch.compiler.ast.Struct;
+import org.apache.etch.compiler.ast.TypeRef;
+import org.apache.etch.util.StringUtil;
+
+
+/**
+ * Option which sets the authorization method for a message.
+ */
+public class Authorize extends Opt
+{
+	/**
+	 * Constructs the Authorize.
+	 *
+	 * @param name
+	 * @param args
+	 * @throws ParseException
+	 */
+	public Authorize( Name name, Token... args ) throws ParseException
+	{
+		super( name.name, name.token.beginLine );
+		addType( Message.class );
+		addType( Service.class );
+		
+		if (args == null || args.length == 0)
+		{
+			method = new Token();
+			method.kind = EtchGrammarConstants.TRUE;
+			method.beginLine = name.token.beginLine;
+			argList = new ArrayList<AuthArg>();
+			return;
+		}
+		
+		method = args[0];
+		if (method.kind != EtchGrammarConstants.ID &&
+				method.kind != EtchGrammarConstants.TRUE &&
+				method.kind != EtchGrammarConstants.FALSE)
+		{
+			throw new ParseException( String.format(
+				"Authorize method should be identifier, true, or false (but not %s) at line %d",
+				method, method.beginLine ) );
+		}
+		
+		if ((method.kind == EtchGrammarConstants.TRUE ||
+				method.kind == EtchGrammarConstants.FALSE) && args.length > 1)
+		{
+			throw new ParseException( String.format(
+				"Authorize %d cannot have any args at line %d",
+				method, method.beginLine ) );
+		}
+
+		argList = argsToArgList( args );
+	}
+	
+	private final Token method;
+	
+	private final List<AuthArg> argList;
+	
+	/**
+	 * @return the authorization method.
+	 */
+	public Token method()
+	{
+		return method;
+	}
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%s@Authorize( %s, %s )\n", indent, method, argList );
+	}
+
+	@Override
+	public String toString()
+	{
+		return String.format( "@Authorize( %s, %s )", method, argList );
+	}
+
+	/**
+	 * @return args as a list.
+	 */
+	private List<AuthArg> argsToArgList( Token[] args )
+	{
+		List<AuthArg> list = new ArrayList<AuthArg>();
+		int n = args.length;
+		for (int i = 1; i < n; i++)
+			list.add( new AuthArg( args[i] ) );
+		return list;
+	}
+	
+	/**
+	 * @return the args for the authorization method.
+	 */
+	public List<AuthArg> args()
+	{
+		return argList;
+	}
+
+	/**
+	 * @return true if the message needs authorization.
+	 */
+	public boolean hasAuth()
+	{
+		return method != null && method.kind != EtchGrammarConstants.TRUE;
+	}
+
+	/**
+	 * Checks the method to be called by authorize to make sure it is
+	 * a service method and that the parameters are correct.
+	 * @param service our service definition
+	 * @param msg the message being protected by the auth
+	 * @throws ParseException
+	 */
+	public void check( Service service, Message msg ) throws ParseException
+	{
+		if (!hasAuth())
+			return;
+		
+		if (isMethodTrue() || isMethodFalse())
+			return;
+		
+		Named<?> named = service.get( method.image );
+		if (named == null)
+			throw new ParseException( String.format(
+				"Authorize method name %s is not defined at %d",
+					method.image, lineno() ) );
+		
+		if (!named.isMessage())
+			throw new ParseException( String.format(
+				"Authorize method name %s is not a method at %d",
+				method.image, lineno() ) );
+		
+		Message authMsg = (Message) named;
+		
+		if (authMsg.type().type().kind != EtchGrammarConstants.BOOLEAN)
+			throw new ParseException( String.format(
+				"Authorize method %s result type is not boolean at %d",
+				method.image, lineno() ) );
+		
+		List<Parameter> authParams = authMsg.getParameters();
+		if (authParams.size() != argList.size())
+			throw new ParseException( String.format(
+				"Authorize method %s parameter list size does not match the number of supplied arguments at %d",
+				method.image, lineno() ) );
+		
+		int n = argList.size();
+		for (int i = 0; i < n; i++)
+		{
+			Parameter param = authParams.get( i );
+			AuthArg aarg = argList.get( i );
+			aarg.setType( param.type() );
+			Token arg = aarg.value();
+			
+//			System.out.printf( "auth method %s param %s = %s\n",
+//				method, param.name(), arg );
+			
+			switch (arg.kind)
+			{
+				case EtchGrammarConstants.NULL:
+					// any parameter value may be specified as null...
+					break;
+				
+				case EtchGrammarConstants.ID:
+					// arg is referencing either a parameter of msg or a
+					// service constant.
+					checkMsgParamOrServiceConst( msg, param, arg, i );
+					break;
+				
+				case EtchGrammarConstants.QID:
+					// arg is referencing an enum item (enum.item) or
+					// could be trying to reference a field of a
+					// parameter of message (param(.field)+).
+					checkMsgParamFieldRefOrEnumItem( msg, param, arg, i );
+					break;
+				
+				case EtchGrammarConstants.TRUE:
+				case EtchGrammarConstants.FALSE:
+					// arg is a boolean constant the parameter better be
+					// boolean, too.
+					checkBooleanConstant( param, arg, i );
+					break;
+				
+				case EtchGrammarConstants.INTEGER:
+					// arg is an integer constant, the parameter better
+					// be an integral or floating type and arg better
+					// be the right size...
+					checkIntegerConstant( param, arg, i );
+					break;
+				
+				case EtchGrammarConstants.OCTAL:
+					// arg is an octal constant, the parameter better
+					// be an integral or floating type and arg better
+					// be the right size...
+					checkOctalConstant( param, arg, i );
+					break;
+				
+				case EtchGrammarConstants.HEX:
+					// arg is a hex constant, the parameter better
+					// be an integral or floating type and arg better
+					// be the right size...
+					checkHexConstant( param, arg, i );
+					break;
+				
+				case EtchGrammarConstants.BINARY:
+					// arg is a binary constant, the parameter better
+					// be an integral or floating type and arg better
+					// be the right size...
+					checkBinaryConstant( param, arg, i );
+					break;
+				
+				case EtchGrammarConstants.DECIMAL:
+					// arg is a decimal constant, the parameter better
+					// be a floating type and arg better be the right
+					// size...
+					checkDecimalConstant( param, arg, i );
+					break;
+				
+				case EtchGrammarConstants.STR:
+					// arg is a string constant the parameter better be
+					// string, too.
+					checkStringConstant( param, arg, i );
+					break;
+				
+				default:
+					throw new ParseException( String.format(
+						"Authorize method %s arg %d unsupported kind (%s) at line %d",
+						method.image, i+1, arg, lineno() ) );
+			}
+		}
+	}
+
+	/**
+	 * @return true if the method is false.
+	 */
+	public boolean isMethodFalse()
+    {
+//		System.out.println( "isMethodFalse() => "+(method.kind == EtchGrammarConstants.FALSE) );
+	    return method.kind == EtchGrammarConstants.FALSE;
+    }
+
+	/**
+	 * @return true if the method is true.
+	 */
+	public boolean isMethodTrue()
+    {
+	    return method.kind == EtchGrammarConstants.TRUE;
+    }
+
+	private void checkMsgParamOrServiceConst( Message msg, Parameter param,
+		Token arg, int argNo ) throws ParseException
+	{
+		Parameter p = msg.getParameter( arg.image );
+		if (p != null)
+		{
+			// it's a parameter, do the types match?
+			
+			Named<?> pt = p.type().getNamed( msg.parent() );
+			Named<?> paramType = param.type().getNamed( msg.parent() );
+			if (pt == paramType)
+				return;
+			
+			throw typeMismatch( param, arg, argNo );
+		}
+		
+		Named<?> named = msg.parent().get( arg.image );
+		
+		if (named != null)
+		{
+			// it's a named thing, it is a constant and do the
+			// types match?
+			
+			if (named.isConstant())
+			{
+				Constant c = (Constant) named;
+				
+				// it's a constant, do the types match?
+				
+				Named<?> ct = c.type().getNamed( msg.parent() );
+				Named<?> paramType = param.type().getNamed( msg.parent() );
+				if (ct == paramType)
+					return;
+				
+				throw typeMismatch( param, arg, argNo );
+			}
+			
+			// the named thing is not a constant, so blow chunks.
+			
+			throw new ParseException( String.format(
+				"Authorize method %s arg %d name not a parameter or constant (%s) at line %d",
+				method.image, argNo+1, arg, lineno() ) );
+		}
+		
+		// the named thing does not exist, so blow chunks.
+		
+		throw new ParseException( String.format(
+			"Authorize method %s arg %d name unknown (%s) at line %d",
+			method.image, argNo+1, arg, lineno() ) );
+	}
+
+	private void checkMsgParamFieldRefOrEnumItem( Message msg, Parameter param,
+		Token arg, int argNo ) throws ParseException
+	{
+		Service service = msg.parent();
+		
+		StringTokenizer path = new StringTokenizer( arg.image, "." );
+		String name = path.nextToken();
+		
+		Parameter p = msg.getParameter( name );
+		if (p != null)
+		{
+			// it's a parameter, so type of p must be a struct...
+
+			p = getField( service, p, path );
+			
+			if (p == null)
+				throw new ParseException( String.format(
+					"Authorize method %s arg %d name does not resolve to a field (%s) at line %d",
+					method.image, argNo+1, arg, lineno() ) );
+			
+			Named<?> pt = p.type().getNamed( service );
+			Named<?> paramType = param.type().getNamed( service );
+			if (pt == paramType)
+				return;
+
+			throw typeMismatch( param, arg, argNo );
+		}
+		
+		// it isn't a parameter, so it must be an enum...
+		
+		Named<?> named = service.get( name );
+		if (named == null)
+			throw new ParseException( String.format(
+				"Authorize method %s arg %d name unknown (%s) at line %d",
+				method.image, argNo+1, arg, lineno() ) );
+		
+		if (!named.isEnumx())
+			throw new ParseException( String.format(
+				"Authorize method %s arg %d name not a parameter field or enum (%s) at line %d",
+				method.image, argNo+1, arg, lineno() ) );
+		
+		Enumx e = (Enumx) named;
+		
+		Item i = e.getItem( path.nextToken() );
+		if (i == null)
+			throw new ParseException( String.format(
+				"Authorize method %s arg %d name not an enum item (%s) at line %d",
+				method.image, argNo+1, arg, lineno() ) );
+		
+		if (path.hasMoreTokens())
+			throw new ParseException( String.format(
+				"Authorize method %s arg %d name not an enum item (%s) at line %d",
+				method.image, argNo+1, arg, lineno() ) );
+	}
+
+	/**
+	 * @param service
+	 * @param p
+	 * @param path
+	 * @return the parameter that was resolved using the tokens from st.
+	 */
+	private Parameter getField( Service service, Parameter p, StringTokenizer path )
+	{
+		if (!path.hasMoreTokens())
+			return p;
+		
+		String name = path.nextToken();
+		
+		// get the type of p, it better be a struct.
+		
+		Named<?> named = p.type().getNamed( service );
+		if (named == null || !named.isStruct())
+			return null;
+		
+		Struct s = (Struct) named;
+		
+		p = s.getParameter( name );
+		if (p == null)
+			return null;
+		
+		return getField( service, p, path );
+	}
+
+	private void checkBooleanConstant( Parameter param, Token arg, int argNo )
+		throws ParseException
+	{
+		if (!param.type().isBoolean())
+			throw typeMismatch( param, arg, argNo );
+	}
+
+	private ParseException typeMismatch( Parameter param, Token arg, int argNo )
+	{
+		//if (true) throw new RuntimeException( "type mismatch" );
+		return new ParseException( String.format(
+			"Authorize method %s parameter %d (%s) type mismatch at line %d",
+			method, argNo+1, param.name(), arg.beginLine ) );
+	}
+
+	private void checkIntegerConstant( Parameter param, Token arg, int argNo )
+		throws ParseException
+	{
+		if (!(param.type().isIntegral() || param.type().isFloating()))
+			throw typeMismatch( param, arg, argNo );
+		
+		Long value = parseLong( arg.image, 10, "" );
+		if (value != null)
+		{
+			// check range of long vs. integral or floating param type
+			if (checkRange( value, param, arg, argNo ))
+				return;
+		}
+		
+		// value range is too much for long type, or parameter is not a
+		// known integral or floating type; try double
+		
+		Double dvalue = parseDouble( arg.image );
+		if (dvalue != null)
+		{
+			// check range of double vs. floating param type
+			if (checkRange( dvalue, param, arg, argNo ))
+				return;
+		}
+		
+		// value range is too much for long or double type, or parameter
+		// is not a known integral or floating type
+		
+		throw typeMismatch( param, arg, argNo );
+	}
+
+	private boolean checkRange( long value, Parameter param, Token arg,
+		int argNo ) throws ParseException
+	{
+		// we parsed the value as a long, now see if it is compatible with
+		// our parameter type.
+		switch (param.type().type().kind)
+		{
+			case EtchGrammarConstants.BYTE:
+				checkRange( value, Byte.MIN_VALUE, Byte.MAX_VALUE, param, arg,
+					argNo );
+				return true;
+			
+			case EtchGrammarConstants.SHORT:
+				checkRange( value, Short.MIN_VALUE, Short.MAX_VALUE, param, arg,
+					argNo );
+				return true;
+			
+			case EtchGrammarConstants.INT:
+				checkRange( value, Integer.MIN_VALUE, Integer.MAX_VALUE, param,
+					arg, argNo );
+				return true;
+			
+			case EtchGrammarConstants.LONG:
+			case EtchGrammarConstants.FLOAT:
+			case EtchGrammarConstants.DOUBLE:
+				// value is a long, and that is certainly compatible with long,
+				// float, or double.
+				return true;
+			
+			default:
+				// parameter is not a recognized type.
+				return false;
+		}
+	}
+
+	private boolean checkRange( double dvalue, Parameter param, Token arg,
+		int argNo ) throws ParseException
+	{
+		// we parsed the value as a double, now see if it is compatible with
+		// our parameter type.
+		switch (param.type().type().kind)
+		{
+			case EtchGrammarConstants.FLOAT:
+				checkRange( dvalue, Float.MIN_VALUE, Float.MAX_VALUE, param,
+					arg, argNo );
+				return true;
+			
+			case EtchGrammarConstants.DOUBLE:
+				// value is a double, and that is certainly compatible with
+				// double.
+				return true;
+			
+			default:
+				// parameter is not a recognized type.
+				return false;
+		}
+	}
+
+	private void checkRange( long value, long min, long max, Parameter param,
+		Token arg, int argNo ) throws ParseException
+	{
+		if (value >= min && value <= max)
+			return;
+		
+		throw new ParseException( String.format(
+			"Authorize method %s parameter %d (%s) integral value out of range at line %d",
+			method, argNo+1, param.name(), arg.beginLine ) );
+	}
+
+	private void checkRange( double dvalue, double min, double max,
+		Parameter param, Token arg, int argNo ) throws ParseException
+	{
+		// ignore sign, it doesn't matter.
+		
+		dvalue = Math.abs( dvalue );
+		
+		if (dvalue >= min && dvalue <= max)
+			return;
+		
+		throw new ParseException( String.format(
+			"Authorize method %s parameter %d (%s) floating value out of range at line %d",
+			method, argNo+1, param.name(), arg.beginLine ) );
+	}
+
+	private Long parseLong( String s, int radix, String prefix )
+	{
+		try
+		{
+			if (!s.toLowerCase().startsWith( prefix ))
+				return null;
+			return Long.parseLong( s.substring( prefix.length() ), radix );
+		}
+		catch ( NumberFormatException e )
+		{
+			return null;
+		}
+	}
+
+	private Double parseDouble( String image )
+	{
+		try
+		{
+			return Double.parseDouble( image );
+		}
+		catch ( NumberFormatException e )
+		{
+			return null;
+		}
+	}
+
+	private void checkOctalConstant( Parameter param, Token arg, int argNo )
+		throws ParseException
+	{
+		if (!param.type().isIntegral())
+			throw typeMismatch( param, arg, argNo );
+		
+		Long value = parseLong( arg.image, 8, "0" );
+		if (value != null)
+		{
+			// check range of long vs. integral or floating param type
+			if (checkRange( value, param, arg, argNo ))
+				return;
+		}
+		
+		// value range is too much for long or double type, or parameter
+		// is not a known integral or floating type
+		
+		throw typeMismatch( param, arg, argNo );
+	}
+
+	private void checkHexConstant( Parameter param, Token arg, int argNo )
+		throws ParseException
+	{
+		if (!param.type().isIntegral())
+			throw typeMismatch( param, arg, argNo );
+		
+		Long value = parseLong( arg.image, 16, "0x" );
+		if (value != null)
+		{
+			// check range of long vs. integral or floating param type
+			if (checkRange( value, param, arg, argNo ))
+				return;
+		}
+		
+		// value range is too much for long or double type, or parameter
+		// is not a known integral or floating type
+		
+		throw typeMismatch( param, arg, argNo );
+	}
+
+	private void checkBinaryConstant( Parameter param, Token arg, int argNo )
+		throws ParseException
+	{
+		if (!param.type().isIntegral())
+			throw typeMismatch( param, arg, argNo );
+		
+		Long value = parseLong( arg.image, 2, "0b" );
+		if (value != null)
+		{
+			// check range of long vs. integral or floating param type
+			if (checkRange( value, param, arg, argNo ))
+				return;
+		}
+		
+		// value range is too much for long or double type, or parameter
+		// is not a known integral or floating type
+		
+		throw typeMismatch( param, arg, argNo );
+	}
+
+	private void checkDecimalConstant( Parameter param, Token arg, int argNo )
+		throws ParseException
+	{
+		if (!param.type().isFloating())
+			throw typeMismatch( param, arg, argNo );
+		
+		Double dvalue = parseDouble( arg.image );
+		if (dvalue != null)
+		{
+			// check range of double vs. floating param type
+			if (checkRange( dvalue, param, arg, argNo ))
+				return;
+		}
+		
+		// value range is too much for long or double type, or parameter
+		// is not a known integral or floating type
+		
+		throw typeMismatch( param, arg, argNo );
+	}
+
+	private void checkStringConstant( Parameter param, Token arg, int argNo )
+		throws ParseException
+	{
+		if (!param.type().isString())
+			throw typeMismatch( param, arg, argNo );
+	}
+	
+	/**
+	 * Wrapper for arg which holds the required arg type as well.
+	 */
+	public static class AuthArg
+	{
+		/**
+		 * @param arg
+		 */
+		public AuthArg( Token arg )
+		{
+			this.arg = arg;
+		}
+		
+		private final Token arg;
+		
+		private TypeRef type;
+		
+		/**
+		 * @return the token of the arg.
+		 */
+		public Token value()
+		{
+			return arg;
+		}
+		
+		/**
+		 * Sets the required type of the arg.
+		 * @param type
+		 */
+		public void setType( TypeRef type )
+		{
+			this.type = type;
+		}
+		
+		/**
+		 * @return the required type of the arg.
+		 */
+		public TypeRef type()
+		{
+			return type;
+		}
+		
+		/**
+		 * @return true if not an id or qid.
+		 */
+		public boolean isLiteralConstant()
+		{
+			switch (arg.kind)
+			{
+				case EtchGrammarConstants.TRUE:
+				case EtchGrammarConstants.FALSE:
+				case EtchGrammarConstants.INTEGER:
+				case EtchGrammarConstants.OCTAL:
+				case EtchGrammarConstants.HEX:
+				case EtchGrammarConstants.BINARY:
+				case EtchGrammarConstants.DECIMAL:
+				case EtchGrammarConstants.STR:
+					return true;
+				default:
+					return false;
+			}
+		}
+		
+		/**
+		 * @param msg
+		 * @return true if this names a parameter of the protected
+		 * method.
+		 */
+		public boolean isParameter( Message msg )
+		{
+			switch (arg.kind)
+			{
+				case EtchGrammarConstants.ID:
+					return msg.hasParameter( arg.image );
+				
+				case EtchGrammarConstants.QID:
+				{
+					String[] n = StringUtil.leftSplit( arg.image, '.' );
+					return msg.hasParameter( n[0] );
+				}
+				
+				default:
+					return false;
+			}
+		}
+		
+		/**
+		 * @param intf
+		 * @return true if this names a constant of the service.
+		 */
+		public boolean isConstant( Service intf )
+		{
+			if (arg.kind != EtchGrammarConstants.ID
+					&& arg.kind != EtchGrammarConstants.QID)
+				return false;
+			
+			Named<?> named = intf.get( arg.image );
+			
+			return named != null && named.isConstant();
+		}
+		
+		/**
+		 * @param intf
+		 * @return true if this names an enum of the service.
+		 */
+		public boolean isEnum( Service intf )
+		{
+			if (arg.kind != EtchGrammarConstants.QID)
+				return false;
+			
+			String[] n = StringUtil.leftSplit( arg.image, '.' );
+			
+			Named<?> named = intf.get( n[0] );
+			
+			return named != null && named.isEnumx();
+		}
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/opt/Direction.java b/compiler/src/main/java/org/apache/etch/compiler/opt/Direction.java
new file mode 100644
index 0000000..68b34e3
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/opt/Direction.java
@@ -0,0 +1,93 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.opt;
+
+import java.util.EnumSet;
+
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.Token;
+import org.apache.etch.compiler.ast.Message;
+import org.apache.etch.compiler.ast.MessageDirection;
+import org.apache.etch.compiler.ast.Name;
+import org.apache.etch.compiler.ast.Opt;
+import org.apache.etch.compiler.ast.Service;
+
+
+/**
+ * Option which sets the direction of a message ([client->]server,
+ * [server->]client, or both.
+ */
+public class Direction extends Opt
+{
+	/**
+	 * Constructs the Direction.
+	 *
+	 * @param name
+	 * @param args
+	 * @throws ParseException
+	 */
+	public Direction( Name name, Token... args ) throws ParseException
+	{
+		super( name.name, name.token.beginLine );
+		addType( Message.class );
+		addType( Service.class );
+		
+		if (args.length != 1)
+			throw new ParseException( String.format( "Direction args length != 1" ) );
+		
+		Token arg = args[0];
+		if (arg.kind != EtchGrammarConstants.ID)
+			throw new ParseException( String.format( "Direction arg should be identifier: "+arg.image ) );
+		
+		try
+		{
+			md = MessageDirection.valueOf( arg.image.toUpperCase() );
+		}
+		catch ( IllegalArgumentException e )
+		{
+			throw new ParseException( String.format(
+				"Direction arg should be one of: "+EnumSet.allOf( MessageDirection.class ) ) );
+		}
+	}
+	
+	private final MessageDirection md;
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%s@Direction( %s )\n", indent, md );
+	}
+
+	@Override
+	public String toString()
+	{
+		return String.format( "@Direction( %s )", md );
+	}
+
+	/**
+	 * @return the appropriate MessageDirection for the direction.
+	 */
+	public MessageDirection getMessageDirection()
+	{
+		return md;
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/opt/Extern.java b/compiler/src/main/java/org/apache/etch/compiler/opt/Extern.java
new file mode 100644
index 0000000..244bcb5
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/opt/Extern.java
@@ -0,0 +1,167 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.opt;
+
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.Token;
+import org.apache.etch.compiler.ast.Name;
+import org.apache.etch.compiler.ast.Opt;
+
+
+/**
+ * Option which sets the language specific attributes of an extern
+ * declaration.
+ */
+public class Extern extends Opt
+{
+	/**
+	 * Constructs the Extern.
+	 *
+	 * @param name
+	 * @param args
+	 * @throws ParseException
+	 */
+	public Extern( Name name, Token... args ) throws ParseException
+	{
+		super( null, name.token.beginLine );
+		addType( org.apache.etch.compiler.ast.Extern.class );
+		
+		// usage: @Extern(language, name, nameImport, serializer, serializerImport)
+		// example: @Extern(java, "java.util.Date", "", "etch.bindings.java.util.DateSerializer", "")
+		
+		if (args.length != 5)
+			throw new ParseException( String.format(
+				"usage: @Extern(language, \"xname\", \"xnameImport\", \"serializer\", \"serializerImport\") at line %d",
+				name.token.beginLine ) );
+		
+		language = args[0];
+		xname = args[1];
+		xnameImport = args[2];
+		serializer = args[3];
+		serializerImport = args[4];
+		
+		if (language.kind != EtchGrammarConstants.ID)
+			throw new ParseException( String.format(
+				"Extern expected language to be <ID> at line %d",
+				language.beginLine ) );
+		
+		if (xname.kind != EtchGrammarConstants.STR)
+			throw new ParseException( String.format(
+				"Extern expected xname to be <STR> at line %d",
+				xname.beginLine ) );
+		
+		if (xnameImport.kind != EtchGrammarConstants.STR)
+			throw new ParseException( String.format(
+				"Extern expected xnameImport to be <STR> at line %d",
+				xnameImport.beginLine ) );
+		
+		if (serializer.kind != EtchGrammarConstants.STR)
+			throw new ParseException( String.format(
+				"Extern expected serializer to be <STR> at line %d",
+				serializer.beginLine ) );
+		
+		if (serializerImport.kind != EtchGrammarConstants.STR)
+			throw new ParseException( String.format(
+				"Extern expected serializerImport to be <STR> at line %d",
+				serializerImport.beginLine ) );
+	}
+	
+	@Override
+	public String name()
+	{
+		return "Extern."+language.image;
+	}
+	
+	/**
+	 * The language of this extern opt.
+	 */
+	public final Token language;
+	
+	/**
+	 * The name of the external class.
+	 */
+	public final Token xname;
+	
+	/**
+	 * How to make the external class available in the environment.
+	 */
+	public final Token xnameImport;
+	
+	/**
+	 * The name of the serializer class.
+	 */
+	public final Token serializer;
+
+	/**
+	 * How to make the serializer name available in the environment.
+	 */
+	public final Token serializerImport;
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%s@Extern %s %s %s %s %s\n", indent, language, xname, xnameImport, serializer, serializerImport );
+	}
+
+	@Override
+	public String toString()
+	{
+		return String.format( "@Extern %s %s %s %s %s", language, xname, xnameImport, serializer, serializerImport );
+	}
+
+	/**
+	 * @return the language (e.g., java) of this extern option.
+	 */
+	public Token getLanguage() {
+		return language;
+	}
+
+	/**
+	 * @return the fully qualified class name of the serializer for this extern.
+	 */
+	public Token getSerializer() {
+		return serializer;
+	}
+
+	/**
+	 * @return the "import" statement we might need to use to access the
+	 * serializer class. Blank ("") means none.
+	 */
+	public Token getSerializerImport() {
+		return serializerImport;
+	}
+
+	/**
+	 * @return the name of the external class.
+	 */
+	public Token getXname() {
+		return xname;
+	}
+
+	/**
+	 * @return the "import" statement we might need to use to access the
+	 * external class. Blank ("") means none.
+	 */
+	public Token getXnameImport() {
+		return xnameImport;
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/opt/Oneway.java b/compiler/src/main/java/org/apache/etch/compiler/opt/Oneway.java
new file mode 100644
index 0000000..962ca67
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/opt/Oneway.java
@@ -0,0 +1,95 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.opt;
+
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.Token;
+import org.apache.etch.compiler.ast.Message;
+import org.apache.etch.compiler.ast.Name;
+import org.apache.etch.compiler.ast.Opt;
+import org.apache.etch.compiler.ast.Service;
+
+
+/**
+ * Option which sets the oneway attribute of a message. If the message is
+ * oneway, then remote sends a message and doesn't wait for any response or
+ * thrown exception.
+ */
+public class Oneway extends Opt
+{
+	/**
+	 * Constructs the Oneway.
+	 *
+	 * @param name
+	 * @param args
+	 * @throws ParseException
+	 */
+	public Oneway( Name name, Token... args ) throws ParseException
+	{
+		super( name.name, name.token.beginLine );
+		addType( Message.class );
+		addType( Service.class );
+		
+		if (args.length > 1)
+			throw new ParseException( String.format(
+				"Oneway accepts one optional boolean argument at line %d",
+				name.token.beginLine ) );
+		
+		if (args.length > 0)
+		{
+			Token arg = args[0];
+			if (arg.kind != EtchGrammarConstants.TRUE &&
+					arg.kind != EtchGrammarConstants.FALSE)
+				throw new ParseException( String.format(
+					"Oneway accepts one optional boolean argument at line %d",
+					name.token.beginLine ) );
+			oneway = Boolean.parseBoolean( arg.image );
+		}
+		else
+		{
+			oneway = true;
+		}
+	}
+	
+	private final boolean oneway;
+	
+	/**
+	 * @return true if the message is a oneway message. A oneway message
+	 * does not delay the sender waiting for a response.
+	 */
+	public boolean isOneway()
+	{
+		return oneway;
+	}
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%s@Oneway %s\n", indent, oneway );
+	}
+
+	@Override
+	public String toString()
+	{
+		return String.format( "@Oneway %s", oneway );
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/opt/Timeout.java b/compiler/src/main/java/org/apache/etch/compiler/opt/Timeout.java
new file mode 100644
index 0000000..e35a65d
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/opt/Timeout.java
@@ -0,0 +1,85 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.opt;
+
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.Token;
+import org.apache.etch.compiler.ast.Message;
+import org.apache.etch.compiler.ast.Name;
+import org.apache.etch.compiler.ast.Opt;
+import org.apache.etch.compiler.ast.Service;
+
+
+/**
+ * Option which sets the timeout of a message which is expecting a
+ * result (that is, a call).
+ * The timeout is in ms.
+ */
+public class Timeout extends Opt
+{
+	/**
+	 * Constructs the Timeout.
+	 *
+	 * @param name
+	 * @param args
+	 * @throws ParseException
+	 */
+	public Timeout( Name name, Token... args ) throws ParseException
+	{
+		super( name.name, name.token.beginLine );
+		addType( Message.class );
+		addType( Service.class );
+		
+		if (args.length != 1)
+			throw new ParseException( String.format( "args.length != 1" ) );
+		Token arg = args[0];
+		if (arg.kind != EtchGrammarConstants.INTEGER)
+			throw new ParseException( String.format( "Timeout arg should be integer constant: "+arg.image ) );
+		int v = Integer.parseInt( arg.image );
+		if (v < 0)
+			throw new ParseException( String.format( "Timeout arg should be integer constant >= 0: "+arg.image ) );
+		
+		timeout = v;
+	}
+	
+	private final int timeout;
+	
+	/**
+	 * @return the timeout value.
+	 */
+	public int timeout()
+	{
+		return timeout;
+	}
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%s@Timeout( %d )\n", indent, timeout );
+	}
+
+	@Override
+	public String toString()
+	{
+		return String.format( "@Timeout( %d )", timeout );
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/opt/ToString.java b/compiler/src/main/java/org/apache/etch/compiler/opt/ToString.java
new file mode 100644
index 0000000..0a110fc
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/opt/ToString.java
@@ -0,0 +1,251 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.opt;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.Token;
+import org.apache.etch.compiler.ast.Except;
+import org.apache.etch.compiler.ast.Name;
+import org.apache.etch.compiler.ast.Opt;
+import org.apache.etch.compiler.ast.Struct;
+
+
+/**
+ * Option which sets the string format of a struct or exception.
+ */
+public class ToString extends Opt
+{
+	/**
+	 * Constructs the ToString.
+	 *
+	 * @param name
+	 * @param args
+	 * @throws ParseException
+	 */
+	public ToString( Name name, Token... args ) throws ParseException
+	{
+		super( name.name, name.token.beginLine );
+		addType( Except.class );
+		addType( Struct.class );
+		
+		if (args.length != 1)
+			throw new ParseException( String.format(
+				"ToString accepts one string argument at line %d",
+				name.token.beginLine ) );
+		
+		Token arg = args[0];
+		if (arg.kind != EtchGrammarConstants.STR)
+			throw new ParseException( String.format(
+				"ToString accepts one string argument at line %d",
+				arg.beginLine ) );
+		
+		try
+		{
+			format = parse( arg.image );
+		}
+		catch ( IOException e )
+		{
+			throw new ParseException( String.format(
+				"ToString: problem with format string at line %d: %s",
+				arg.beginLine, e.getMessage() ) );
+		}
+	}
+	
+	private final List<FmtItem> format;
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%s@ToString( %s )\n", indent, format );
+	}
+
+	@Override
+	public String toString()
+	{
+		return String.format( "@ToString( %s )", format );
+	}
+
+	/**
+	 * @return the format for the ToString.
+	 */
+	public List<FmtItem> getFormat()
+	{
+		return format;
+	}
+	
+	private static List<FmtItem> parse( String s ) throws IOException
+	{
+		if (s.startsWith( "\"" ))
+			s = s.substring( 1 );
+		
+		if (s.endsWith( "\"" ))
+			s = s.substring( 0, s.length()-1 );
+		
+		List<FmtItem> list = new ArrayList<FmtItem>();
+		StringReader rdr = new StringReader( s );
+		while (stringItem( list, rdr ) && fieldItem( list, rdr ))
+		{
+			// nothing else to do.
+		}
+		return list;
+	}
+
+	private static boolean stringItem( List<FmtItem> list, StringReader rdr )
+		throws IOException
+	{
+		StringBuffer sb = new StringBuffer();
+		int c;
+		boolean escape = false;
+		while ((c = rdr.read()) >= 0)
+		{
+			if (!escape)
+			{
+				if (c == '{')
+				{
+					// unescaped brace is start of format item.
+					break;
+				}
+				
+				if (c == '\\')
+				{
+					// unescaped backslash is start of escape
+					escape = true;
+					continue;
+				}
+			}
+			else
+			{
+				if (c == 't') c = '\t';
+				else if (c == 'r') c = '\r';
+				else if (c == 'n') c = '\n';
+				else if (c == '{') c = '{';
+				else if (c == '\\') c = '\\';
+				else throw new IOException( "bad escape. expecting one of t, r, n, {, or \\. got '"+(char) c+"'" );
+				escape = false;
+			}
+			
+			sb.append( (char) c );
+		}
+		
+		if (escape)
+			throw new IOException( "partial escape at end of string" );
+		
+		if (sb.length() > 0)
+			list.add( new StringItem( sb.toString() ) );
+		
+		return c >= 0;
+	}
+
+	private static boolean fieldItem( List<FmtItem> list, StringReader rdr )
+		throws IOException
+	{
+		StringBuffer sb = new StringBuffer();
+		int c;
+		while ((c = rdr.read()) >= 0)
+		{
+			if (c == '}')
+				break;
+			
+			sb.append( (char) c );
+		}
+		
+		if (c != '}')
+			throw new IOException( "unclosed field item at end of string" );
+		
+		if (sb.length() > 0)
+			list.add( new FieldItem( sb.toString() ) );
+		
+		return c >= 0;
+	}
+
+	/**
+	 * A format item.
+	 */
+	public interface FmtItem
+	{
+		/**
+		 * @return the value of the format item.
+		 */
+		public String value();
+	}
+	
+	/**
+	 * A string format item.
+	 */
+	public static class StringItem implements FmtItem
+	{
+		/**
+		 * Constructs the string format item.
+		 * @param s the string format item.
+		 */
+		public StringItem( String s )
+		{
+			this.s = s;
+		}
+		
+		private final String s;
+		
+		@Override
+		public String toString()
+		{
+			return "String: '"+s+"'";
+		}
+
+		public String value()
+		{
+			return s;
+		}
+	}
+	
+	/**
+	 * A field format item.
+	 */
+	public static class FieldItem implements FmtItem
+	{
+		/**
+		 * Constructs the field format item.
+		 * @param s the name of the field.
+		 */
+		public FieldItem( String s )
+		{
+			this.s = s;
+		}
+		
+		private final String s;
+		
+		@Override
+		public String toString()
+		{
+			return "Field: "+s;
+		}
+
+		public String value()
+		{
+			return s;
+		}
+	}
+}
diff --git a/compiler/src/main/java/org/apache/etch/compiler/opt/Unchecked.java b/compiler/src/main/java/org/apache/etch/compiler/opt/Unchecked.java
new file mode 100644
index 0000000..e91a90c
--- /dev/null
+++ b/compiler/src/main/java/org/apache/etch/compiler/opt/Unchecked.java
@@ -0,0 +1,92 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler.opt;
+
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.apache.etch.compiler.ParseException;
+import org.apache.etch.compiler.Token;
+import org.apache.etch.compiler.ast.Except;
+import org.apache.etch.compiler.ast.Name;
+import org.apache.etch.compiler.ast.Opt;
+
+
+/**
+ * Option which sets the unchecked attribute of an exception.
+ */
+public class Unchecked extends Opt
+{
+	/**
+	 * Constructs the Unchecked.
+	 *
+	 * @param name
+	 * @param args
+	 * @throws ParseException
+	 */
+	public Unchecked( Name name, Token... args ) throws ParseException
+	{
+		super( name.name, name.token.beginLine );
+		addType( Except.class );
+		
+		if (args.length > 1)
+			throw new ParseException( String.format(
+				"Unchecked accepts one optional boolean argument at line %d",
+				name.token.beginLine ) );
+		
+		if (args.length > 0)
+		{
+			Token arg = args[0];
+			if (arg.kind != EtchGrammarConstants.TRUE &&
+					arg.kind != EtchGrammarConstants.FALSE)
+				throw new ParseException( String.format(
+					"Unchecked accepts one optional boolean argument at line %d",
+					name.token.beginLine ) );
+			unchecked = Boolean.parseBoolean( arg.image );
+		}
+		else
+		{
+			unchecked = true;
+		}
+	}
+	
+	private final boolean unchecked;
+	
+	/**
+	 * @return true if the exception should inherit from an unchecked
+	 * type (e.g., java's RuntimeException) vs. a checked type (e.g.,
+	 * java's Exception).
+	 */
+	public boolean isUnchecked()
+	{
+		return unchecked;
+	}
+
+	@Override
+	public void dump( String indent )
+	{
+		System.out.printf( "%s@Unchecked\n", indent );
+	}
+
+	@Override
+	public String toString()
+	{
+		return String.format( "@Unchecked" );
+	}
+}
diff --git a/compiler/src/main/javacc/EtchGrammar.html b/compiler/src/main/javacc/EtchGrammar.html
new file mode 100644
index 0000000..c0551e7
--- /dev/null
+++ b/compiler/src/main/javacc/EtchGrammar.html
@@ -0,0 +1,277 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<!--
+ *  Licensed to the Apache Software Foundation (ASF) under one   *
+ *  or more contributor license agreements.  See the NOTICE file *
+ *  distributed with this work for additional information        *
+ *  regarding copyright ownership.  The ASF licenses this file   *
+ *  to you under the Apache License, Version 2.0 (the            *
+ *  "License"); you may not use this file except in compliance   *
+ *  with the License.  You may obtain a copy of the License at   *
+ *                                                               *
+ *    http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                               *
+ *  Unless required by applicable law or agreed to in writing,   *
+ *  software distributed under the License is distributed on an  *
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ *  KIND, either express or implied.  See the License for the    *
+ *  specific language governing permissions and limitations      *
+ *  under the License.                                           *
+-->
+<HTML>
+<HEAD>
+<TITLE>BNF for EtchGrammar.jj</TITLE>
+</HEAD>
+<BODY>
+<H1 ALIGN=CENTER>BNF for EtchGrammar.jj</H1>
+<H2 ALIGN=CENTER>TOKENS</H2>
+<TABLE>
+ <!-- Special token -->
+ <TR>
+  <TD>
+<PRE>
+/*
+ * Tokens to ignore in the BNF follow.
+ */</PRE>
+  </TD>
+ </TR>
+ <!-- Token -->
+ <TR>
+  <TD>
+   <PRE>
+&lt;DEFAULT&gt; SKIP : {
+" "
+| "\t"
+| "\r"
+| "\n"
+| "\f"
+| &lt;SINGLE1: "//" (~["\r","\n"])* ["\r","\n"]&gt;
+| &lt;SINGLE2: "#" (~["\r","\n"])* ["\r","\n"]&gt;
+}
+
+   </PRE>
+  </TD>
+ </TR>
+ <!-- Token -->
+ <TR>
+  <TD>
+   <PRE>
+&lt;DEFAULT&gt; SPECIAL : {
+&lt;FORMAL: "/**" (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/"&gt;
+| &lt;BLOCK: "/*" (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/"&gt;
+}
+
+   </PRE>
+  </TD>
+ </TR>
+ <!-- Token -->
+ <TR>
+  <TD>
+   <PRE>
+&lt;DEFAULT&gt; TOKEN : {
+&lt;BOOLEAN: "boolean"&gt;
+| &lt;BYTE: "byte"&gt;
+| &lt;CONST: "const"&gt;
+| &lt;DOUBLE: "double"&gt;
+| &lt;ENUM: "enum"&gt;
+| &lt;EXCEPTION: "exception"&gt;
+| &lt;EXTENDS: "extends"&gt;
+| &lt;EXTERN: "extern"&gt;
+| &lt;FALSE: "false"&gt;
+| &lt;FLOAT: "float"&gt;
+| &lt;INCLUDE: "include"&gt;
+| &lt;INT: "int"&gt;
+| &lt;LONG: "long"&gt;
+| &lt;MIXIN: "mixin"&gt;
+| &lt;MODULE: "module"&gt;
+| &lt;NULL: "null"&gt;
+| &lt;OBJECT: "object"&gt;
+| &lt;SERVICE: "service"&gt;
+| &lt;SHORT: "short"&gt;
+| &lt;STRING: "string"&gt;
+| &lt;STRUCT: "struct"&gt;
+| &lt;THROWS: "throws"&gt;
+| &lt;TRUE: "true"&gt;
+| &lt;VOID: "void"&gt;
+| &lt;ID: ["a"-"z","A"-"Z"] (["a"-"z","A"-"Z","0"-"9","_"])*&gt;
+| &lt;QID: &lt;ID&gt; ("." &lt;ID&gt;)+&gt;
+| &lt;#INT_LIT: ["1"-"9"] (["0"-"9"])*&gt;
+| &lt;#SGN: (["-"])?&gt;
+| &lt;INTEGER: &lt;SGN&gt; ("0" | &lt;INT_LIT&gt;)&gt;
+| &lt;OCTAL: "0" (["0"-"7"])+&gt;
+| &lt;HEX: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+&gt;
+| &lt;BINARY: "0" ["b","B"] (["0"-"1"])+&gt;
+| &lt;#EXP: ["e","E"] &lt;INTEGER&gt;&gt;
+| &lt;#FRACTION: &lt;SGN&gt; "." (["0"-"9"])+&gt;
+| &lt;DECIMAL: &lt;INTEGER&gt; ("." (["0"-"9"])*)? &lt;EXP&gt; | &lt;INTEGER&gt; "." (["0"-"9"])* (&lt;EXP&gt;)? | &lt;FRACTION&gt; (&lt;EXP&gt;)?&gt;
+| &lt;STR: "\"" (~["\"","\\","\r","\n"] | "\\" ["\"","\\","r","n","t"] | "\\u" (["0"-"9","a"-"f","A"-"F"]){4,-1})* "\""&gt;
+| &lt;AT: "@"&gt;
+| &lt;COMMA: ","&gt;
+| &lt;EQ: "="&gt;
+| &lt;SEMI: ";"&gt;
+| &lt;LPAREN: "("&gt;
+| &lt;RPAREN: ")"&gt;
+| &lt;LBRACE: "{"&gt;
+| &lt;RBRACE: "}"&gt;
+| &lt;LBRACKET: "["&gt;
+| &lt;RBRACKET: "]"&gt;
+}
+
+   </PRE>
+  </TD>
+ </TR>
+</TABLE>
+<H2 ALIGN=CENTER>NON-TERMINALS</H2>
+<TABLE>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod1">module</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod2">module_stmt</A> <A HREF="#prod3">service</A></TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod2">module_stmt</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>&lt;MODULE&gt; <A HREF="#prod4">xid</A> ( &lt;SEMI&gt; )?</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod3">service</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod5">opts</A> &lt;SERVICE&gt; <A HREF="#prod6">def</A> &lt;LBRACE&gt; <A HREF="#prod7">stmts</A> &lt;RBRACE&gt;</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod5">opts</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>( <A HREF="#prod8">opt</A> )*</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod8">opt</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>&lt;AT&gt; <A HREF="#prod9">id</A> ( &lt;LPAREN&gt; <A HREF="#prod10">args</A> &lt;RPAREN&gt; )?</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod10">args</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod11">arg</A> ( &lt;COMMA&gt; <A HREF="#prod11">arg</A> )*</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod11">arg</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>( <A HREF="#prod12">cvalue</A> | <A HREF="#prod4">xid</A> | &lt;NULL&gt; )</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod12">cvalue</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>( &lt;TRUE&gt; | &lt;FALSE&gt; | &lt;INTEGER&gt; | &lt;OCTAL&gt; | &lt;HEX&gt; | &lt;BINARY&gt; | &lt;DECIMAL&gt; | &lt;STR&gt; )</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod7">stmts</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>( <A HREF="#prod5">opts</A> ( <A HREF="#prod13">mixin_stmt</A> | <A HREF="#prod14">include_stmt</A> | <A HREF="#prod15">const_stmt</A> | <A HREF="#prod16">enum_stmt</A> | <A HREF="#prod17">struct_stmt</A> | <A HREF="#prod18">extern_stmt</A> | <A HREF="#prod19">exception_stmt</A> | <A HREF="#prod20">message_stmt</A> ) )*</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod13">mixin_stmt</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>&lt;MIXIN&gt; <A HREF="#prod21">ref</A> ( &lt;SEMI&gt; )?</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod14">include_stmt</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>&lt;INCLUDE&gt; &lt;STR&gt; ( &lt;SEMI&gt; )?</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod15">const_stmt</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>&lt;CONST&gt; <A HREF="#prod22">ctype</A> <A HREF="#prod6">def</A> &lt;EQ&gt; <A HREF="#prod12">cvalue</A> ( &lt;SEMI&gt; )?</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod16">enum_stmt</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>&lt;ENUM&gt; <A HREF="#prod6">def</A> &lt;LPAREN&gt; <A HREF="#prod23">item_list</A> &lt;RPAREN&gt; ( &lt;SEMI&gt; )?</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod23">item_list</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod6">def</A> ( &lt;COMMA&gt; <A HREF="#prod6">def</A> )*</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod17">struct_stmt</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>&lt;STRUCT&gt; <A HREF="#prod6">def</A> <A HREF="#prod24">params</A> ( &lt;EXTENDS&gt; <A HREF="#prod21">ref</A> )? ( &lt;SEMI&gt; )?</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod18">extern_stmt</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>&lt;EXTERN&gt; <A HREF="#prod6">def</A> ( &lt;SEMI&gt; )?</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod19">exception_stmt</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>&lt;EXCEPTION&gt; <A HREF="#prod6">def</A> <A HREF="#prod24">params</A> ( &lt;EXTENDS&gt; <A HREF="#prod21">ref</A> )? ( &lt;SEMI&gt; )?</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod20">message_stmt</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod25">rtype</A> <A HREF="#prod6">def</A> <A HREF="#prod24">params</A> ( &lt;THROWS&gt; <A HREF="#prod26">throws_list</A> )? ( &lt;SEMI&gt; )?</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod26">throws_list</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod21">ref</A> ( &lt;COMMA&gt; <A HREF="#prod21">ref</A> )*</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod9">id</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>&lt;ID&gt;</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod27">qid</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>&lt;QID&gt;</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod4">xid</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>( <A HREF="#prod27">qid</A> | <A HREF="#prod9">id</A> )</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod6">def</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod9">id</A></TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod21">ref</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod4">xid</A></TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod22">ctype</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>( &lt;BOOLEAN&gt; | &lt;BYTE&gt; | &lt;SHORT&gt; | &lt;INT&gt; | &lt;LONG&gt; | &lt;FLOAT&gt; | &lt;DOUBLE&gt; | &lt;STRING&gt; )</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod28">ptype</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>( <A HREF="#prod22">ctype</A> | &lt;OBJECT&gt; | <A HREF="#prod21">ref</A> )</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod25">rtype</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>( ( <A HREF="#prod28">ptype</A> <A HREF="#prod29">dim</A> ) | &lt;VOID&gt; )</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod29">dim</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>( &lt;LBRACKET&gt; &lt;RBRACKET&gt; )*</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod24">params</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>&lt;LPAREN&gt; ( <A HREF="#prod30">param</A> ( &lt;COMMA&gt; <A HREF="#prod30">param</A> )* )? &lt;RPAREN&gt;</TD>
+</TR>
+<TR>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod30">param</A></TD>
+<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod28">ptype</A> <A HREF="#prod29">dim</A> <A HREF="#prod6">def</A></TD>
+</TR>
+</TABLE>
+</BODY>
+</HTML>
diff --git a/compiler/src/main/javacc/EtchGrammar.jj b/compiler/src/main/javacc/EtchGrammar.jj
new file mode 100644
index 0000000..59e7727
--- /dev/null
+++ b/compiler/src/main/javacc/EtchGrammar.jj
@@ -0,0 +1,479 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one   *
+ *  or more contributor license agreements.  See the NOTICE file *
+ *  distributed with this work for additional information        *
+ *  regarding copyright ownership.  The ASF licenses this file   *
+ *  to you under the Apache License, Version 2.0 (the            *
+ *  "License"); you may not use this file except in compliance   *
+ *  with the License.  You may obtain a copy of the License at   *
+ *                                                               *
+ *    http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                               *
+ *  Unless required by applicable law or agreed to in writing,   *
+ *  software distributed under the License is distributed on an  *
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ *  KIND, either express or implied.  See the License for the    *
+ *  specific language governing permissions and limitations      *
+ *  under the License.                                           *
+ */
+
+/* $Id$
+ *
+ * Grammer for the etch idl compiler.
+ */
+ 
+options
+{
+	JAVA_UNICODE_ESCAPE = false;
+	STATIC = false;
+	JDK_VERSION = "1.5";
+	OUTPUT_DIRECTORY = "../../../target/generated-sources/main/javacc/java/org/apache/etch/compiler";
+}
+
+PARSER_BEGIN(EtchGrammar)
+
+package org.apache.etch.compiler;
+
+import java.io.InputStream;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.etch.compiler.ast.Constant;
+import org.apache.etch.compiler.ast.Enumx;
+import org.apache.etch.compiler.ast.Except;
+import org.apache.etch.compiler.ast.Service;
+import org.apache.etch.compiler.ast.Item;
+import org.apache.etch.compiler.ast.Message;
+import org.apache.etch.compiler.ast.Module;
+import org.apache.etch.compiler.ast.Name;
+import org.apache.etch.compiler.ast.Opt;
+import org.apache.etch.compiler.ast.ParamList;
+import org.apache.etch.compiler.ast.Parameter;
+import org.apache.etch.compiler.ast.Struct;
+import org.apache.etch.compiler.ast.Thrown;
+import org.apache.etch.compiler.ast.TypeRef;
+
+/** The JavaCC grammar file for the etch compiler. */
+public class EtchGrammar extends EtchHelper
+{
+	public EtchGrammar( Backend b, InputStream is )
+	{
+		this( is );
+		this.binding = b;
+	}
+	
+	private Backend binding;
+	
+	private Service gintf;
+}
+
+PARSER_END(EtchGrammar)
+
+/*
+ * Tokens to ignore in the BNF follow.
+ */
+
+SKIP :
+{
+	<" ">
+|	<"\t">
+|	<"\r">
+|	<"\n">
+|	<"\f">
+|	<SINGLE1 : "//" (~["\r","\n"])* ["\r","\n"]>
+|	<SINGLE2 : "#" (~["\r","\n"])* ["\r","\n"]>
+}
+
+SPECIAL_TOKEN :
+{
+	<FORMAL : "/**" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
+|	<BLOCK : "/*" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
+}
+
+TOKEN :
+{
+	<BOOLEAN : "boolean">
+|	<BYTE : "byte">
+|	<CONST : "const">
+|	<DOUBLE : "double">
+|	<ENUM : "enum">
+|	<EXCEPTION : "exception">
+|	<EXTENDS : "extends">
+|	<EXTERN : "extern">
+|	<FALSE : "false">
+|	<FLOAT : "float">
+|   <INCLUDE : "include">
+|	<INT : "int">
+|	<LONG : "long">
+|	<MIXIN : "mixin">
+|	<MODULE : "module">
+|	<NULL : "null">
+|	<OBJECT : "object">
+|	<SERVICE : "service">
+|	<SHORT : "short">
+|	<STRING : "string">
+|	<STRUCT : "struct">
+|	<THROWS : "throws">
+|	<TRUE : "true">
+|	<VOID : "void">
+|	<ID : ["a"-"z","A"-"Z"] (["a"-"z","A"-"Z","0"-"9","_"])*>
+|	<QID : <ID> ( "." <ID> )+>
+|	<#INT_LIT : ["1"-"9"] (["0"-"9"])*>
+|	<#SGN : (["-"])?>
+|	<INTEGER : <SGN> ("0" | <INT_LIT>)>
+|	<OCTAL : "0" (["0"-"7"])+>
+|	<HEX : "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+>
+|	<BINARY : "0" ["b","B"] (["0"-"1"])+>
+|	<#EXP : ["e", "E"] <INTEGER>>
+|	<#FRACTION : <SGN> "." (["0"-"9"])+>
+|	<DECIMAL : (<INTEGER> ( "." (["0"-"9"])* )? <EXP>) | (<INTEGER> "." (["0"-"9"])* (<EXP>)?) | (<FRACTION> (<EXP>)?)>
+|	<STR : "\"" (~["\"","\\","\r","\n"] | ("\\" ["\"","\\","r","n","t"]) | ("\\u" (["0"-"9","a"-"f","A"-"F"]){4}))* "\"">
+|	<AT : "@">
+|	<COMMA : ",">
+|	<EQ : "=">
+|	<SEMI : ";">
+|	<LPAREN : "(">
+|	<RPAREN : ")">
+|	<LBRACE : "{">
+|	<RBRACE : "}">
+|	<LBRACKET : "[">
+|	<RBRACKET : "]">
+}
+
+Module module( CmdLineOptions cmdLineOptions ) :
+{ Module m; }
+{
+	m = module_stmt( cmdLineOptions )
+	service( m )
+	{ return m; }
+}
+
+Module module_stmt( CmdLineOptions cmdLineOptions ) :
+{ Token k; Token t; }
+{
+	k = <MODULE> t = xid() ( <SEMI> )?
+	
+	{
+		Module m = new Module( new Name( t, t.image ), cmdLineOptions );
+		moduleComment( m, k.specialToken );
+		return m;
+	}
+}
+
+void service( Module m ) :
+{ Map<String, Opt> opts; Token k; Name n; Service i; }
+{
+	{
+		doStartService();	
+	}
+	
+	opts = opts()
+	k = <SERVICE> n = def()
+	{		 
+		saveComment( k.specialToken );
+		i = m.addService( n, opts );
+		serviceComment( i, getComment() );
+		binding.addDefaults( i );
+		Service ointf = gintf;
+		gintf = i;
+	}
+	<LBRACE> stmts( i ) <RBRACE>
+	{
+		gintf = ointf;
+		doEndService( i );	
+	}
+}
+
+Map<String, Opt> opts() :
+{ Map<String, Opt> map = new HashMap<String, Opt>(); Opt o; }
+{
+	(
+		o = opt()
+		{ map.put( o.name(), o ); }
+	)*
+	{ return map; }
+}
+
+Opt opt() :
+{ Token k; Token n; List<Token> list = new ArrayList<Token>(); }
+{
+	k = <AT> n = id()
+	{
+		saveComment( k.specialToken );
+	}
+	( <LPAREN> args( list ) <RPAREN> )?
+	{ return makeOpt( new Name( n, n.image ), list ); }
+}
+
+void args( List<Token> list ) :
+{ Token v; }
+{
+	v = arg() { list.add( v ); }
+	(
+		<COMMA> v = arg()
+		{ list.add( v ); }
+	)*
+}
+
+Token arg() :
+{ Token t; }
+{
+	(
+		t = cvalue()
+	|	t = ref()
+	|	t = <NULL>
+	)
+	{ return t; }
+}
+
+Token cvalue() :
+{ Token t; }
+{
+	(
+		t = <TRUE>
+	|	t = <FALSE>
+	|	t = <INTEGER>
+	|	t = <OCTAL>
+	|	t = <HEX>
+	|	t = <BINARY>
+	|	t = <DECIMAL>
+	|	t = <STR> { fixString( t ); }
+	)
+	{ return t; }
+}
+
+void stmts( Service i ) :
+{ Map<String, Opt> opts; }
+{
+	(
+		opts = opts()
+		(
+			mixin_stmt( i, opts )
+		|	include_stmt( i, opts )
+		|	const_stmt( i, opts )
+		|	enum_stmt( i, opts )
+		|	struct_stmt( i, opts )
+		|	extern_stmt( i, opts )
+		|	exception_stmt( i, opts )
+		|	message_stmt( i, opts )
+		)
+	)*
+}
+
+void mixin_stmt( Service i, Map<String, Opt> opts ) :
+{ Token t; }
+{
+	<MIXIN> t = ref() ( <SEMI> )?
+	{ i.addMixin( new Name( t, t.image ), opts ); }
+}
+
+
+void include_stmt( Service i, Map<String, Opt> opts ) :
+{ Token f; }
+{
+	<INCLUDE> f = <STR> ( <SEMI> )?
+	{ 
+		doInclude( f, i ); 
+	}
+}
+
+void const_stmt( Service i, Map<String, Opt> opts ) :
+{ Token k; TypeRef tr; Name n; Token v; }
+{
+	k = <CONST> tr = ctype() n = def() <EQ> v = cvalue() ( <SEMI> )?
+	{
+		Constant c = i.addConstant( n, opts, tr, v );
+		constantComment( c, k.specialToken );
+	}
+}
+
+void enum_stmt( Service i, Map<String, Opt> opts ) :
+{ Token k; Name n; Enumx e; }
+{
+	k = <ENUM> n = def()
+	{
+		e = i.addEnum( n, opts );
+		enumComment( e, k.specialToken );
+	}
+	<LPAREN> item_list( e ) <RPAREN> ( <SEMI> )?
+}
+
+void item_list( Enumx e ) :
+{ Name n; Item i; }
+{
+	n = def()
+	{
+		i = e.addItem( n );
+		itemComment( i, n.token.specialToken );
+	}
+	(
+		<COMMA> n = def()
+		{
+			i = e.addItem( n );
+			itemComment( i, n.token.specialToken );
+		}
+	)*
+}
+
+void struct_stmt( Service i, Map<String, Opt> opts ) :
+{ Token k; Name n; Struct s; Token x; Token e; }
+{
+	k = <STRUCT> n = def()
+	{ saveComment( k.specialToken ); x = getComment(); s = i.addStruct( n, opts ); }
+	params( s )
+	( <EXTENDS> e = ref() { s.setExtends( new Name( e, e.image ) ); } )?
+	( <SEMI> )?
+	{ structComment( s, x ); }
+}
+
+void extern_stmt( Service i, Map<String, Opt> opts ) :
+{ Name n; }
+{
+	<EXTERN> n = def()
+	{ i.addExtern( n, opts ); }
+	( <SEMI> )?
+}
+
+void exception_stmt( Service i, Map<String, Opt> opts ) :
+{ Token k; Name n; Except s; Token x; Token e; }
+{
+	k = <EXCEPTION> n = def()
+	{ saveComment( k.specialToken ); x = getComment(); s = i.addExcept( n, opts ); }
+	params( s )
+	( <EXTENDS> e = ref() { s.setExtends( new Name( e, e.image ) ); } )?
+	( <SEMI> )?
+	{ exceptComment( s, x ); }
+}
+
+void message_stmt( Service i, Map<String, Opt> opts ) :
+{ TypeRef rt; Name n; Message m; Token k; }
+{
+	rt = rtype() n = def()
+	{
+		saveComment( rt.type().specialToken );
+		k = getComment();
+		m = i.addMessage( n, opts, rt );
+	}
+	params( m )
+	(
+		<THROWS> throws_list( m )
+	)?
+	( <SEMI> )?
+	{ messageComment( m, k ); }
+}
+
+void throws_list( Message m ) :
+{ Token n; Thrown t; }
+{
+	n = ref()
+	{
+		t = m.addThrown( new Name( n, n.image ) );
+		thrownComment( t, n.specialToken );
+	}
+	(
+		<COMMA> n = ref()
+		{
+			t = m.addThrown( new Name( n, n.image ) );
+			thrownComment( t, n.specialToken );
+		}
+	)*
+}
+
+Token id() :
+{ Token t; }
+{
+	t = <ID>
+	{ return t; }
+}
+
+Token qid() :
+{ Token t; }
+{
+	t = <QID>
+	{ return t; }
+}
+
+Token xid() :
+{ Token t; }
+{
+	( t = qid() | t = id() )
+	{ return t; }
+}
+
+Name def() :
+{ Token t; }
+{
+	t = id()
+	{ return new Name( t, t.image ); }
+}
+
+Token ref() :
+{ Token t; }
+{
+	t = xid()
+	{ return t; }
+}
+
+TypeRef ctype() :
+{ Token t; }
+{
+	(
+		t = <BOOLEAN>
+	|	t = <BYTE>
+	|	t = <SHORT>
+	|	t = <INT>
+	|	t = <LONG>
+	|	t = <FLOAT>
+	|	t = <DOUBLE>
+	|	t = <STRING>
+	)
+	{ return new TypeRef( gintf, t ); }
+}
+
+TypeRef ptype() :
+{ TypeRef tr; Token t; }
+{
+	(
+		tr = ctype()
+	|   t = <OBJECT> { tr = new TypeRef( gintf, t ); }
+	|	t = ref() { tr = new TypeRef( gintf, t ); }
+	)
+	{ return tr; }
+}
+
+TypeRef rtype() :
+{ TypeRef tr; Token t; int d; }
+{
+	(
+		( tr = ptype() d = dim() { tr.setDim( d ); } )
+	|	t = <VOID> { tr = new TypeRef( gintf, t ); }
+	)
+	{ return tr; }
+}
+
+int dim() :
+{ int d = 0; }
+{
+	( <LBRACKET> <RBRACKET> { d++; } )*
+	{ return d; }
+}
+
+void params( ParamList<?> pl ) :
+{}
+{
+	<LPAREN> ( param( pl ) ( <COMMA> param( pl ) )* )? <RPAREN>
+}
+
+void param( ParamList<?> pl ) :
+{ TypeRef tr; int d; Name n; }
+{
+	tr = ptype() d = dim() n = def()
+	{
+		tr.setDim( d );
+		Parameter p = pl.addParameter( n, tr );
+		parameterComment( p, tr.type().specialToken );
+	}
+}
diff --git a/compiler/src/main/resources/org/apache/etch/compiler/globalKeywords.kwd b/compiler/src/main/resources/org/apache/etch/compiler/globalKeywords.kwd
new file mode 100644
index 0000000..b012919
--- /dev/null
+++ b/compiler/src/main/resources/org/apache/etch/compiler/globalKeywords.kwd
@@ -0,0 +1,15 @@
+# $Id$
+# 
+# Copyright 2007-2008 Cisco Systems Inc.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy
+# of the License at
+#  
+#     http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
\ No newline at end of file
diff --git a/compiler/src/main/scripts/etch.bat b/compiler/src/main/scripts/etch.bat
new file mode 100644
index 0000000..b4573be
--- /dev/null
+++ b/compiler/src/main/scripts/etch.bat
@@ -0,0 +1,36 @@
+@rem  Licensed to the Apache Software Foundation (ASF) under one   *
+@rem  or more contributor license agreements.  See the NOTICE file *
+@rem  distributed with this work for additional information        *
+@rem  regarding copyright ownership.  The ASF licenses this file   *
+@rem  to you under the Apache License, Version 2.0 (the            *
+@rem  "License"); you may not use this file except in compliance   *
+@rem  with the License.  You may obtain a copy of the License at   *
+@rem                                                               *
+@rem    http://www.apache.org/licenses/LICENSE-2.0                 *
+@rem                                                               *
+@rem  Unless required by applicable law or agreed to in writing,   *
+@rem  software distributed under the License is distributed on an  *
+@rem  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+@rem  KIND, either express or implied.  See the License for the    *
+@rem  specific language governing permissions and limitations      *
+@rem  under the License.                                           *
+@echo off
+setlocal
+
+rem Find the etch home directory
+
+set ETCH_HOME=%~dp0..
+
+rem Make enough of a classpath to get to first base
+
+set ETCH_CP=
+for %%i in ("%ETCH_HOME%\lib\etch-compiler-*.jar") do set ETCH_CP=%ETCH_CP%;%%i
+
+rem add clover to classpath if defined and exists
+
+if "%CLOVER_HOME%" == "" goto skip_clover
+if not exist "%CLOVER_HOME%\lib\clover.jar" goto skip_clover
+set ETCH_CP=%ETCH_CP%;%CLOVER_HOME%\lib\clover.jar
+:skip_clover
+
+java -cp "%ETCH_CP%" org.apache.etch.compiler.EtchMain %*
diff --git a/compiler/src/main/scripts/etch.sh b/compiler/src/main/scripts/etch.sh
new file mode 100755
index 0000000..8167f6b
--- /dev/null
+++ b/compiler/src/main/scripts/etch.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+#  Licensed to the Apache Software Foundation (ASF) under one   *
+#  or more contributor license agreements.  See the NOTICE file *
+#  distributed with this work for additional information        *
+#  regarding copyright ownership.  The ASF licenses this file   *
+#  to you under the Apache License, Version 2.0 (the            *
+#  "License"); you may not use this file except in compliance   *
+#  with the License.  You may obtain a copy of the License at   *
+#                                                               *
+#    http://www.apache.org/licenses/LICENSE-2.0                 *
+#                                                               *
+#  Unless required by applicable law or agreed to in writing,   *
+#  software distributed under the License is distributed on an  *
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+#  KIND, either express or implied.  See the License for the    *
+#  specific language governing permissions and limitations      *
+#  under the License.                                           *
+
+#
+# Run Etch compiler.
+#
+
+# Find Java
+if [ "${JAVA_HOME}" != "" ]; then
+    JAVA_CMD="${JAVA_HOME}"/bin/java
+else
+    JAVA_CMD=`which java`
+fi
+if [ ! -x "${JAVA_CMD}" ]; then
+    echo "Cannot find Java"
+    exit 1
+fi
+
+# Compute ETCH Home
+export ETCH_HOME=`dirname "$0"`/..
+
+# Compute classpath for compiler
+ETCH_CP=
+for x in `cd "${ETCH_HOME}"; echo lib/etch-compiler-*.jar` ; do
+    ETCH_CP="${ETCH_CP}:${ETCH_HOME}/$x"
+done
+
+# Add clover if installed ..
+if [ -f "${CLOVER_HOME}/lib/clover.jar" ]; then
+    ETCH_CP="${ETCH_CP}:${CLOVER_HOME}/lib/clover.jar"
+fi
+
+# Invoke Etch
+exec "$JAVA_CMD" -cp "${ETCH_CP}" "-Detch.home=${ETCH_HOME}" org.apache.etch.compiler.EtchMain ${1+"$@"}
diff --git a/compiler/src/test/etch/comments/Comments.etch b/compiler/src/test/etch/comments/Comments.etch
new file mode 100644
index 0000000..2ad3fb5
--- /dev/null
+++ b/compiler/src/test/etch/comments/Comments.etch
@@ -0,0 +1,74 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.compiler.test
+
+service Comments
+{
+	/**/
+	/***/
+	/****/
+	/*****/
+	/******/
+	
+	/* */
+	/*  */
+	/*   */
+	/*    */
+	/*     */
+	
+	/* * */
+	/* * * */
+	/* * * * */
+	/* * * * * */
+	/* * * * * * */
+	
+	/* ** */
+	/* ** ** */
+	/* ** ** ** */
+	/* ** ** ** ** */
+	/* ** ** ** ** ** */
+	
+	/* / * / */
+	/* / * / * / */
+	/* / * / * / * / */
+	/* / * / * / * / * / */
+	/* / * / * / * / * / * / */
+	
+	//
+	///
+	////
+	/////
+	
+	#
+	##
+	###
+	####
+	#####
+	
+	//blah
+	// blah
+	//*
+	// *
+	
+	#blah
+	# blah
+	#/*
+	# /*
+	//#
+	#//
+}
diff --git a/compiler/src/test/etch/constants/Constants.etch b/compiler/src/test/etch/constants/Constants.etch
new file mode 100644
index 0000000..d494ef4
--- /dev/null
+++ b/compiler/src/test/etch/constants/Constants.etch
@@ -0,0 +1,198 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.compiler.test
+
+service Constants
+{
+	// data types
+	
+	const boolean t1 = false
+	const byte t2 = 0
+	const short t3 = 0
+	const int t4 = 0
+	const long t5 = 0
+	const float t6 = 0
+	const double t7 = 0
+	const string t8 = ""
+	
+	// booleans
+	
+	const boolean t = true
+	const boolean f = false
+	
+	// integers
+	
+	const byte z = 0
+	const byte mz = -0
+	
+	const byte i1 = 1
+	const byte i10 = 10
+	const byte i100 = 100
+	const short i1000 = 1000
+	const short i10000 = 10000
+	const int i100000 = 100000
+	const int i1000000 = 1000000
+	const int i10000000 = 10000000
+	const int i100000000 = 100000000
+	const int i1000000000 = 1000000000
+	const long i10000000000 = 10000000000
+	const long i100000000000 = 100000000000
+	const long i1000000000000 = 1000000000000
+	const long i10000000000000 = 10000000000000
+	const long i100000000000000 = 100000000000000
+	const long i1000000000000000 = 1000000000000000
+	const long i10000000000000000 = 10000000000000000
+	const long i100000000000000000 = 100000000000000000
+	const long i1000000000000000000 = 1000000000000000000
+//	const long i10000000000000000000 = 10000000000000000000 // too big
+	
+	const byte mi1 = -1
+	const byte mi10 = -10
+	const byte mi100 = -100
+	const short mi1000 = -1000
+	const short mi10000 = -10000
+	const int mi100000 = -100000
+	const int mi1000000 = -1000000
+	const int mi10000000 = -10000000
+	const int mi100000000 = -100000000
+	const int mi1000000000 = -1000000000
+	const long mi10000000000 = -10000000000
+	const long mi100000000000 = -100000000000
+	const long mi1000000000000 = -1000000000000
+	const long mi10000000000000 = -10000000000000
+	const long mi100000000000000 = -100000000000000
+	const long mi1000000000000000 = -1000000000000000
+	const long mi10000000000000000 = -10000000000000000
+	const long mi100000000000000000 = -100000000000000000
+	const long mi1000000000000000000 = -1000000000000000000
+//	const long mi10000000000000000000 = -10000000000000000000 // too small
+	
+	// biggest and smallest
+	
+	const byte min_byte = -128
+	const byte max_byte = 127
+	
+	const short min_short = -32768
+	const short max_short = 32767
+	
+	const int min_int = -2147483648
+	const int max_int = 2147483647
+	
+	const long min_long = -9223372036854775808
+	const long max_long = 9223372036854775807
+	
+	const float min_float = 1.4e-45
+	const float max_float = 3.4028235e38
+	
+	const double min_double = 4.9e-324
+	const double max_double = 1.7976931348623157e308
+	
+	// binary
+	
+	//const int b0 = 0b0
+	//const int b0a = 0b00
+	//const int b1 = 0b1
+	//const int b1a = 0b01
+	//const int b2 = 0b10
+	//const int b3 = 0b11
+	
+	// octal
+	
+	const int o0 = 00
+	const int o1 = 01
+	const int o2 = 02
+	const int o3 = 03
+	const int o4 = 04
+	const int o5 = 05
+	const int o6 = 06
+	const int o7 = 07
+	const int o10 = 010
+	
+	// hex
+	
+	const int h0 = 0x0
+	const int h1 = 0x1
+	const int h2 = 0x2
+	const int h3 = 0x3
+	const int h4 = 0x4
+	const int h5 = 0x5
+	const int h6 = 0x6
+	const int h7 = 0x7
+	const int h8 = 0x8
+	const int h9 = 0x9
+	const int ha = 0xa
+	const int hb = 0xb
+	const int hc = 0xc
+	const int hd = 0xd
+	const int he = 0xe
+	const int hf = 0xf
+	const int h10 = 0x10
+	
+	// floating zeros
+	
+	const float f0a = 0
+	const float f0b = 0.
+	const float f0c = .0
+	const float f0d = 0.0
+	const float f0e = 0e0
+	
+	const float mf0a = -0
+	const float mf0b = -0.
+	const float mf0c = -.0
+	const float mf0d = -0.0
+	const float mf0e = -0e0
+	
+	// various floating non-zeros
+	
+	const float f1a = 1
+	const float f1b = 1.
+	const float f1c = .1
+	const float f1d = 1.1
+	const float f1e = 1e0
+	
+	const float mf1a = -1
+	const float mf1b = -1.
+	const float mf1c = -.1
+	const float mf1d = -1.1
+	const float mf1e = -1e0
+	
+	// floating big and small
+	
+	//const float fbig = 1234567890.0987654321e1234567890
+	//const float mfbig = -1234567890.0987654321e1234567890
+	//const float fsmall = 1234567890.0987654321e-1234567890
+	//const float mfsmall = -1234567890.0987654321e-1234567890
+	
+	// strings
+	
+	const string blank = ""
+	
+	const string s1 = "a"
+	const string s2 = "ab"
+	const string s3 = "abc"
+	const string s4 = "abcd"
+	const string s5 = "abcde"
+	
+	const string e1 = "\""
+	const string e2 = "\\"
+	const string e3 = "\t"
+	const string e4 = "\r"
+	const string e5 = "\n"
+	const string e6 = "\u0054his is a \u0074est of\u0020unicode escapes\u002e"
+	const string e7 = "\u00a1Use unicode escapes to \u201cquote\u201d things!"
+}
diff --git a/compiler/src/test/java/org/apache/etch/compiler/TestEtchMain.java b/compiler/src/test/java/org/apache/etch/compiler/TestEtchMain.java
new file mode 100644
index 0000000..4c2d890
--- /dev/null
+++ b/compiler/src/test/java/org/apache/etch/compiler/TestEtchMain.java
@@ -0,0 +1,344 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URL;
+
+import org.junit.Test;
+
+/**
+ * Test of EtchMain.
+ */
+public class TestEtchMain
+{
+	private final MyEtchMain prog = new MyEtchMain();
+	
+	private final static String T = "--testing";
+	
+	private final static String BINDING = "null";
+	
+	/** @throws Exception */
+	@Test
+	public void test1() throws Exception
+	{
+		// option -b not specified
+		prog.doMain( new String[] { T } );
+		assertEquals( 1, prog.code );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void test2() throws Exception
+	{
+		// missing value for option -b
+		prog.doMain( new String[] { T, "-b" } );
+		assertEquals( 1, prog.code );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void test3() throws Exception
+	{
+		// missing file name
+		prog.doMain( new String[] { T, "-b", "xxx" } );
+		assertEquals( 1, prog.code );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void test4() throws Exception
+	{
+		// binding name is bogus
+		prog.doMain( new String[] { T, "-b", "xxx", "yyy" } );
+		assertEquals( 3, prog.code );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void test5() throws Exception
+	{
+		// source file doesn't exist
+		prog.doMain( new String[] { T, "-b", BINDING, "yyy" } );
+		assertEquals( 3, prog.code );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void test6() throws Exception
+	{
+		// source file doesn't end in .etch
+		prog.doMain( new String[] { T, "-b", BINDING, findTestTxt() } );
+		assertEquals( 3, prog.code );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test7() throws Exception
+	{
+		// compilation should have worked.
+		prog.doMain( new String[] { T, "-b", BINDING, findTestEtch() } );
+		if (prog.code != 0)
+			System.out.println( "TestEtchMain.test7 msgs = "+
+				((ListLogHandler) prog.testingClo.lh).msgs );
+		assertEquals( 0, prog.code );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test8() throws Exception
+	{
+		// compilation should have worked.
+		prog.doMain( new String[] {} );
+		assertNull( prog.testingClo );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test9() throws Exception
+	{
+		// compilation should have worked.
+		prog.doMain( new String[] { T } );
+		assertFalse( prog.testingClo.ignoreGlobalWordsList );
+		assertFalse( prog.testingClo.ignoreLocalWordsList );
+		assertFalse( prog.testingClo.noMixinArtifacts );
+		assertFalse( prog.testingClo.noFlattenPackages );
+		assertFalse( prog.testingClo.quiet );
+		assertFalse( prog.testingClo.ignoreIncludePath );
+		assertTrue( prog.testingClo.testing );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test10() throws Exception
+	{
+		// compilation should have worked.
+		prog.doMain( new String[] { T, "-q" } );
+		assertFalse( prog.testingClo.ignoreGlobalWordsList );
+		assertFalse( prog.testingClo.ignoreLocalWordsList );
+		assertFalse( prog.testingClo.noMixinArtifacts );
+		assertFalse( prog.testingClo.noFlattenPackages );
+		assertTrue( prog.testingClo.quiet );
+		assertFalse( prog.testingClo.ignoreIncludePath );
+		assertTrue( prog.testingClo.testing );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test11() throws Exception
+	{
+		// compilation should have worked.
+		prog.doMain( new String[] { T, "--quiet" } );
+		assertFalse( prog.testingClo.ignoreGlobalWordsList );
+		assertFalse( prog.testingClo.ignoreLocalWordsList );
+		assertFalse( prog.testingClo.noMixinArtifacts );
+		assertFalse( prog.testingClo.noFlattenPackages );
+		assertTrue( prog.testingClo.quiet );
+		assertFalse( prog.testingClo.ignoreIncludePath );
+		assertTrue( prog.testingClo.testing );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test12() throws Exception
+	{
+		// compilation should have worked.
+		prog.doMain( new String[] { T, "-g" } );
+		assertTrue( prog.testingClo.ignoreGlobalWordsList );
+		assertFalse( prog.testingClo.ignoreLocalWordsList );
+		assertFalse( prog.testingClo.noMixinArtifacts );
+		assertFalse( prog.testingClo.noFlattenPackages );
+		assertFalse( prog.testingClo.quiet );
+		assertFalse( prog.testingClo.ignoreIncludePath );
+		assertTrue( prog.testingClo.testing );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test13() throws Exception
+	{
+		// compilation should have worked.
+		prog.doMain( new String[] { T, "--ignore-global-words-list" } );
+		assertTrue( prog.testingClo.ignoreGlobalWordsList );
+		assertFalse( prog.testingClo.ignoreLocalWordsList );
+		assertFalse( prog.testingClo.noMixinArtifacts );
+		assertFalse( prog.testingClo.noFlattenPackages );
+		assertFalse( prog.testingClo.quiet );
+		assertFalse( prog.testingClo.ignoreIncludePath );
+		assertTrue( prog.testingClo.testing );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test14() throws Exception
+	{
+		// compilation should have worked.
+		prog.doMain( new String[] { T, "-l" } );
+		assertFalse( prog.testingClo.ignoreGlobalWordsList );
+		assertTrue( prog.testingClo.ignoreLocalWordsList );
+		assertFalse( prog.testingClo.noMixinArtifacts );
+		assertFalse( prog.testingClo.noFlattenPackages );
+		assertFalse( prog.testingClo.quiet );
+		assertFalse( prog.testingClo.ignoreIncludePath );
+		assertTrue( prog.testingClo.testing );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test15() throws Exception
+	{
+		// compilation should have worked.
+		prog.doMain( new String[] { T, "--ignore-local-words-list" } );
+		assertFalse( prog.testingClo.ignoreGlobalWordsList );
+		assertTrue( prog.testingClo.ignoreLocalWordsList );
+		assertFalse( prog.testingClo.noMixinArtifacts );
+		assertFalse( prog.testingClo.noFlattenPackages );
+		assertFalse( prog.testingClo.quiet );
+		assertFalse( prog.testingClo.ignoreIncludePath );
+		assertTrue( prog.testingClo.testing );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test16() throws Exception
+	{
+		// compilation should have worked.
+		prog.doMain( new String[] { T, "-i" } );
+		assertFalse( prog.testingClo.ignoreGlobalWordsList );
+		assertFalse( prog.testingClo.ignoreLocalWordsList );
+		assertFalse( prog.testingClo.noMixinArtifacts );
+		assertFalse( prog.testingClo.noFlattenPackages );
+		assertFalse( prog.testingClo.quiet );
+		assertTrue( prog.testingClo.ignoreIncludePath );
+		assertTrue( prog.testingClo.testing );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test17() throws Exception
+	{
+		// compilation should have worked.
+		prog.doMain( new String[] { T, "--ignore-include-path" } );
+		assertFalse( prog.testingClo.ignoreGlobalWordsList );
+		assertFalse( prog.testingClo.ignoreLocalWordsList );
+		assertFalse( prog.testingClo.noMixinArtifacts );
+		assertFalse( prog.testingClo.noFlattenPackages );
+		assertFalse( prog.testingClo.quiet );
+		assertTrue( prog.testingClo.ignoreIncludePath );
+		assertTrue( prog.testingClo.testing );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test18() throws Exception
+	{
+		// compilation should have worked.
+		prog.doMain( new String[] { T, "-n" } );
+		assertFalse( prog.testingClo.ignoreGlobalWordsList );
+		assertFalse( prog.testingClo.ignoreLocalWordsList );
+		assertTrue( prog.testingClo.noMixinArtifacts );
+		assertFalse( prog.testingClo.noFlattenPackages );
+		assertFalse( prog.testingClo.quiet );
+		assertFalse( prog.testingClo.ignoreIncludePath );
+		assertTrue( prog.testingClo.testing );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test19() throws Exception
+	{
+		// compilation should have worked.
+		prog.doMain( new String[] { T, "--no-mixin-artifacts" } );
+		assertFalse( prog.testingClo.ignoreGlobalWordsList );
+		assertFalse( prog.testingClo.ignoreLocalWordsList );
+		assertTrue( prog.testingClo.noMixinArtifacts );
+		assertFalse( prog.testingClo.noFlattenPackages );
+		assertFalse( prog.testingClo.quiet );
+		assertFalse( prog.testingClo.ignoreIncludePath );
+		assertTrue( prog.testingClo.testing );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test20() throws Exception
+	{
+		// compilation should have worked.
+		prog.doMain( new String[] { T, "-f" } );
+		assertFalse( prog.testingClo.ignoreGlobalWordsList );
+		assertFalse( prog.testingClo.ignoreLocalWordsList );
+		assertFalse( prog.testingClo.noMixinArtifacts );
+		assertTrue( prog.testingClo.noFlattenPackages );
+		assertFalse( prog.testingClo.quiet );
+		assertFalse( prog.testingClo.ignoreIncludePath );
+		assertTrue( prog.testingClo.testing );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test21() throws Exception
+	{
+		// compilation should have worked.
+		prog.doMain( new String[] { T, "--no-flatten-packages" } );
+		assertFalse( prog.testingClo.ignoreGlobalWordsList );
+		assertFalse( prog.testingClo.ignoreLocalWordsList );
+		assertFalse( prog.testingClo.noMixinArtifacts );
+		assertTrue( prog.testingClo.noFlattenPackages );
+		assertFalse( prog.testingClo.quiet );
+		assertFalse( prog.testingClo.ignoreIncludePath );
+		assertTrue( prog.testingClo.testing );
+	}
+	
+	private String findTestTxt() throws Exception
+	{
+		return findFile( "test.txt" );
+	}
+	
+	private String findTestEtch() throws Exception
+	{
+		return findFile( "test.etch" );
+	}
+	
+	private String findFile( String fn ) throws Exception
+	{
+		URL u = getClass().getResource( fn );
+		File f = new File( new URI( u.toString() ) );
+		return f.getAbsolutePath();
+	}
+
+	private static class MyEtchMain extends EtchMain
+	{
+		@Override
+		public void exit( int code, String source, String reason,
+			boolean emergency )
+		{
+			this.code = code;
+		}
+		
+		/** the exit code */
+		public int code;
+	}
+}
diff --git a/compiler/src/test/java/org/apache/etch/compiler/TestMapWords.java b/compiler/src/test/java/org/apache/etch/compiler/TestMapWords.java
new file mode 100644
index 0000000..8c16777
--- /dev/null
+++ b/compiler/src/test/java/org/apache/etch/compiler/TestMapWords.java
@@ -0,0 +1,434 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.compiler;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.compiler.ast.Message;
+import org.apache.etch.compiler.ast.Module;
+import org.apache.etch.compiler.ast.Named;
+import org.apache.etch.compiler.ast.ParamList;
+import org.apache.etch.compiler.ast.Service;
+import org.apache.etch.compiler.ast.TypeRef;
+import org.junit.Before;
+import org.junit.Test;
+
+
+/**
+ * UnitTest for the mapWords(String, Map<String, String>) method in Backend.
+ * These tests rely on mapWordsTestFileOne and mapWordsTestFileTwo being in the
+ * same directory as this file for testing.  Testing includes parsing these
+ * files, checking recovery from bad syntax and expected results from succesful
+ * parsing.
+ */
+public class TestMapWords
+{
+	/**
+	 * A concrete implementation of Backend.  The only function you may assume
+	 * works is mapWords(String, Map<String, String>.
+	 */
+	private class WordMapper extends Backend
+	{
+		/**
+		 *
+		 * @throws Exception
+		 */
+		public WordMapper()
+			throws Exception
+		{
+			// nothing to do.
+		}
+
+		@Override
+		public String asyncReceiverPoolName( Message msg )
+		{
+			return null;
+		}
+
+		@Override
+		public String enum_efqname( String fqname, String moduleName,
+			String serviceName, String enumName )
+		{
+			// Not needed for testing
+			return null;
+		}
+
+		@Override
+		public String except_efqname( String fqname, String moduleName,
+			String serviceName, String enumName )
+		{
+			// Not needed for testing
+			return null;
+		}
+
+		@Override
+		public String formatString( ParamList<Service> n, boolean isExcept )
+			throws ParseException, IOException
+		{
+			// Not needed for testing
+			return null;
+		}
+
+		@Override
+		public void generate( Module module, CmdLineOptions options )
+			throws Exception
+		{
+			// Not needed for testing
+		}
+
+		@Override
+		public String getLang()
+		{
+			// Not needed for testing
+			return null;
+		}
+
+		@Override
+		public String getNativeTypeName( TypeRef type )
+		{
+			// Not needed for testing
+			return null;
+		}
+
+		@Override
+		public String getTypeName( TypeRef type )
+		{
+			// Not needed for testing
+			return null;
+		}
+
+		@Override
+		public String getTypeValue( TypeRef type, Token value )
+			throws IOException
+		{
+			// Not needed for testing
+			return null;
+		}
+
+		@Override
+		public String getValidator( Named<?> named )
+		{
+			// Not needed for testing
+			return null;
+		}
+
+		@Override
+		public String mfvname( String vname )
+		{
+			// Not needed for testing
+			return null;
+		}
+
+		@Override
+		public String mtvname( String vname )
+		{
+			// Not needed for testing
+			return null;
+		}
+
+		@Override
+		public String qualifyConstantName( Service intf, Token name )
+		{
+			// Not needed for testing
+			return null;
+		}
+
+		@Override
+		public String qualifyEnumName( Service intf, Token name )
+		{
+			// Not needed for testing
+			return null;
+		}
+
+		@Override
+		public String qualifyParameterName( Token name )
+		{
+			// Not needed for testing
+			return null;
+		}
+
+		@Override
+		public String struct_efqname( String fqname, String moduleName,
+			String serviceName, String enumName )
+		{
+			// Not needed for testing
+			return null;
+		}
+
+		@Override
+		public void mapWords(String fileName, Map<String, String> wordMap)
+			throws IOException, FileNotFoundException
+		{
+			super.mapWords(fileName, wordMap);
+		}
+
+		@Override
+		public void addDefaults( Service service ) throws ParseException
+		{
+			// Not needed for testing
+		}
+	}
+
+
+	private static final String tmpPath1 = "org/apache/etch/compiler/";
+	private static final String tmpPath2 = null;
+	private static final String tmpPath3 = "resources/org/apache/etch/compiler/";
+	private static final String[] path = {tmpPath1, tmpPath2, tmpPath3};
+
+	private static final String firstFile = "mapWordsTestFileOne.kwd";
+	private static final String secondFile = "mapWordsTestFileTwo.kwd";
+
+	private static Map<String, String> myMap;
+	private static WordMapper myMapper;
+
+	private static Map<String, String> firstMapping;
+	private static Map<String, String> firstSecondMapping;
+
+
+	/**
+	 * Reinitialize baseline before each test.  To be safe.
+	 *
+	 * @throws Exception
+	 */
+	@Before
+	public void startUp()
+		throws Exception
+	{
+		myMap = new HashMap<String, String>();
+
+		myMapper = new WordMapper();
+		myMapper.mapWords(getPath(path, firstFile), myMap);
+
+		firstMapping = new HashMap<String, String>();
+		firstSecondMapping = new HashMap<String, String>();
+
+		// The results of parsing the firstFile into a new map
+		for (int i = 1; i < 5; ++i)
+			firstMapping.put("key" + Integer.toString(i), "xkey" + Integer.toString(i));
+		for (int i = 5; i < 16; ++i)
+			firstMapping.put("key" + Integer.toString(i), "value" + Integer.toString(i));
+		firstMapping.put("key16", "value17");
+		firstMapping.put("key17", "value17");
+		firstMapping.put("key18", "xkey18");
+		firstMapping.put("Key19", "XKey19");
+		firstMapping.put("KEY20", "XKEY20");
+		firstMapping.put("kEy21", "xkEy21");
+
+		// The results of parsing the firstFile into a new map, and then parsing
+		// the secondFile into the same map
+		firstSecondMapping.putAll(firstMapping);
+		firstSecondMapping.put("key1", "foo");
+		firstSecondMapping.put("key5", "xkey5");
+		firstSecondMapping.put("Key19", "bar");
+		firstSecondMapping.put("KEY20", "KEY20");
+		firstSecondMapping.put("key22", "xkey22");
+		firstSecondMapping.put("key23", "value23");
+	}
+
+
+	/**
+	 * Basic test to ensure files can be parsed without comments, whitespace or
+	 * bad syntax crashing the function.
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void simpleParse()
+		throws Exception
+	{
+		assertEquals(firstMapping.size(), myMap.size());
+	}
+
+	/**
+	 * Overall test to see if the first file parsed with expected results.
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void expectedResults()
+		throws Exception
+	{
+		assertEquals(firstMapping, myMap);
+	}
+
+	/**
+	 * Assert comments trailing mappings aren't parsed.
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void trailingComments()
+		throws Exception
+	{
+		// comments after implicit mappings
+		assertEquals(firstMapping.get("key1"), myMap.get("key1"));
+		assertEquals(firstMapping.get("key2"), myMap.get("key2"));
+		assertEquals(firstMapping.get("key3"), myMap.get("key3"));
+		assertEquals(firstMapping.get("key4"), myMap.get("key4"));
+
+		// comments after explicit mappings
+		assertEquals(firstMapping.get("key6"), myMap.get("key6"));
+		assertEquals(firstMapping.get("key7"), myMap.get("key7"));
+		assertEquals(firstMapping.get("key8"), myMap.get("key8"));
+		assertEquals(firstMapping.get("key10"), myMap.get("key10"));
+		assertEquals(firstMapping.get("key11"), myMap.get("key11"));
+		assertEquals(firstMapping.get("key13"), myMap.get("key13"));
+		assertEquals(firstMapping.get("key14"), myMap.get("key14"));
+		assertEquals(firstMapping.get("key15"), myMap.get("key15"));
+	}
+
+	/**
+	 * Assert explicit mappings work.
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void explicitMappings()
+		throws Exception
+	{
+		assertEquals(firstMapping.get("key5"), myMap.get("key5"));
+		assertEquals(firstMapping.get("key6"), myMap.get("key6"));
+		assertEquals(firstMapping.get("key7"), myMap.get("key7"));
+		assertEquals(firstMapping.get("key8"), myMap.get("key8"));
+		assertEquals(firstMapping.get("key9"), myMap.get("key9"));
+		assertEquals(firstMapping.get("key10"), myMap.get("key10"));
+		assertEquals(firstMapping.get("key11"), myMap.get("key11"));
+		assertEquals(firstMapping.get("key12"), myMap.get("key12"));
+		assertEquals(firstMapping.get("key13"), myMap.get("key13"));
+		assertEquals(firstMapping.get("key14"), myMap.get("key14"));
+		assertEquals(firstMapping.get("key15"), myMap.get("key15"));
+	}
+
+	/**
+	 * Assert implicit mappings work.
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void implicitMappings()
+		throws Exception
+	{
+		assertEquals(firstMapping.get("key1"), myMap.get("key1"));
+		assertEquals(firstMapping.get("key2"), myMap.get("key2"));
+		assertEquals(firstMapping.get("key3"), myMap.get("key3"));
+		assertEquals(firstMapping.get("key4"), myMap.get("key4"));
+		assertEquals(firstMapping.get("key18"), myMap.get("key18"));
+		assertEquals(firstMapping.get("key19"), myMap.get("key19"));
+		assertEquals(firstMapping.get("key20"), myMap.get("key20"));
+		assertEquals(firstMapping.get("key21"), myMap.get("key21"));
+	}
+
+	/**
+	 * Assert repeated mappings overwrite.
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void overwrittenMappings()
+		throws Exception
+	{
+		assertEquals(firstMapping.get("key16"), myMap.get("key16"));
+		assertEquals(firstMapping.get("key17"), myMap.get("key17"));
+		assertEquals(firstMapping.get("key18"), myMap.get("key18"));
+	}
+
+	/**
+	 * Assert implicit mappings have an uppercase 'x' where appropriate.
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void upcasing()
+		throws Exception
+	{
+		assertEquals(firstMapping.get("key19"), myMap.get("key19"));
+		assertEquals(firstMapping.get("key20"), myMap.get("key20"));
+		assertEquals(firstMapping.get("key21"), myMap.get("key21"));
+	}
+
+	/**
+	 * Assert that repeated mappings cause change when mapping a second file.
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void twoParsings()
+		throws Exception
+	{
+		assertEquals(firstMapping, myMap);
+		myMapper.mapWords(getPath(path, secondFile), myMap);
+		assertEquals(firstSecondMapping, myMap);
+	}
+
+	/**
+	 * Assert that repeated mappings change the mappings they should
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void multiParsings()
+		throws Exception
+	{
+		assertEquals(firstMapping, myMap);
+		myMapper.mapWords(getPath(path, secondFile), myMap);
+		assertEquals(firstSecondMapping, myMap);
+		myMapper.mapWords(getPath(path, firstFile), myMap);
+
+		// Add the new parsings and re-check
+		firstMapping.put("key22", "xkey22");
+		firstMapping.put("key23", "value23");
+		assertEquals(firstMapping.size(), myMap.size());
+		assertEquals(firstMapping, myMap);
+	}
+
+	// -------
+	// Helpers
+	// -------
+
+	/**
+	 * Returns the correct path to a resource.
+	 * @param path the paths to try for opening the resources
+	 * @param fn the file name of the file to open
+	 * @return the correct path to a resource
+	 */
+	private static String getPath(String[] path, String fn)
+		throws FileNotFoundException
+	{
+		for (String p: path)
+		{
+			if (p == null)
+				continue;
+			
+			String s = p + fn;
+			
+			URL temp = ClassLoader.getSystemResource(s);
+			if (temp != null)
+					return s;
+		}
+		throw new FileNotFoundException(fn);
+	}
+}
diff --git a/compiler/src/test/resources/org/apache/etch/compiler/mapWordsTestFileOne.kwd b/compiler/src/test/resources/org/apache/etch/compiler/mapWordsTestFileOne.kwd
new file mode 100644
index 0000000..a38ba31
--- /dev/null
+++ b/compiler/src/test/resources/org/apache/etch/compiler/mapWordsTestFileOne.kwd
@@ -0,0 +1,44 @@
+# $Id$
+# 
+# Copyright 2007-2008 Cisco Systems Inc.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy
+# of the License at
+#  
+#     http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+# Whitespace betwixt comments
+key1
+key2#Comment following directly after a key
+key3 # Simple Comment
+key4  # Multi space comment
+
+key5 = value5
+key6 = value6#Comment following directly after a value
+key7 = value7 # Simple Comment
+key8 = value8  # Multi space comment
+key9=value9
+key10=value10#Comment following directly after a non-spaced value
+key11=value11 # Simple Comment
+key12 value12
+key13 value13#Comment following directly after a value
+key14 value14 # Simple Comment
+key15 value15  # Multi space comment
+
+key16 value16
+key16 value17
+key17
+key17 value17
+key18 value18
+key18
+
+Key19
+KEY20
+kEy21
\ No newline at end of file
diff --git a/compiler/src/test/resources/org/apache/etch/compiler/mapWordsTestFileTwo.kwd b/compiler/src/test/resources/org/apache/etch/compiler/mapWordsTestFileTwo.kwd
new file mode 100644
index 0000000..35634ee
--- /dev/null
+++ b/compiler/src/test/resources/org/apache/etch/compiler/mapWordsTestFileTwo.kwd
@@ -0,0 +1,22 @@
+# $Id$
+# 
+# Copyright 2007-2008 Cisco Systems Inc.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy
+# of the License at
+#  
+#     http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+key1 = foo
+key5
+Key19 = bar
+KEY20 																	KEY20
+key22
+key23 = value23
\ No newline at end of file
diff --git a/compiler/src/test/resources/org/apache/etch/compiler/test.etch b/compiler/src/test/resources/org/apache/etch/compiler/test.etch
new file mode 100644
index 0000000..8e13458
--- /dev/null
+++ b/compiler/src/test/resources/org/apache/etch/compiler/test.etch
@@ -0,0 +1,24 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one   *
+ *  or more contributor license agreements.  See the NOTICE file *
+ *  distributed with this work for additional information        *
+ *  regarding copyright ownership.  The ASF licenses this file   *
+ *  to you under the Apache License, Version 2.0 (the            *
+ *  "License"); you may not use this file except in compliance   *
+ *  with the License.  You may obtain a copy of the License at   *
+ *                                                               *
+ *    http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                               *
+ *  Unless required by applicable law or agreed to in writing,   *
+ *  software distributed under the License is distributed on an  *
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ *  KIND, either express or implied.  See the License for the    *
+ *  specific language governing permissions and limitations      *
+ *  under the License.                                           *
+ */
+module foo
+
+service Foo
+{
+	void helloWorld( string msg )
+}
diff --git a/compiler/src/test/resources/org/apache/etch/compiler/test.txt b/compiler/src/test/resources/org/apache/etch/compiler/test.txt
new file mode 100644
index 0000000..1e03f63
--- /dev/null
+++ b/compiler/src/test/resources/org/apache/etch/compiler/test.txt
@@ -0,0 +1 @@
+file used to test the compiler.
\ No newline at end of file
diff --git a/etch.properties b/etch.properties
new file mode 100644
index 0000000..26355ec
--- /dev/null
+++ b/etch.properties
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one   *
+# or more contributor license agreements.  See the NOTICE file *
+# distributed with this work for additional information        *
+# regarding copyright ownership.  The ASF licenses this file   *
+# to you under the Apache License, Version 2.0 (the            *
+# "License"); you may not use this file except in compliance   *
+# with the License.  You may obtain a copy of the License at   *
+#                                                              *
+#   http://www.apache.org/licenses/LICENSE-2.0                 *
+#                                                              *
+# Unless required by applicable law or agreed to in writing,   *
+# software distributed under the License is distributed on an  *
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+# KIND, either express or implied.  See the License for the    *
+# specific language governing permissions and limitations      *
+# under the License.                                           *
+majorVersion=1
+minorVersion=1
+patchVersion=0
+suffix=-incubating
diff --git a/examples/build.xml b/examples/build.xml
new file mode 100644
index 0000000..8b1912f
--- /dev/null
+++ b/examples/build.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-examples" basedir="." default="help">
+    <description>Etch Examples</description>
+    <property name="Etch.basedir" location="${basedir}/.." />
+    <import file="${Etch.basedir}/build-support/etch.includes.xml" />
+
+    <property name="target" location="${basedir}/target" />
+    
+    <target name="do-clean">
+        <build_example dir="chat" logdir="${basedir}/target/logs" />
+        <build_example dir="distmap" logdir="${basedir}/target/logs" />
+        <build_example dir="example" logdir="${basedir}/target/logs" />
+        <build_example dir="perf" logdir="${basedir}/target/logs" />
+        <delete dir="${target}" failonerror="false" quiet="true" />
+    </target>
+    
+    <target name="do-init">
+        <delete dir="${target}" failonerror="false" quiet="true" />
+        <mkdir dir="${target}" />
+    </target>
+    
+    <target name="do-build">
+        <build_example dir="chat" logdir="${basedir}/target/logs" />
+        <build_example dir="distmap" logdir="${basedir}/target/logs" />
+        <build_example dir="example" logdir="${basedir}/target/logs" />
+        <build_example dir="perf" logdir="${basedir}/target/logs" />
+    </target>
+    
+    <target name="do-postbuild">
+    </target>
+    
+    <target name="do-help">
+    </target>
+
+</project>
diff --git a/examples/chat/README.txt b/examples/chat/README.txt
new file mode 100644
index 0000000..99f4b25
--- /dev/null
+++ b/examples/chat/README.txt
@@ -0,0 +1,33 @@
+To get started with the example you will need jdk 1.5.0_x,
+where x is pretty recent (>= 15), or any release of jdk 1.6.
+You will also need ant 1.7.0, with ant .net plugin if you
+want to build csharp. You will also need microsoft .net
+sdk 2.0 for csharp builds.
+
+To build:
+
+> ant
+
+This will run the default target which will build both java
+and csharp programs. You can also use build-java or build-csharp
+targets to build only java or only csharp.
+
+To run java chat, open a cmd window and run these commands:
+
+> cd target\bin
+> start java -cp chat.jar etch.examples.chat.MainChatListener
+> start java -cp chat.jar etch.examples.chat.MainChatClient
+> start java -cp chat.jar etch.examples.chat.MainChatClient
+
+Two chat clients will be started; there is a help command;
+login as a different user in each with any password; they
+can chat with each other!
+
+To run csharp chat:
+
+> cd target\bin
+> start ChatListener.exe
+> start ChatClient.exe
+> start ChatClient.exe
+
+You can mix and match the various clients and listeners.
diff --git a/examples/chat/build.xml b/examples/chat/build.xml
new file mode 100644
index 0000000..da6d1e6
--- /dev/null
+++ b/examples/chat/build.xml
@@ -0,0 +1,327 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-chat-example" basedir="." default="help" >
+    <description>Chat Example</description>
+    <property name="Etch.basedir" location="${basedir}/../.." />
+    <import file="${Etch.basedir}/build-support/etch.includes.xml" />
+
+    <!-- TODO better computation of etch.home, etch.version -->
+    <property environment="env" />
+
+    <!-- compute ETCH_HOME -->
+    <property name="build.ETCH_HOME" location="${basedir}/../../target/Installers/dist" />
+    <condition property="etch.home" value="${env.ETCH_HOME}" >
+        <isset property="${env.ETCH_HOME}" />
+    </condition>
+    <condition property="etch.home" value="${build.ETCH_HOME}" >
+        <not><isset property="etch.home" /></not>
+    </condition>
+
+    <property name="Etch.dependency.junit.jar"
+        location="${default.junit.lib}/junit-4.3.1.jar" />
+
+    <property name="Etch.buildSupportDirectory" location="../../build-support" />
+
+    <!-- compute etch.version -->
+    <condition property="etch.version" value="${Etch.version}" >
+        <not><isset property="etch.version" /></not>
+    </condition>
+
+    <!-- Csharp Support -->
+    <condition property="USE.dotnet" >
+        <and>
+            <os family="windows" />
+            <available file="${env.windir}/Microsoft.NET/Framework/v2.0.50727/msbuild.exe" />
+        </and>
+    </condition>
+    <condition property="USE.mono" >
+        <and>
+            <not><os family="windows" /></not>
+            <!-- TODO mono support is not fully baked, use -DUSE.mono to test -->
+            <!-- <available file="${env.MONO_HOME}/bin/mdtool" /> -->
+            <isset property="USE.mono" />
+        </and>
+    </condition>
+    <condition property="BUILD.csharp" >
+        <or>
+            <isset property="USE.dotnet" />
+            <isset property="USE.mono" />
+        </or>
+    </condition>
+
+    <!-- import etch task -->
+    <taskdef
+        onerror="report"
+        resource="org/apache/etch/tools/ant/etch.xml"
+        classpath="${etch.home}/lib/etch-ant-plugin-${etch.version}.jar" />
+
+    <!-- import dotnet task -->
+    <condition property="ant.dotnet.jar" value="ant-dotnet-1.0.jar" >
+        <not><isset property="ant.dotnet.jar" /></not>
+    </condition>
+
+    <taskdef
+        onerror="report"
+        resource="org/apache/ant/dotnet/antlib.xml"
+        classpath="${ant.dotnet.jar}" />
+
+    <macrodef name="mdtool" >
+        <attribute name="dir"         default="." />
+        <attribute name="failonerror" default="false" />
+        <attribute name="project"     default="project.csproj" />
+        <attribute name="target"      default="${build.target}" />
+        <sequential>
+            <exec executable="${env.MONO_HOME}/bin/mdtool" dir="@{dir}" failonerror="@{failonerror}" >
+                <arg value="build" />
+                <arg value="--buildfile:@{project}" />
+            </exec>
+        </sequential>
+    </macrodef>
+
+    <!-- set properties -->
+    <property name="src"               location="${basedir}/src" />
+    <property name="main-src-java"     location="${src}/main/java" />
+    <property name="test-src-java"     location="${src}/test/java" />
+    <property name="target"            location="${basedir}/target" />
+    <property name="dist-src"          location="${target}/dist-src" />
+    <property name="generated-sources" location="${target}/generated-sources" />
+    <property name="gen-src-java"      location="${generated-sources}/main/etch/java" />
+    <property name="gen-src-csharp"    location="${generated-sources}/main/etch/csharp" />
+    <property name="bin"               location="${target}/bin" />
+    <property name="classes"           location="${target}/classes" />
+    <property name="classes-test"      location="${target}/classes-test" />
+    <property name="test-results"      location="${target}/test-results" />
+    <property name="nunit-results"     location="${target}/nunit-results" />
+    <property name="dist"              location="${basedir}/../../target/Installers/dist" />
+
+    <!-- initialize -->
+    <target name="init" >
+        <mkdir dir="${target}" />
+        <mkdir dir="${dist-src}" />
+        <mkdir dir="${generated-sources}" />
+        <mkdir dir="${gen-src-java}" />
+        <mkdir dir="${gen-src-csharp}" />
+        <mkdir dir="${bin}" />
+        <mkdir dir="${classes}" />
+        <mkdir dir="${classes-test}" />
+        <mkdir dir="${test-results}" />
+        <mkdir dir="${nunit-results}" />
+    </target>
+
+    <!-- build the server -->
+    <target name="generate-sources" depends="init" >
+        <!-- generate sources -->
+
+        <etch home="${etch.home}"
+              file="${src}/main/etch/Chat.etch"
+              binding="java"
+              outputDir="${gen-src-java}" />
+
+        <etch home="${etch.home}"
+              file="${src}/main/etch/Chat.etch"
+              binding="csharp"
+              outputDir="${gen-src-csharp}" />
+    </target>
+
+    <property name="etch-java-runtime-name"
+        value="etch-java-runtime-${etch.version}.jar" />
+
+    <property name="Etch.dependency.java.runtime"
+        location="${etch.home}/lib/${etch-java-runtime-name}" />
+
+    <target name="build-java" depends="generate-sources" >
+        <!-- compile sources -->
+
+        <javac target="1.5" destdir="${classes}" >
+            <src path="${gen-src-java}" />
+            <src path="${main-src-java}" />
+            <classpath>
+                <pathelement location="${Etch.dependency.java.runtime}" />
+            </classpath>
+        </javac>
+
+        <javac target="1.5" destdir="${classes-test}" >
+            <src path="${gen-src-java}" />
+            <src path="${main-src-java}" />
+            <src path="${test-src-java}" />
+            <classpath>
+                <pathelement location="${Etch.dependency.java.runtime}" />
+                <pathelement location="${Etch.dependency.junit.jar}" />
+            </classpath>
+        </javac>
+
+        <!-- Create Jar -->
+        <jar jarfile="${bin}/chat.jar" >
+            <manifest>
+                <attribute name="Class-Path" value="${etch-java-runtime-name}" />
+            </manifest>
+            <fileset dir="${classes}" >
+                <include name="**/*" />
+            </fileset>
+        </jar>
+
+        <!-- copy in dependencies -->
+        <copy todir="${bin}" file="${Etch.dependency.java.runtime}" />
+    </target>
+
+    <target name="build-csharp-with-mono" depends="generate-sources" if="USE.mono" >
+        <mdtool dir="${src}/main/csharp/ChatClientProj" project="ChatClientProj.csproj" />
+        <mdtool dir="${src}/main/csharp/ChatListenerProj" project="ChatListenerProj.csproj" />
+    </target>
+
+    <target name="build-csharp-with-dotnet" depends="generate-sources" if="USE.dotnet" >
+        <msbuild buildfile="${src}/main/csharp/ChatListenerProj/ChatListenerProj.csproj" >
+            <property name="Configuration" value="${build.target}" />
+        </msbuild>
+        <msbuild buildfile="${src}/main/csharp/ChatClientProj/ChatClientProj.csproj" >
+            <property name="Configuration" value="${build.target}" />
+        </msbuild>
+        <msbuild buildfile="${src}/test/csharp/ChatTestProj/ChatTestProj.csproj" >
+            <property name="Configuration" value="${build.target}" />
+        </msbuild>
+        <copy todir="${bin}" >
+            <fileset dir="${src}/main/csharp/ChatListenerProj/bin/${build.target}" >
+                <include name="*" />
+            </fileset>
+            <fileset dir="${src}/main/csharp/ChatClientProj/bin/${build.target}" >
+                <include name="*" />
+            </fileset>
+        </copy>
+    </target>
+
+    <target name="build-csharp" depends="build-csharp-with-mono,build-csharp-with-dotnet" />
+
+    <target name="build" depends="build-java,build-csharp" />
+
+    <!-- run unit tests -->
+
+    <target name="test-java" depends="build-java" >
+        <!-- Run Unit Tests -->
+        <junit printsummary="yes" haltonfailure="no" dir="${classes-test}"
+            errorProperty="build.tests.fail" failureProperty="build.tests.fail" >
+            <classpath>
+                <pathelement location="${classes-test}" />
+                <pathelement location="${Etch.dependency.java.runtime}" />
+                <pathelement location="${Etch.dependency.junit.jar}" />
+            </classpath>
+            <formatter type="xml" />
+            <batchtest fork="true" todir="${test-results}" >
+                <fileset dir="${test-src-java}" >
+                    <include name="**/Test*.java" />
+                </fileset>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="test-csharp" depends="build-csharp" if="BUILD.csharp" >
+         <nunit xmlout="${nunit-results}/NUnitResults.xml" >
+             <testassembly name="${src}/test/csharp/ChatTestProj/bin/${build.target}/ChatTestProj.dll" />
+         </nunit>
+
+         <xslt style="${Etch.buildSupportDirectory}/NUnitToJUnit.xsl"
+                 in="${nunit-results}/NUnitResults.xml" out="${test-results}/TEST-NUnitResults.xml" />
+   </target>
+
+    <target name="test" depends="build,test-java,test-csharp,done" >
+    </target>
+
+    <target name="done" depends="build" >
+        <echo>
+
+Build Complete!
+
+To run java chat, open a cmd window and run these commands:
+
+> cd target\bin
+> start java -cp chat.jar org.apache.etch.examples.chat.MainChatListener
+> start java -cp chat.jar org.apache.etch.examples.chat.MainChatClient
+> start java -cp chat.jar org.apache.etch.examples.chat.MainChatClient
+
+Two chat clients will be started; there is a help command;
+login as a different user in each with any password; they
+can chat with each other!
+
+To run csharp chat:
+
+> cd target\bin
+> start ChatListener.exe
+> start ChatClient.exe
+> start ChatClient.exe
+
+You can mix and match the various clients and listeners.
+
+        </echo>
+    </target>
+
+    <!-- build everything -->
+    <target name="init-debug" >
+        <property name="build.target" value="Debug" />
+    </target>
+
+    <target name="init-release" >
+        <property name="build.target" value="Release" />
+    </target>
+
+    <target name="dist-src" >
+        <copy file="dist-build.xml" tofile="${dist-src}/build.xml" overwrite="true" >
+            <filterset refid="Etch.buildTokens" />
+        </copy>    
+        <copy file="README.txt" tofile="${dist-src}/README.txt" overwrite="true" />
+        
+        <copy todir="${dist-src}/src/main/etch" overwrite="true" >
+            <fileset dir="${src}/main/etch" >
+                <exclude name="**/.svn/**" />
+                <include name="**/*.etch" />
+            </fileset>
+        </copy>
+        
+        <copy todir="${dist-src}/src/main/java" overwrite="true" >
+            <fileset dir="${src}/main/java" >
+                <exclude name="**/.svn/**" />
+                <include name="**/*.java" />
+            </fileset>
+        </copy>
+        
+        <copy todir="${dist-src}/src/main/csharp" overwrite="true" >
+            <fileset dir="${src}/main/csharp" >
+                <exclude name="**/.svn/**" />
+                <include name="**/*.cs" />
+            </fileset>
+        </copy>
+        
+        <copy todir="${dist}/examples/chat" overwrite="true" >
+            <fileset dir="${dist-src}" />
+        </copy>
+    </target>
+
+    <target name="debug" depends="dist-src,init-debug,test" />
+    <target name="release" depends="dist-src,init-release,test" />
+
+    <!-- clean -->
+    <target name="clean" >
+        <delete dir="${target}" quiet="true" />
+        <delete dir="${src}/main/csharp/ChatClientProj/bin" quiet="true" />
+        <delete dir="${src}/main/csharp/ChatClientProj/obj" quiet="true" />
+        <delete dir="${src}/main/csharp/ChatListenerProj/bin" quiet="true" />
+        <delete dir="${src}/main/csharp/ChatListenerProj/obj" quiet="true" />
+        <delete dir="${src}/test/csharp/ChatTestProj/bin" quiet="true" />
+        <delete dir="${src}/test/csharp/ChatTestProj/obj" quiet="true" />
+    </target>
+</project>
diff --git a/examples/chat/dist-build.xml b/examples/chat/dist-build.xml
new file mode 100644
index 0000000..8b651a3
--- /dev/null
+++ b/examples/chat/dist-build.xml
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-chat-example" basedir="." default="build">
+    <description>Chat Example</description>
+
+    <property name="etch.home" location="${basedir}/../.."/>
+    <property name="etch.version" value="@EtchVersion@"/>
+    <property name="etch-java-runtime-name" value="etch-java-runtime-${etch.version}.jar"/>
+
+    <property name="etch-ant-plugin.jar"   location="${etch.home}/lib/etch-ant-plugin-${etch.version}.jar"/>
+    <property name="etch-java-runtime.jar" location="${etch.home}/lib/${etch-java-runtime-name}"/>
+    <property name="etch.dll"              location="${etch.home}/lib/Etch.dll"/>
+
+    <property name="src"               location="${basedir}/src"/>
+    <property name="src-main-etch"     location="${src}/main/etch"/>
+    <property name="src-main-java"     location="${src}/main/java"/>
+    <property name="src-main-csharp"   location="${src}/main/csharp"/>
+    <property name="target"            location="${basedir}/target"/>
+    <property name="generated-sources" location="${target}/generated-sources"/>
+    <property name="gensrc-main-etch-java" location="${generated-sources}/main/etch/java"/>
+    <property name="gensrc-main-etch-csharp" location="${generated-sources}/main/etch/csharp"/>
+    <property name="classes"           location="${target}/classes"/>
+    <property name="bin"               location="${target}/bin"/>
+    
+    <condition property="BUILD.csharp" >
+        <os family="windows" />
+    </condition>    
+
+    <taskdef
+        resource="org/apache/etch/tools/ant/etch.xml"
+        classpath="${etch-ant-plugin.jar}"/>
+
+    <target name="build" depends="build-java, build-csharp, done"/>
+
+    <target name="build-java" depends="gensrc-java">
+        <javac destdir="${classes}" source="1.5" debug="true">
+            <classpath>
+                <pathelement location="${etch-java-runtime.jar}"/>
+            </classpath>
+            <src path="${src-main-java}"/>
+            <src path="${gensrc-main-etch-java}"/>
+        </javac>
+
+        <jar jarfile="${bin}/chat.jar">
+            <manifest>
+                <attribute name="Class-Path" value="${etch-java-runtime-name}"/>
+            </manifest>
+            <fileset dir="${classes}"/>
+        </jar>
+
+        <copy todir="${bin}" file="${etch-java-runtime.jar}"/>
+    </target>
+
+    <target name="done">
+        <echo>
+
+To run java chat, open a cmd window and run these commands:
+
+> cd target\bin
+> start java -cp chat.jar etch.examples.chat.MainChatListener
+> start java -cp chat.jar etch.examples.chat.MainChatClient
+> start java -cp chat.jar etch.examples.chat.MainChatClient
+
+Two chat clients will be started; there is a help command;
+login as a different user in each with any password; they
+can chat with each other!
+
+To run csharp chat, open a cmd window and run these commands:
+
+> cd target\bin
+> start ChatListener.exe
+> start ChatClient.exe
+> start ChatClient.exe
+
+You can mix and match the various clients and listeners.
+
+        </echo>
+    </target>
+
+    <target name="build-csharp" depends="gensrc-csharp" if="BUILD.csharp" >
+        <csc
+                debug="true"
+                warnLevel="1"
+                unsafe="false"
+                targetType="exe"
+                incremental="false"
+                mainClass = "etch.examples.chat.MainChatClient"
+                destFile="${bin}/ChatClient.exe">
+            <src dir="${src-main-csharp}/ChatClientProj" includes="**/*.cs"/>
+            <src dir="${src-main-csharp}/etch.examples.chat" includes="**/*.cs"/>
+            <src dir="${gensrc-main-etch-csharp}" includes="**/*.cs"/>
+            <reference file="${etch.dll}"/>
+        </csc>
+
+        <csc
+                debug="true"
+                warnLevel="1"
+                unsafe="false"
+                targetType="exe"
+                incremental="false"
+                mainClass = "etch.examples.chat.MainChatListener"
+                destFile="${bin}/ChatListener.exe">
+            <src dir="${src-main-csharp}/ChatListenerProj" includes="**/*.cs"/>
+            <src dir="${src-main-csharp}/etch.examples.chat" includes="**/*.cs"/>
+            <src dir="${gensrc-main-etch-csharp}" includes="**/*.cs"/>
+            <reference file="${etch.dll}"/>
+        </csc>
+
+        <copy todir="${bin}" file="${etch.dll}"/>
+    </target>
+
+    <target name="gensrc" depends="gensrc-java, gensrc-csharp"/>
+
+    <target name="gensrc-java" depends="init">
+        <etch
+            home="${etch.home}"
+            binding="java"
+            quiet="true"
+            outputDir="${gensrc-main-etch-java}"
+            file="${src-main-etch}/Chat.etch"/>
+    </target>
+
+    <target name="gensrc-csharp" depends="init">
+        <etch
+            home="${etch.home}"
+            binding="csharp"
+            quiet="true"
+            outputDir="${gensrc-main-etch-csharp}"
+            file="${src-main-etch}/Chat.etch"/>
+    </target>
+
+    <target name="init">
+        <mkdir dir="${target}"/>
+        <mkdir dir="${generated-sources}"/>
+        <mkdir dir="${gensrc-main-etch-java}"/>
+        <mkdir dir="${gensrc-main-etch-csharp}"/>
+        <mkdir dir="${classes}"/>
+        <mkdir dir="${bin}"/>
+    </target>
+
+    <target name="clean">
+        <delete dir="${target}"/>
+    </target>
+</project>
diff --git a/examples/chat/src/main/csharp/ChatClientProj/ChatClientProj.csproj b/examples/chat/src/main/csharp/ChatClientProj/ChatClientProj.csproj
new file mode 100644
index 0000000..677d588
--- /dev/null
+++ b/examples/chat/src/main/csharp/ChatClientProj/ChatClientProj.csproj
@@ -0,0 +1,113 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+    -->
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{13BBC268-2F31-4C68-B62B-3C2CFD0228BE}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>org.apache.etch.examples.chat</RootNamespace>
+    <AssemblyName>ChatClient</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\BaseChatClient.cs">
+      <Link>BaseChatClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\BaseChatServer.cs">
+      <Link>BaseChatServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\Chat.cs">
+      <Link>Chat.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\ChatClient.cs">
+      <Link>ChatClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\ChatHelper.cs">
+      <Link>ChatHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\ChatServer.cs">
+      <Link>ChatServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\RemoteChat.cs">
+      <Link>RemoteChat.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\RemoteChatClient.cs">
+      <Link>RemoteChatClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\RemoteChatServer.cs">
+      <Link>RemoteChatServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\StubChat.cs">
+      <Link>StubChat.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\StubChatClient.cs">
+      <Link>StubChatClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\StubChatServer.cs">
+      <Link>StubChatServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\ValueFactoryChat.cs">
+      <Link>ValueFactoryChat.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.chat\ImplChatClient.cs">
+      <Link>ImplChatClient.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.chat\MainChatClient.cs">
+      <Link>MainChatClient.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\..\..\binding-csharp\runtime\src\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/examples/chat/src/main/csharp/ChatClientProj/Properties/AssemblyInfo.cs b/examples/chat/src/main/csharp/ChatClientProj/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e2e4887
--- /dev/null
+++ b/examples/chat/src/main/csharp/ChatClientProj/Properties/AssemblyInfo.cs
@@ -0,0 +1,48 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Chat Client")]
+[assembly: AssemblyDescription("Chat Client Executable")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Cisco Systems")]
+[assembly: AssemblyProduct("Etch")]
+[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c0f12a50-25e5-4648-9d2d-a1bc8ab3deb8")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+[assembly: AssemblyVersion("0.0.0.1")]
+[assembly: AssemblyFileVersion("0.0.0.1")]
diff --git a/examples/chat/src/main/csharp/ChatListenerProj/ChatListenerProj.csproj b/examples/chat/src/main/csharp/ChatListenerProj/ChatListenerProj.csproj
new file mode 100644
index 0000000..1b73ce3
--- /dev/null
+++ b/examples/chat/src/main/csharp/ChatListenerProj/ChatListenerProj.csproj
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{574C28F9-1D0D-47CB-9F18-221E5128D5A6}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>etch.examples.chat</RootNamespace>
+    <AssemblyName>ChatListener</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\BaseChatClient.cs">
+      <Link>BaseChatClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\BaseChatServer.cs">
+      <Link>BaseChatServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\Chat.cs">
+      <Link>Chat.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\ChatClient.cs">
+      <Link>ChatClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\ChatHelper.cs">
+      <Link>ChatHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\ChatServer.cs">
+      <Link>ChatServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\RemoteChat.cs">
+      <Link>RemoteChat.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\RemoteChatClient.cs">
+      <Link>RemoteChatClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\RemoteChatServer.cs">
+      <Link>RemoteChatServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\StubChat.cs">
+      <Link>StubChat.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\StubChatClient.cs">
+      <Link>StubChatClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\StubChatServer.cs">
+      <Link>StubChatServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\ValueFactoryChat.cs">
+      <Link>ValueFactoryChat.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.chat\ImplChatServer.cs">
+      <Link>ImplChatServer.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.chat\MainChatListener.cs">
+      <Link>MainChatListener.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\..\..\binding-csharp\runtime\src\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/examples/chat/src/main/csharp/ChatListenerProj/Properties/AssemblyInfo.cs b/examples/chat/src/main/csharp/ChatListenerProj/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ca9f0ee
--- /dev/null
+++ b/examples/chat/src/main/csharp/ChatListenerProj/Properties/AssemblyInfo.cs
@@ -0,0 +1,48 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Chat Listener")]
+[assembly: AssemblyDescription("Chat Listener Executable")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Cisco Systems")]
+[assembly: AssemblyProduct("Etch")]
+[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("46937d63-b889-459e-8254-4f9906b89449")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+[assembly: AssemblyVersion("0.0.0.1")]
+[assembly: AssemblyFileVersion("0.0.0.1")]
diff --git a/examples/chat/src/main/csharp/etch.examples.chat/ImplChatClient.cs b/examples/chat/src/main/csharp/etch.examples.chat/ImplChatClient.cs
new file mode 100644
index 0000000..a797859
--- /dev/null
+++ b/examples/chat/src/main/csharp/etch.examples.chat/ImplChatClient.cs
@@ -0,0 +1,115 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace org.apache.etch.examples.chat
+{
+    public class ImplChatClient : BaseChatClient
+    {
+        private readonly String _whoami;
+        private readonly bool _snub;
+        private List<String> whoisOnline = new List<string>();
+        private ChatServer server;
+
+
+        /// <summary>
+        /// Constructs the ChatClientImpl
+        /// </summary>
+        /// <param name="whoami"></param>
+        /// <param name="snub"></param>
+        public ImplChatClient( RemoteChatServer server, String whoami, bool snub )
+        {
+            this.server = server;
+            _whoami = whoami;
+            _snub = snub;
+        }
+
+        #region ChatClient Members
+
+        public override void whoIsOnline( string[] names )
+        {
+            foreach ( String name in names )
+            {
+                Console.WriteLine( "{0}: {1} online (src = whoIsOnline)\n", _whoami, name );
+                whoisOnline.Add( name );
+            }
+        }
+
+        public override void  statusChange( string name, bool? online )
+        {
+            if ( (bool) online )
+            {
+                Console.WriteLine( "{0}: {1} online (src = statusChange)\n", _whoami, name );
+                whoisOnline.Add( name );
+            }
+            else
+            {
+                Console.WriteLine( " {0}: {1} offline\n", _whoami, name );
+                whoisOnline.Remove( name );
+            }
+        }
+
+        #endregion
+
+        #region Chat Members
+
+        public override bool? isLoggedIn()
+        {
+            // server is always logged in to the client
+            return true;
+        }
+
+        public override void send( string who, string msg )
+        {
+            Console.WriteLine( "{0}: msg from {1}: {2}\n", _whoami, who, msg );
+            if ( _snub )
+            {
+                server.send( who, String.Format( "{0}, leave me alone!", who ) );
+                Console.WriteLine( "snub done" );
+            }
+        }
+
+        #endregion
+
+        
+
+        #region Session Members
+
+        public void SessionControl( object control, object value )
+        {
+            throw new Exception( "The method or operation is not implemented." );
+        }
+
+        public void SessionNotify( object eventObj )
+        {
+            if ( eventObj.Equals( SessionConsts.DOWN ) )
+                Console.WriteLine( "(server disconnected)" );
+        }
+
+        public object SessionQuery( object query )
+        {
+            throw new Exception( "The method or operation is not implemented." );
+        }
+
+        #endregion
+    }
+}
diff --git a/examples/chat/src/main/csharp/etch.examples.chat/ImplChatServer.cs b/examples/chat/src/main/csharp/etch.examples.chat/ImplChatServer.cs
new file mode 100644
index 0000000..fbff292
--- /dev/null
+++ b/examples/chat/src/main/csharp/etch.examples.chat/ImplChatServer.cs
@@ -0,0 +1,236 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace org.apache.etch.examples.chat
+{
+    public class ImplChatServer : BaseChatServer
+    {
+
+        private readonly RemoteChatClient _client;
+        private Dictionary<String, ImplChatServer> _whoIsOnline;
+
+        /// <summary>
+        /// Constructs the ImplChatServer.
+        /// </summary>
+        /// <param name="client">the client to use for callbacks.</param>
+        /// <param name="whoIsOnline">the database of who is online.</param>
+        public ImplChatServer( RemoteChatClient client, Dictionary<String, ImplChatServer> whoIsOnline )
+        {
+            _client = client;
+            _whoIsOnline = whoIsOnline;
+        }
+
+        #region ChatServer Members
+
+        private string _user;
+ 
+        [ MethodImpl ( MethodImplOptions.Synchronized ) ]
+        public override void login( string name, string pwd )
+        {
+            if ( (bool) isLoggedIn() )
+                throw new org.apache.etch.examples.chat.types.Chat.Failure( "Already logged in" );
+
+            if ( name == null )
+                throw new types.Chat.Failure("Name is null");
+            
+            if ( name.StartsWith("bad"))
+                throw new types.Chat.Failure("Username is not valid");
+
+            if ( name.Length == 0 )
+                throw new types.Chat.Failure("Username is empty");
+
+            if ( pwd == null )
+                throw new types.Chat.Failure("Password is not valid");
+
+            if ( pwd.StartsWith("bad"))
+                throw new types.Chat.Failure("Password is not valid");
+
+            // TODO check user authentication.
+
+            // add this user to the who is online map.
+
+            lock ( _whoIsOnline ) 
+            {
+                ImplChatServer other ;
+
+                // user is logged in already
+                if ( _whoIsOnline.ContainsKey( name ) )
+                {
+                    other = _whoIsOnline[ name ];
+                    try
+                    {
+                        other.Deliver( "SYSTEM", "You have been logged out because you logged in somewhere else." );
+                    }
+                    catch (Exception)
+                    {
+                        // ignore failure to send this message
+                    }
+                    other.logout();
+                    other = null;
+                }
+                // key is not present, i.e., user isn't logged in already
+                else
+                    _whoIsOnline.Add( name, this );
+            }
+
+            // mark as logged in
+            _user = name;
+
+            // say we're online
+            SayStatusChanged( _user, true );
+
+            // tell the client who's online
+            List<String> who;
+
+
+            lock ( _whoIsOnline )
+            {
+                who = new List<string>( _whoIsOnline.Keys );
+            }
+
+            who.Remove( name );
+            _client.whoIsOnline( who.ToArray() );
+
+            Console.WriteLine( "login : " + name );
+        }
+
+        [MethodImpl( MethodImplOptions.Synchronized )]
+        public override void logout()
+        {
+            if ( _user != null )
+            {
+                bool tookUsOffline = false;
+
+                lock ( _whoIsOnline )
+                {
+                    if ( _whoIsOnline.ContainsKey( _user ) )
+                    {
+                        if ( _whoIsOnline[ _user ] == this )
+                        {
+                            // remove us from the online map
+
+                            _whoIsOnline.Remove( _user );
+                            tookUsOffline = true;
+                        }
+                    }
+                }
+
+                if ( tookUsOffline )
+                {
+                    // say we're offline
+                    SayStatusChanged( _user, false );
+                    Console.WriteLine( "logout : " + _user );
+                }
+            }
+
+            _user = null;
+        }
+
+        #endregion
+
+        #region Chat Members
+
+        public override bool? isLoggedIn()
+        {
+            return ( _user != null );
+        }
+
+        private void SayStatusChanged( String u, bool isOnline )
+        {
+            Dictionary<String, ImplChatServer>.ValueCollection who = _whoIsOnline.Values;
+            ImplChatServer[] cArray = new ImplChatServer[ _whoIsOnline.Count ];
+            who.CopyTo( cArray, 0 );
+
+            foreach ( ImplChatServer other in cArray )
+            {
+                if ( other != this )
+                    other._client.statusChange( u, isOnline );
+            }
+        }
+
+        // send
+        public override void send( string who, string msg )
+        {
+            String me = _user;
+            if ( me == null )
+                return;
+
+            ImplChatServer other;
+            lock ( _whoIsOnline )
+            {
+                if ( _whoIsOnline.ContainsKey( who ) )    
+                    other = _whoIsOnline[ who ];
+                else
+                    other = null;
+            }
+
+            if ( other == null )
+                throw new types.Chat.Failure( "user is not online : " + who );
+
+            other.Deliver( me, msg );
+        }
+
+        #endregion
+
+        private void Deliver( String from, String msg )
+        {
+            try 
+            {
+                _client.send(from, msg );
+            }
+            catch( types.Chat.Failure e ) 
+            {
+                Console.WriteLine( e );
+                throw e;
+            }
+            catch ( Exception e ) 
+            {
+                Console.WriteLine( e );
+                throw e;
+            }
+        }
+    
+        #region Session Members
+
+       
+
+        public override void _SessionNotify(object eventObj)
+        {
+            if (eventObj.Equals(SessionConsts.UP))
+                return;
+             if (eventObj.Equals(SessionConsts.DOWN))
+             {
+                 logout();
+                 return;
+             }
+             if (eventObj is Exception)
+                 Console.WriteLine(((Exception) eventObj).StackTrace);
+                
+        }
+
+   
+
+        #endregion
+    }
+}
diff --git a/examples/chat/src/main/csharp/etch.examples.chat/MainChatClient.cs b/examples/chat/src/main/csharp/etch.examples.chat/MainChatClient.cs
new file mode 100644
index 0000000..d444c1f
--- /dev/null
+++ b/examples/chat/src/main/csharp/etch.examples.chat/MainChatClient.cs
@@ -0,0 +1,320 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace org.apache.etch.examples.chat
+{
+    public class MainChatClient : ChatClient, ObjSession
+    {
+        private readonly List<String> _whoIsOnline = new List<string>();
+        private readonly DateTimeFormatInfo myDTFI = new CultureInfo("en-US", false).DateTimeFormat;
+
+
+        public static void Main( String[] args )
+        {
+            string uri;
+            if ( args.Length == 1 )
+            {
+                uri = args[0];
+            }
+            else if ( args.Length == 0 )
+            {
+                uri = "tcp://localhost:4005?TcpTransport.reconnectDelay=4000";
+            }
+            else
+            {
+                Console.WriteLine("usage: MainChatClient [<uri>]");
+                Environment.Exit( 1 );
+                return;
+            }
+
+            Console.WriteLine("Connecting to chat server at " + uri);
+
+            MainChatClient client = new MainChatClient();
+            RemoteChatServer server = ChatHelper.NewServer( uri, null, new MyChatClientFactory( client ));
+            server._StartAndWaitUp( 4000 );
+
+            Console.WriteLine( "( connected, enter commands or help)" );
+
+            while ( true )
+            {
+                Console.Write( "cmd : " );
+                Console.Out.Flush();
+
+                String s = Console.ReadLine();
+                if (s == null)
+                    break;
+
+                if ( s.Length == 0 )
+                    continue;
+
+                char[] seps = { ' ', '\t', '\r', '\n' };
+                String[] cmds = s.Split( seps );
+                
+                if ( cmds.Length == 0 )
+                    continue;
+
+                if ( cmds[ 0 ].Equals( "help" ) )
+                {
+                    Do_help();
+                    continue;
+                }
+
+                if ( cmds[0].Equals( "login") )
+                {
+                    Do_login( server, cmds );
+                    continue;
+                }
+
+                if ( cmds[0].Equals( "logout") )
+                {
+                    server.logout();
+                    continue;
+                }
+
+                if ( cmds[0].Equals( "quit") )
+                {
+                    break;
+                }
+
+                if ( cmds[ 0 ].Equals( "send" ) )
+                {
+                    // extract message 
+                    // note: cmds[2] = message to be extracted
+
+                    if ( cmds.Length < 3 )
+                    {
+                        Console.WriteLine("usage : send <user> <msg>");
+                        continue;
+                    }
+
+                    char[] seps2 = {'\n', '\r'};
+                    String msg = "";
+
+                    for ( int i = 2; i < cmds.Length; i++ )
+                        msg = msg + " " + cmds[ i ];
+
+                    String[] cmds2 = msg.Split( seps2 );
+                    Do_send( server, cmds[ 1 ], cmds2 );
+                    continue;
+                }
+
+                if ( cmds[ 0 ].Equals( "who" ) )
+                {
+                    Do_who( client );
+                    continue;
+                }
+
+                Console.WriteLine( "unknown command" );
+                Do_help();
+            }
+
+            //server.logout();
+            //( ( RemoteChatServer ) server )._StopAndWaitDown( 4000 );
+            server._Stop();
+        }
+
+        private static void Do_help()
+        {
+            Console.WriteLine( "commands: " );
+	        Console.WriteLine( "  help" );
+	        Console.WriteLine( "  login <user> <pwd>" );
+	        Console.WriteLine( "  logout" );
+	        Console.WriteLine( "  quit" );
+ 	        Console.WriteLine( "  send <user> <msg>" );
+ 	        Console.WriteLine( "  who" );
+        }
+
+        private static void Do_login( ChatServer server, String[] st )
+        {
+            try
+            {
+                String name = st[ 1 ];
+                String pwd = st[ 2 ];
+                server.login( name, pwd );
+                Console.WriteLine( "login successful" );
+            }
+            catch ( org.apache.etch.examples.chat.types.Chat.Failure e )
+            {
+                Console.WriteLine( "failed : " + e.GetMessage() );
+            }
+            catch ( IndexOutOfRangeException )
+            {
+                Console.WriteLine( "usage : login <username> <pwd>" );
+            }
+            catch ( Exception e )
+            {
+                Console.WriteLine( e.Message );
+            }
+        }
+
+        /// <summary>
+        /// Send message 
+        /// </summary>
+        /// <param name="server"></param>
+        /// <param name="user">username</param>
+        /// <param name="st">message to be sent</param>
+        /// 
+        private static void Do_send( ChatServer server, String user, String[] st )
+        {
+            try
+            {
+                String who = user;
+                String msg = st[ 0 ];
+                server.send( who, msg );
+            }
+            catch ( org.apache.etch.examples.chat.types.Chat.Failure e )
+            {
+                Console.WriteLine( "failed : " + e.GetMessage() );
+            }
+            catch ( _Etch_AuthException )
+            {
+                Console.WriteLine( "you must login first" );
+            }
+            catch ( IndexOutOfRangeException )
+            {
+                Console.WriteLine( "usage: send <user> <msg> " );
+            }
+            catch ( Exception e )
+            {
+                
+                Console.WriteLine( e.Message );
+            }
+        }
+
+        private static void Do_who(MainChatClient client)
+        {
+            String[] names = client.GetWhoIsOnline();
+            foreach ( String name in names )
+            {
+                Console.WriteLine( " " + name );
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>a list of who is currently online</returns>
+        public String[] GetWhoIsOnline()
+        {
+            return _whoIsOnline.ToArray();
+        }
+
+
+        #region ChatClient Members
+
+        public void whoIsOnline( string[] names )
+        {
+            foreach ( String name in names )
+            {
+                Console.WriteLine( name + " is online" );
+                _whoIsOnline.Add( name );
+            }
+        }
+
+        public void statusChange( string name, bool? online )
+        {
+            if ( ( bool ) online )
+            {
+                Console.WriteLine( name + " is online" );
+                _whoIsOnline.Add( name );
+            }
+            else
+            {
+                Console.WriteLine( name + " is offline" );
+                _whoIsOnline.Remove( name );
+            }
+        }
+
+        #endregion
+
+        #region Chat Members
+
+        public bool? isLoggedIn()
+        {
+            // server is always logged in to the client
+            return true;
+        }
+
+        public void send( string who, string msg )
+        {
+            lock (myDTFI)
+            {
+                Console.WriteLine( "[ {0}@{1} ] {2}\n", who, DateTime.Now.ToString("HH:mm:ss",myDTFI ), msg );
+            }
+        }
+
+
+        #endregion
+
+        #region Session Members
+
+        public void _SessionControl( object control, object value )
+        {
+            throw new Exception( "The method or operation is not implemented." );
+        }
+
+        public void _SessionNotify( object eventObj )
+        {
+            if ( eventObj.Equals( SessionConsts.UP ) )
+            {
+                Console.WriteLine( " (server opened connection)" );
+                return;
+            }
+            if ( eventObj.Equals( SessionConsts.DOWN ) )
+            {
+                Console.WriteLine( " (server closed connection)" );
+                return;
+            }
+            if ( eventObj is Exception )
+            {
+                Console.WriteLine( eventObj );
+                return;
+            }
+
+        }
+
+        public object _SessionQuery( object query )
+        {
+            throw new Exception( "The method or operation is not implemented." );
+        }
+
+        #endregion
+
+        private class MyChatClientFactory : ChatHelper.ChatClientFactory
+        {
+            public MyChatClientFactory(MainChatClient client)
+            {
+                this.client = client;
+            }
+
+            private readonly MainChatClient client;
+
+            public ChatClient NewChatClient(RemoteChatServer server)
+            {
+                return client;
+            }
+        }
+    }
+}
diff --git a/examples/chat/src/main/csharp/etch.examples.chat/MainChatListener.cs b/examples/chat/src/main/csharp/etch.examples.chat/MainChatListener.cs
new file mode 100644
index 0000000..ed20f32
--- /dev/null
+++ b/examples/chat/src/main/csharp/etch.examples.chat/MainChatListener.cs
@@ -0,0 +1,62 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace org.apache.etch.examples.chat
+{
+    ///
+    ///<summary> Main implementation for ChatListener. </summary>
+    ///
+    public class MainChatListener : ChatHelper.ChatServerFactory
+    {
+        ///
+        /// <summary>Main for ChatListener.</summary>
+        /// <param name="args"></param>
+        ///
+        public static void Main(String[] args)
+        {
+            string uri = "tcp://127.0.0.1:4005";
+            ServerFactory listener = ChatHelper.NewListener(uri, null, new MainChatListener());
+            listener.TransportControl(TransportConsts.START_AND_WAIT_UP, 4000);
+        }
+
+        ///
+        /// <summary>Constructs the MainChatListener.</summary>
+        ///
+        public MainChatListener()
+        {
+            whoIsOnline = new Dictionary<string, ImplChatServer>();
+        }
+
+        public readonly Dictionary<string, ImplChatServer> whoIsOnline;
+
+        ///
+        /// <summary>Return a new instance of ChatServer.</summary>
+        /// <param>Remote Chat Client</param>
+        ///
+        public ChatServer NewChatServer(RemoteChatClient client)
+        {
+            return new ImplChatServer(client, whoIsOnline);
+        }
+    }
+}
\ No newline at end of file
diff --git a/examples/chat/src/main/etch/Chat.etch b/examples/chat/src/main/etch/Chat.etch
new file mode 100644
index 0000000..4fed837
--- /dev/null
+++ b/examples/chat/src/main/etch/Chat.etch
@@ -0,0 +1,101 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.examples.chat
+
+/**
+ * The Chat example program implements a simple service
+ * for communicating between logged in users.
+ */
+@Authorize( isLoggedIn ) @Timeout( 4000 )
+service Chat
+{
+	/**
+	 * Exception thrown if Chat fails.
+	 *
+	 * @param msg the reason for the failure.
+	 */
+	exception Failure( string msg )
+	
+	//////////
+	// AUTH //
+	//////////
+	
+	/**
+	 * Marks the user as logged in if they are authentic and have the right
+	 * to utilize the service.
+	 *
+	 * @param name the name of the user.
+	 *
+	 * @param pwd the password of the user.
+	 *
+	 * @throws Failure if the user is already logged in, name or pwd don't
+	 * match authentication database, or if the user doesn't have the right
+	 * to utilize the service.
+	 */
+	@Authorize( true )
+	void login( string name, string pwd ) throws Failure
+	
+	/**
+	 * Marks the user as logged out.
+	 */
+	@Authorize( true )
+	void logout()
+	
+	/**
+	 * Checks if a user is logged in.
+	 *
+	 * @return true if a user is logged in.
+	 */
+	@Authorize( true ) @Direction( Both )
+	boolean isLoggedIn()
+	
+	//////////
+	// CHAT //
+	//////////
+	
+	/**
+	 * Reports the set of online users upon login.
+	 *
+	 * @param names the set of online users.
+	 */
+	@Oneway @Direction( Client )
+	void whoIsOnline( string[] names )
+	
+	/**
+	 * Reports a status change of a user.
+	 *
+	 * @param name the name of the user.
+	 *
+	 * @param online true if they are now online.
+	 */
+	@Oneway @Direction( Client )
+	void statusChange( string name, boolean online ) 
+	
+	/**
+	 * Sends a message to or from the named user.
+	 *
+	 * @param who the name of the recipient or the sender
+	 * depending upon the direction.
+	 *
+	 * @param msg the message to send.
+	 *
+	 * @throws Failure if the user is not online.
+	 */
+	@Direction( Both ) @AsyncReceiver( Queued )
+	void send( string who, string msg ) throws Failure
+}
diff --git a/examples/chat/src/main/java/org/apache/etch/examples/chat/ImplChatClient.java b/examples/chat/src/main/java/org/apache/etch/examples/chat/ImplChatClient.java
new file mode 100644
index 0000000..372f7ed
--- /dev/null
+++ b/examples/chat/src/main/java/org/apache/etch/examples/chat/ImplChatClient.java
@@ -0,0 +1,108 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.chat;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.etch.util.core.io.Session;
+
+
+
+/**
+ * Your custom implementation of BaseChatClient. Add methods here to provide
+ * implementations of messages from the server.
+ */
+public class ImplChatClient extends BaseChatClient
+{
+	/**
+	 * Constructs the ImplChatClient.
+	 *
+	 * @param server a connection to the server session. Use this to send a
+	 * message to the server.
+	 * @param whoami 
+	 * @param snub 
+	 */
+	public ImplChatClient( RemoteChatServer server, String whoami, boolean snub )
+	{
+		this.server = server;
+		this.whoami = whoami;
+		this.snub = snub;
+	}
+	
+	private final RemoteChatServer server;
+	
+	private final String whoami;
+	
+	private final boolean snub;
+
+	@Override
+	public Boolean isLoggedIn()
+	{
+		// server is always logged in to the client.
+		return true;
+	}
+
+	@Override
+	public void statusChange( String name, Boolean online ) 
+	{
+		if (online)
+		{
+			System.out.printf( "%s: %s online (src=statusChange)\n", whoami, name );
+			whoIsOnline.add( name );
+		}
+		else
+		{
+			System.out.printf( "%s: %s offline\n", whoami, name );
+			whoIsOnline.remove( name );
+		}
+	}
+
+	@Override
+	public void whoIsOnline( String[] names )
+    {
+		for (String name: names)
+		{
+			System.out.printf( "%s: %s online (src=whoIsOnline)\n", whoami, name );
+			whoIsOnline.add(  name );
+		}
+    }
+	
+	private Set<String> whoIsOnline = new HashSet<String>();
+
+	@Override
+	public void send( String who, String msg ) throws Failure
+    {
+		System.out.printf( "%s: msg from %s: %s\n", whoami, who, msg );
+		if (snub)
+		{
+			server.send( who, String.format( "%s, leave me alone!", who ) );
+			System.out.println( "snub done" );
+		}
+    }
+
+	@Override
+	public void _sessionNotify( Object event ) throws Exception
+	{
+		if (event == Session.DOWN)
+			System.out.println( "(server disconnected)" );
+	}
+}
\ No newline at end of file
diff --git a/examples/chat/src/main/java/org/apache/etch/examples/chat/ImplChatServer.java b/examples/chat/src/main/java/org/apache/etch/examples/chat/ImplChatServer.java
new file mode 100644
index 0000000..4c75c04
--- /dev/null
+++ b/examples/chat/src/main/java/org/apache/etch/examples/chat/ImplChatServer.java
@@ -0,0 +1,232 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.chat;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.etch.util.Log;
+import org.apache.etch.util.core.io.Session;
+
+
+
+/**
+ * Your custom implementation of BaseChatServer. Add methods here to provide
+ * implementations of messages from the client.
+ */
+public class ImplChatServer extends BaseChatServer
+{
+	/**
+	 * Constructs the ImplChatServer.
+	 *
+	 * @param client a connection to the client session. Use this to send a
+	 * message to the client.
+	 * @param whoIsOnline database of online connections.
+	 */
+	public ImplChatServer( RemoteChatClient client,
+		Map<String, ImplChatServer> whoIsOnline )
+	{
+		this.client = client;
+		this.whoIsOnline = whoIsOnline;
+	}
+	
+	private final RemoteChatClient client;
+
+	private final Map<String, ImplChatServer> whoIsOnline;
+
+	////////////////////
+	// Authentication //
+	////////////////////
+	
+//	private final static String INVALID_NAME_PWD_MSG = "User name/password is not valid";
+
+	@Override
+	public synchronized void login( String name, String pwd ) throws Failure
+	{
+		if (isLoggedIn())
+			throw new Failure( "Already logged in" );
+
+		if (name == null)
+			throw new Failure("Username is null");
+		
+		if (name.length() == 0)
+			throw new Failure("Username is empty");
+		
+		if (name.startsWith("bad"))
+			throw new Failure("Username is not valid");
+
+		if (pwd == null)
+			throw new Failure("Password is null");
+		
+		if (pwd.startsWith("bad"))
+			throw new Failure("Password is not valid");
+		
+		// TODO check user authentication.
+
+		// add this user to the who is online map.
+		
+		ImplChatServer other = whoIsOnline.put( name, this );
+		if (other != null)
+		{
+			try
+			{
+				other.deliver( "SYSTEM", "You have been logged out because you logged in somewhere else." );
+			}
+			catch ( Exception e )
+			{
+				// ignore failure to send this message.
+			}
+			other.logout();
+			other = null;
+		}
+		
+		// mark as logged in.
+
+		user = name;
+		
+		// say we're online
+		
+		sayStatusChanged( user, true );
+
+		// tell the client who's online
+		
+		Set<String> who;
+		synchronized (whoIsOnline)
+		{
+			who = new HashSet<String>( whoIsOnline.keySet() );
+		}
+		who.remove( name );
+		client.whoIsOnline( who.toArray( new String[who.size()] ) );
+		
+		Log.report( "login", "who", name );
+	}
+
+	@Override
+	public synchronized void logout()
+	{
+		if (user != null)
+		{
+			boolean tookUsOfflne = false;
+			
+			synchronized (whoIsOnline)
+			{
+				if (whoIsOnline.get( user ) == this)
+				{
+					// remove us from the online map.
+					
+					whoIsOnline.remove( user );
+					tookUsOfflne = true;
+				}
+			}
+			
+			if (tookUsOfflne)
+			{
+				// say we're offline
+				
+				sayStatusChanged( user, false );
+
+				Log.report( "logout", "who", user );
+			}
+			
+			user = null;
+		}
+	}
+
+	@Override
+	public Boolean isLoggedIn()
+	{
+		return user != null;
+	}
+
+	private void sayStatusChanged( String u, boolean isOnline )
+    {
+		Collection<ImplChatServer> who = whoIsOnline.values();
+	    for (ImplChatServer other: who.toArray( new ImplChatServer[who.size()] ))
+	    	if (other != this)
+	    		other.client.statusChange( u, isOnline );
+    }
+
+	private String user;
+
+	//////////
+	// Send //
+	//////////
+
+	@Override
+	public void send( String who, String msg ) throws Failure
+	{
+		String me = user;
+		if (me == null)
+			return;
+		
+		ImplChatServer other = whoIsOnline.get( who );
+		if (other == null)
+			throw new Failure( "user is not online: "+who );
+		
+		other.deliver( me, msg );
+	}
+
+	private void deliver( String from, String msg ) throws Failure
+	{
+		// TODO check from not in user's block list...
+		
+		try
+		{
+			Log.report( "sending", "from", from, "to", user, "msg", msg );
+			client.send( from, msg );
+			Log.report( "sent", "from", from, "to", user, "msg", msg );
+		}
+		catch ( Failure e )
+		{
+			e.printStackTrace();
+			throw e;
+		}
+		catch ( RuntimeException e )
+		{
+			e.printStackTrace();
+			throw e;
+		}
+	}
+
+	////////////////////////////////////////
+	// Session query, control, and notify //
+	////////////////////////////////////////
+
+	@Override
+	public void _sessionNotify( Object event ) throws Exception
+	{
+		if (event == Session.UP)
+			return;
+		
+		if (event == Session.DOWN)
+		{
+			logout();
+			return;
+		}
+		
+		if (event instanceof Throwable)
+			((Throwable) event).printStackTrace();
+		else
+			Log.report( "event", "conn", this, "what", event );
+	}
+}
\ No newline at end of file
diff --git a/examples/chat/src/main/java/org/apache/etch/examples/chat/MainChatClient.java b/examples/chat/src/main/java/org/apache/etch/examples/chat/MainChatClient.java
new file mode 100644
index 0000000..f0ecef3
--- /dev/null
+++ b/examples/chat/src/main/java/org/apache/etch/examples/chat/MainChatClient.java
@@ -0,0 +1,311 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.chat;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.apache.etch.bindings.java.support.ObjSession;
+import org.apache.etch.bindings.java.support._Etch_AuthException;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.core.io.Session;
+import org.apache.etch.util.core.io.Transport;
+
+
+
+/**
+ * Simple command line chat client.
+ */
+public class MainChatClient implements ChatClient, ObjSession
+{
+	/**
+	 * @param args
+	 * @throws Exception 
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		Log.addSink( null );
+		Log.report( "MainChatClient" );
+		
+		final String uri;
+		if (args.length == 1)
+		{
+			uri = args[0];
+		}
+		else if (args.length == 0)
+		{
+			uri = "tcp://localhost:4005?TcpTransport.reconnectDelay=4000";
+		}
+		else
+		{
+			System.out.println( "usage: MainChatClient [<uri>]" );
+			System.exit( 1 );
+			return;
+		}
+		
+		System.out.println( "Connecting to chat server at "+uri );
+		
+		final MainChatClient client = new MainChatClient();
+		
+		RemoteChatServer server = ChatHelper.newServer( uri, null,
+			new ChatHelper.ChatClientFactory()
+			{
+				public ChatClient newChatClient( RemoteChatServer server )
+					throws Exception
+				{
+					return client;
+				}
+			} );
+		
+		server._startAndWaitUp( 4000 );
+		
+		System.out.println( "(connected, enter command or 'help' to list commands)" );
+		
+		BufferedReader rdr = new BufferedReader( new InputStreamReader( System.in ) );
+		while (true)
+		{
+			System.out.print( "cmd: " );
+			System.out.flush();
+			
+			String s = rdr.readLine();
+			if (s.length() == 0)
+				continue;
+			
+			StringTokenizer st = new StringTokenizer( s, " \t\r\n" );
+			if (!st.hasMoreTokens())
+				continue;
+			
+			String cmd = st.nextToken();
+			
+			if (cmd.equals( "help" ))
+			{
+				do_help();
+				continue;
+			}
+			
+			if (cmd.equals( "login" ))
+			{
+				do_login( server, st );
+				continue;
+			}
+			
+			if (cmd.equals( "logout" ))
+			{
+				do_logout( server );
+				continue;
+			}
+			
+			if (cmd.equals( "quit" ))
+				break;
+			
+			if (cmd.equals( "send" ))
+			{
+				do_send( server, cmd, st );
+				continue;
+			}
+			
+			if (cmd.equals( "who" ))
+			{
+				do_who( client );
+				continue;
+			}
+
+			System.out.println( "unknown command "+cmd );
+			do_help();
+		}
+		
+		server._transportControl( Transport.STOP, null );
+	}
+
+	private static void do_help()
+    {
+	    System.out.println( "commands: " );
+	    System.out.println( "  help" );
+	    System.out.println( "  login <user> <pwd>" );
+	    System.out.println( "  logout" );
+	    System.out.println( "  quit" );
+ 	    System.out.println( "  send <user> <msg>" );
+ 	    System.out.println( "  who" );
+	}
+
+	private static void do_login( ChatServer server, StringTokenizer st )
+    {
+		try
+		{
+			String name = st.nextToken();
+			String pwd = st.nextToken();
+			server.login( name, pwd );
+			System.out.println( "(login successful)" );
+		}
+		catch ( NoSuchElementException e )
+		{
+			System.out.println( "usage: login <user> <pwd>" );
+		}
+		catch ( Failure e )
+		{
+			System.out.println( "failed: "+e.getMessage() );
+			e.printStackTrace();
+		}
+		catch ( Exception e )
+		{
+			System.out.println( "failed: "+e );
+			e.printStackTrace();
+		}
+    }
+
+	private static void do_logout( ChatServer server )
+	{
+		server.logout();
+		System.out.println( "(logout successful)" );
+	}
+
+	private static void do_send( ChatServer server, String cmd, StringTokenizer st )
+    {
+		try
+		{
+			String who = st.nextToken();
+			String msg = st.nextToken( "\r\n" );
+			server.send( who, msg );
+		}
+		catch ( NoSuchElementException e )
+		{
+			System.out.println( "usage: send <user> <msg>" );
+		}
+		catch ( _Etch_AuthException e )
+		{
+			System.out.println( "you must login first" );
+		}
+		catch ( Failure e )
+		{
+			System.out.println( "failed: "+e.getMessage() );
+		}
+		catch ( Exception e )
+		{
+			System.out.println( "failed: "+e );
+		}
+    }
+	
+	private static void do_who( MainChatClient client )
+    {
+	    for (String name: client.getWhoIsOnline())
+	    	System.out.println( "  "+name );
+    }
+	
+	/**
+	 * @return a list of who is online right now.
+	 */
+	public String[] getWhoIsOnline()
+	{
+		return whoIsOnline.toArray( new String[0] );
+	}
+	
+	private final Set<String> whoIsOnline = Collections.synchronizedSet( new HashSet<String>() );
+
+    ////////////////
+    // ChatClient //
+    ////////////////
+
+	public void whoIsOnline( String[] names )
+    {
+	    for (String name: names)
+	    {
+	    	whoIsOnline.add( name );
+	    	System.out.println( name+" is online" );
+	    }
+    }
+
+	public void statusChange( String name, Boolean online )
+    {
+		if (online)
+		{
+			whoIsOnline.add( name );
+			System.out.println( name+" is now online" );
+		}
+		else
+		{
+			whoIsOnline.remove( name );
+			System.out.println( name+" is now offline" );
+		}
+    }
+
+	//////////
+	// Chat //
+	//////////
+
+	public Boolean isLoggedIn()
+    {
+		// server is always logged in to the client.
+	    return true;
+    }
+
+	public void send( String who, String msg ) throws Failure
+    {
+		synchronized( df )
+		{
+			System.out.printf( "[ %s@%s ] %s\n", who, df.format( new Date() ), msg );
+		}
+    }
+	
+	private DateFormat df = new SimpleDateFormat( "HH:mm:ss" );
+
+	////////////////
+	// ObjSession //
+	////////////////
+
+	public Object _sessionQuery( Object query )
+	{
+		throw new UnsupportedOperationException( "unknown query: "+query );
+	}
+
+	public void _sessionControl( Object control, Object value )
+	{
+		throw new UnsupportedOperationException( "unknown control: "+control );
+	}
+
+	public void _sessionNotify( Object event )
+	{
+		if (event.equals( Session.UP ) )
+		{
+			System.out.println( "(server opened connection)" );
+			return;
+		}
+		
+		if (event.equals( Session.DOWN ) )
+		{
+			System.out.println( "(server closed connection)" );
+			return;
+		}
+		
+		if (event instanceof Throwable)
+		{
+			((Throwable) event).printStackTrace();
+			return;
+		}
+	}
+}
diff --git a/examples/chat/src/main/java/org/apache/etch/examples/chat/MainChatListener.java b/examples/chat/src/main/java/org/apache/etch/examples/chat/MainChatListener.java
new file mode 100644
index 0000000..db74310
--- /dev/null
+++ b/examples/chat/src/main/java/org/apache/etch/examples/chat/MainChatListener.java
@@ -0,0 +1,77 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.chat;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.core.io.Transport;
+
+
+
+/**
+ * Main program for ChatServer. This program makes a listener to accept
+ * connections from MainChatClient.
+ */
+public class MainChatListener implements ChatHelper.ChatServerFactory
+{
+	/**
+	 * Main program for ChatServer.
+	 * 
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		Log.addSink( null );
+		Log.report( "MainChatListener" );
+		
+		String uri = "tcp://0.0.0.0:4005";
+		if (args.length > 0)
+		{
+			uri = args[0];
+		}
+		else if (args.length != 0)
+		{
+			System.out.println( "usage: MainChatListener [uri]" );
+			System.exit( 1 );
+			return;
+		}
+		
+		MainChatListener implFactory = new MainChatListener();
+		
+		ServerFactory listener = ChatHelper.newListener( uri, null,
+			implFactory );
+
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+	}
+
+	private final Map<String, ImplChatServer> whoIsOnline =
+		Collections.synchronizedMap( new HashMap<String, ImplChatServer>() );
+
+	public ChatServer newChatServer( RemoteChatClient client )
+	{
+		return new ImplChatServer( client, whoIsOnline );
+	}
+}
diff --git a/examples/chat/src/test/csharp/ChatTestProj/ChatTestProj.csproj b/examples/chat/src/test/csharp/ChatTestProj/ChatTestProj.csproj
new file mode 100644
index 0000000..176209f
--- /dev/null
+++ b/examples/chat/src/test/csharp/ChatTestProj/ChatTestProj.csproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{01A7F0CC-78AB-4CFE-88DB-32AAC6D6C00B}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>ChatTestProj</RootNamespace>
+    <AssemblyName>ChatTestProj</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="nunit.framework, Version=2.4.7.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>$(NUNIT_HOME)\bin\nunit.framework.dll</HintPath>
+      <SpecificVersion>False</SpecificVersion>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\BaseChatClient.cs">
+      <Link>BaseChatClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\BaseChatServer.cs">
+      <Link>BaseChatServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\Chat.cs">
+      <Link>Chat.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\ChatClient.cs">
+      <Link>ChatClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\ChatHelper.cs">
+      <Link>ChatHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\ChatServer.cs">
+      <Link>ChatServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\RemoteChat.cs">
+      <Link>RemoteChat.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\RemoteChatClient.cs">
+      <Link>RemoteChatClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\RemoteChatServer.cs">
+      <Link>RemoteChatServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\StubChat.cs">
+      <Link>StubChat.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\StubChatClient.cs">
+      <Link>StubChatClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\StubChatServer.cs">
+      <Link>StubChatServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.chat\ValueFactoryChat.cs">
+      <Link>ValueFactoryChat.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.chat\ImplChatClient.cs">
+      <Link>ImplChatClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.chat\ImplChatServer.cs">
+      <Link>ImplChatServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.chat\MainChatClient.cs">
+      <Link>MainChatClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.chat\MainChatListener.cs">
+      <Link>MainChatListener.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.chat\TestRemoteChatServer.cs">
+      <Link>TestRemoteChatServer.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\..\..\binding-csharp\runtime\src\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/examples/chat/src/test/csharp/ChatTestProj/Properties/AssemblyInfo.cs b/examples/chat/src/test/csharp/ChatTestProj/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..09afdb8
--- /dev/null
+++ b/examples/chat/src/test/csharp/ChatTestProj/Properties/AssemblyInfo.cs
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ChatTestProj")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ChatTestProj")]
+[assembly: AssemblyCopyright("Copyright ©  2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("70f5f8de-3685-4fab-b80e-fa21bd0d197d")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/examples/chat/src/test/csharp/etch.examples.chat/TestRemoteChatServer.cs b/examples/chat/src/test/csharp/etch.examples.chat/TestRemoteChatServer.cs
new file mode 100644
index 0000000..4554f88
--- /dev/null
+++ b/examples/chat/src/test/csharp/etch.examples.chat/TestRemoteChatServer.cs
@@ -0,0 +1,169 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+using org.apache.etch.examples.chat.types.Chat;
+
+namespace org.apache.etch.examples.chat
+{
+    [TestFixture]
+    public class TestRemoteChatServer
+    {
+        private const String _fred = "Fred";
+       
+        private static RemoteChatServer fred_server;
+
+        private static ServerFactory listener;
+
+        [TestFixtureSetUp]
+        public  void SetupListener()
+        {
+            String uri = "tcp://localhost:4010";
+
+            MainChatListener implFactory = new MainChatListener();
+            listener = ChatHelper.NewListener(uri, null, implFactory);
+
+            listener.TransportControl(TransportConsts.START_AND_WAIT_UP, 4000);
+
+            Console.WriteLine("Listener Started");
+        }
+      
+        [SetUp]
+        public void AssignNullToConnections()
+        {
+            fred_server = null;
+           
+        }
+
+               
+        [Test]
+        public void TestLogin1()
+        {
+            fred_server = SetupUserAndConnection(_fred);
+            fred_server.login( _fred, _fred );
+        }
+
+
+        [Test]
+        [ExpectedException( typeof( Failure ) )]
+        public void TestLogin2()
+        {
+            fred_server =  SetupUserAndConnection(_fred );           
+            fred_server.login( _fred, _fred );
+            fred_server.login(_fred, _fred);            
+        }
+
+        [Test]
+        [ExpectedException(typeof(Failure))]
+        public void TestLogin3()
+        {
+            fred_server = SetupUserAndConnection(null);
+            fred_server.login(null, null);
+        }
+
+        [Test]
+        [ExpectedException(typeof(Failure))]
+        public void TestLogin4()
+        {
+            fred_server = SetupUserAndConnection("fred");
+            fred_server.login("fred", "badPass");
+        }
+
+        [Test]
+        [ExpectedException(typeof(Failure))]
+        public void TestLogin()
+        {
+            fred_server = SetupUserAndConnection("badUser");
+            fred_server.login("badUser", "badPass");
+
+        }
+
+        [TearDown]
+        public void ShutDownOpenConnections()
+        {
+            if (fred_server != null)
+            {
+                fred_server.logout();
+                fred_server._Stop();
+            }
+        }
+
+        [TestFixtureTearDown]
+        public void StopListener()
+        {
+            if (listener != null)
+            {
+                listener.TransportControl(TransportConsts.STOP_AND_WAIT_DOWN, 4000);
+                listener = null;
+            }
+        }
+
+        /// <summary>
+        /// Setup the connection and server specific information for this user. 
+        /// </summary>
+        /// <param name="username"></param>
+        /// <returns>The ChatServer instance to play with</returns>
+        /// 
+        public static RemoteChatServer SetupUserAndConnection( String username)
+        {
+            
+            String uri = "tcp://localhost:4010";
+            
+            MyChatClientImpl client = new MyChatClientImpl( username);
+            RemoteChatServer server = ChatHelper.NewServer( uri,null, client );
+         
+            server._StartAndWaitUp( 4000 );
+
+            return server;           
+        }
+
+        /// <summary>
+        /// Create your own ChatClientImpl so as to verify messages. 
+        /// </summary>
+        public class MyChatClientImpl : ChatHelper.ChatClientFactory
+        {
+                     
+            public String user;
+
+            /// <summary>
+            /// Constructs the ChatClientImpl
+            /// </summary>
+          
+            public MyChatClientImpl(string user )
+            {
+             
+                this.user = user;
+            }
+
+
+            #region ChatClientFactory Members
+
+            public ChatClient NewChatClient(RemoteChatServer server)
+            {
+                return new ImplChatClient(server, user, false);
+            }
+
+            #endregion
+        }
+
+    }
+}
diff --git a/examples/chat/src/test/java/org/apache/etch/examples/chat/TestRemoteChatServer.java b/examples/chat/src/test/java/org/apache/etch/examples/chat/TestRemoteChatServer.java
new file mode 100644
index 0000000..9a4aac8
--- /dev/null
+++ b/examples/chat/src/test/java/org/apache/etch/examples/chat/TestRemoteChatServer.java
@@ -0,0 +1,180 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.chat;
+
+// import static org.junit.Assert.*; 
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.examples.chat.Chat.Failure;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.core.io.Transport;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+/**
+ * Tests RemoteChatServer.
+ */
+public class TestRemoteChatServer
+{
+	final String user = "user1";
+	final String nullUser = null;
+	final String badUser = "baduser";
+	final String badPass = "badPass"; 
+	RemoteChatServer cs;
+
+	/**
+	 * Start remote chat listener
+	 * @throws Exception
+	 */
+	@BeforeClass
+	public static void startRemoteChatListener() throws Exception 
+	{
+		Log.addSink(null);
+		Log.report("StartRemoteChatListener");
+		
+		String uri = "tcp://localhost:4005";
+		MainChatListener implFactory = new MainChatListener(); 
+		listener = ChatHelper.newListener( uri, null, implFactory );
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+		
+		Log.report( "StartRemoteChatListener",
+			"status", "up",
+			"listener", listener );
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@AfterClass
+	public static void stopRemoteChatListener() throws Exception
+	{
+		if (listener != null)
+		{
+			listener.transportControl( Transport.STOP_AND_WAIT_DOWN, 4000 );
+			listener = null;
+		}
+	}
+	
+	private static ServerFactory listener;
+	
+	/**
+	 * testLogin1: Login user
+	 * @throws Exception
+	 */
+	@Test
+	public void testLogin1() throws Exception
+	{		
+		Log.report("TestRemoteChatServer.login: testLogin1 - Login user");
+		cs = setupAndConnectUser(user);
+		cs.login(user,user);
+	}
+	
+	/**
+	 * testLogin2: User is already logged in
+	 * @throws Exception
+	 */
+	@Test(expected = Failure.class)
+	public void testLogin2() throws Exception
+	{
+		Log.report("TestRemoteChatServer.login: testLogin2 - Login user. User is already logged in");
+		cs = setupAndConnectUser(user);
+		cs.login(user,user);
+		cs.login(user,user);
+	}
+	
+	/**
+	 * testLogin3: Login - user is null
+	 * @throws Exception
+	 */
+	@Test(expected = Failure.class)
+	public void testLogin3() throws Exception
+	{		
+		Log.report("TestRemoteChatServer.login: testLogin3 - Login user. User is null");
+		cs = setupAndConnectUser(nullUser);
+		cs.login(nullUser,nullUser);
+	}
+	
+	/**
+	 * testLogin4: Login - bad password
+	 * @throws Exception
+	 */
+	@Test(expected = Failure.class)
+	public void testLogin4() throws Exception
+	{		
+		Log.report("TestRemoteChatServer.login: testLogin4 - Login user. Bad password");
+		cs = setupAndConnectUser(user);
+		cs.login(user,badPass);
+	}
+	
+	/**
+	 * testLogin5: Login - bad username
+	 * @throws Exception
+	 */
+	@Test(expected = Failure.class)
+	public void testLogin5() throws Exception
+	{		
+		Log.report("TestRemoteChatServer.login: testLogin5 - Login user. Bad username");
+		cs = setupAndConnectUser(user);
+		cs.login(user,badUser);
+	}
+	
+	/**
+	 * Logout out user and close TCP conection
+	 * @throws Exception 
+	 */
+	@After
+	public void cleanup() throws Exception {
+		if (cs != null)
+		{
+			cs.logout();
+			cs._stop();
+		}
+	}
+	
+	/**
+	 * @param user
+	 * @return chat server
+	 * @throws Exception
+	 */
+	public RemoteChatServer setupAndConnectUser (final String user) throws Exception
+	{
+		String uri = "tcp://localhost:4005";
+		
+//		ChatClientImpl client = new ChatClientImpl(user, false);
+		RemoteChatServer server = ChatHelper.newServer( uri, null,
+			new ChatHelper.ChatClientFactory()
+			{
+				public ChatClient newChatClient( RemoteChatServer server )
+					throws Exception
+				{
+					return new ImplChatClient( server, user, false );
+				}
+			} );
+//		client._setServer(server);
+	
+		server._startAndWaitUp( 4000 );
+		
+		return server;
+	}
+}
diff --git a/examples/distmap/README.txt b/examples/distmap/README.txt
new file mode 100644
index 0000000..4f8e55d
--- /dev/null
+++ b/examples/distmap/README.txt
@@ -0,0 +1,28 @@
+To get started with the example you will need jdk 1.5.0_x,
+where x is pretty recent (>= 15), or any release of jdk 1.6.
+You will also need ant 1.7.0, with ant .net plugin if you
+want to build csharp. You will also need microsoft .net
+sdk 2.0 for csharp builds.
+
+To build:
+
+> ant
+
+This will run the default target which will build both java
+and csharp programs. You can also use build-java or build-csharp
+targets to build only java or only csharp.
+
+To run java distributed map, open a cmd window and run these
+commands:
+
+> cd target\bin
+> start java -cp distmap.jar etch.examples.distmap.MainDistributedHashTableListener
+> start java -cp distmap.jar etch.examples.distmap.MainDistributedHashTableClient
+
+To run csharp distributed map:
+
+> cd target\bin
+> start DistMapListener.exe
+> start DistMapClient.exe
+
+You can mix and match the various clients and listeners.
diff --git a/examples/distmap/build.xml b/examples/distmap/build.xml
new file mode 100644
index 0000000..b98fcbc
--- /dev/null
+++ b/examples/distmap/build.xml
@@ -0,0 +1,322 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-distmap-example" basedir="." default="help" >
+    <description>Distributed Map Example</description>
+    <property name="Etch.basedir" location="${basedir}/../.." />
+    <import file="${Etch.basedir}/build-support/etch.includes.xml" />
+
+    <!-- TODO better computation of etch.home, etch.version -->
+    <property environment="env" />
+
+    <!-- compute ETCH_HOME -->
+    <property name="build.ETCH_HOME" location="${basedir}/../../target/Installers/dist" />
+    <condition property="etch.home" value="${env.ETCH_HOME}" >
+        <isset property="${env.ETCH_HOME}" />
+    </condition>
+    <condition property="etch.home" value="${build.ETCH_HOME}" >
+        <not><isset property="etch.home" /></not>
+    </condition>
+
+    <property name="Etch.dependency.junit.jar"
+        location="${default.junit.lib}/junit-4.3.1.jar" />
+
+    <property name="Etch.buildSupportDirectory" location="../../build-support" />
+
+    <!-- compute etch.version -->
+    <condition property="etch.version" value="${Etch.version}" >
+        <not><isset property="etch.version" /></not>
+    </condition>
+
+    <!-- Csharp Support -->
+    <condition property="USE.dotnet" >
+        <and>
+            <os family="windows" />
+            <available file="${env.windir}/Microsoft.NET/Framework/v2.0.50727/msbuild.exe" />
+        </and>
+    </condition>
+    <condition property="USE.mono" >
+        <and>
+            <not><os family="windows" /></not>
+            <!-- TODO mono support is not fully baked, use -DUSE.mono to test -->
+            <!-- <available file="${env.MONO_HOME}/bin/mdtool" /> -->
+            <isset property="USE.mono" />
+        </and>
+    </condition>
+    <condition property="BUILD.csharp" >
+        <or>
+            <isset property="USE.dotnet" />
+            <isset property="USE.mono" />
+        </or>
+    </condition>
+
+    <!-- import etch task -->
+    <taskdef
+        onerror="report"
+        resource="org/apache/etch/tools/ant/etch.xml"
+        classpath="${etch.home}/lib/etch-ant-plugin-${etch.version}.jar" />
+
+    <!-- import dotnet task -->
+    <condition property="ant.dotnet.jar" value="ant-dotnet-1.0.jar" >
+        <not><isset property="ant.dotnet.jar" /></not>
+    </condition>
+
+    <taskdef
+        onerror="report"
+        resource="org/apache/ant/dotnet/antlib.xml"
+        classpath="${ant.dotnet.jar}" />
+
+    <macrodef name="mdtool" >
+        <attribute name="dir"         default="." />
+        <attribute name="failonerror" default="false" />
+        <attribute name="project"     default="project.csproj" />
+        <attribute name="target"      default="${build.target}" />
+        <sequential>
+            <exec executable="${env.MONO_HOME}/bin/mdtool" dir="@{dir}" failonerror="@{failonerror}" >
+                <arg value="build" />
+                <arg value="--buildfile:@{project}" />
+            </exec>
+        </sequential>
+    </macrodef>
+
+    <!-- set properties -->
+    <property name="src"               location="${basedir}/src" />
+    <property name="main-src-java"     location="${src}/main/java" />
+    <property name="test-src-java"     location="${src}/test/java" />
+    <property name="target"            location="${basedir}/target" />
+    <property name="dist-src"          location="${target}/dist-src" />
+    <property name="generated-sources" location="${target}/generated-sources" />
+    <property name="gen-src-java"      location="${generated-sources}/main/etch/java" />
+    <property name="gen-src-csharp"    location="${generated-sources}/main/etch/csharp" />
+    <property name="bin"               location="${target}/bin" />
+    <property name="classes"           location="${target}/classes" />
+    <property name="classes-test"      location="${target}/classes-test" />
+    <property name="test-results"      location="${target}/test-results" />
+    <property name="nunit-results"     location="${target}/nunit-results" />
+    <property name="dist"              location="${basedir}/../../target/Installers/dist" />
+
+    <!-- initialize -->
+    <target name="init" >
+        <mkdir dir="${target}" />
+        <mkdir dir="${dist-src}" />
+        <mkdir dir="${generated-sources}" />
+        <mkdir dir="${gen-src-java}" />
+        <mkdir dir="${gen-src-csharp}" />
+        <mkdir dir="${bin}" />
+        <mkdir dir="${classes}" />
+        <mkdir dir="${classes-test}" />
+        <mkdir dir="${test-results}" />
+        <mkdir dir="${nunit-results}" />
+    </target>
+
+    <!-- build the server -->
+    <target name="generate-sources" depends="init" >
+        <!-- generate sources -->
+
+        <etch home="${etch.home}"
+              file="${src}/main/etch/DistributedHashTable.etch"
+              binding="java"
+              outputDir="${gen-src-java}" />
+
+        <etch home="${etch.home}"
+              file="${src}/main/etch/DistributedHashTable.etch"
+              binding="csharp"
+              outputDir="${gen-src-csharp}" />
+    </target>
+
+    <property name="etch-java-runtime-name"
+        value="etch-java-runtime-${etch.version}.jar" />
+
+    <property name="Etch.dependency.java.runtime"
+        location="${etch.home}/lib/${etch-java-runtime-name}" />
+
+    <target name="build-java" depends="generate-sources" >
+        <!-- compile sources -->
+
+        <javac target="1.5" destdir="${classes}" >
+            <src path="${gen-src-java}" />
+            <src path="${main-src-java}" />
+            <classpath>
+                <pathelement location="${Etch.dependency.java.runtime}" />
+            </classpath>
+        </javac>
+
+        <javac target="1.5" destdir="${classes-test}" >
+            <src path="${gen-src-java}" />
+            <src path="${main-src-java}" />
+            <src path="${test-src-java}" />
+            <classpath>
+                <pathelement location="${Etch.dependency.java.runtime}" />
+                <pathelement location="${Etch.dependency.junit.jar}" />
+            </classpath>
+        </javac>
+
+        <!-- Create Jar -->
+        <jar jarfile="${bin}/distmap.jar" >
+            <manifest>
+                <attribute name="Class-Path" value="${etch-java-runtime-name}" />
+            </manifest>
+            <fileset dir="${classes}" >
+                <include name="**/*" />
+            </fileset>
+        </jar>
+
+        <!-- copy in dependencies -->
+        <copy todir="${bin}" file="${Etch.dependency.java.runtime}" />
+    </target>
+
+    <target name="build-csharp-with-mono" depends="generate-sources" if="USE.mono" >
+        <mdtool dir="${src}/main/csharp/DistMapClientProj" project="DistMapClientProj.csproj" />
+        <mdtool dir="${src}/main/csharp/DistMapListenerProj" project="DistMapListenerProj.csproj" />
+    </target>
+
+    <target name="build-csharp-with-dotnet" depends="generate-sources" if="USE.dotnet" >
+        <msbuild buildfile="${src}/main/csharp/DistMapListenerProj/DistMapListenerProj.csproj" >
+            <property name="Configuration" value="${build.target}" />
+        </msbuild>
+        <msbuild buildfile="${src}/main/csharp/DistMapClientProj/DistMapClientProj.csproj" >
+            <property name="Configuration" value="${build.target}" />
+        </msbuild>
+        <msbuild buildfile="${src}/test/csharp/DistMapTestProj/DistMapTestProj.csproj" >
+            <property name="Configuration" value="${build.target}" />
+        </msbuild>
+        <copy todir="${bin}" >
+            <fileset dir="${src}/main/csharp/DistMapListenerProj/bin/${build.target}" >
+                <include name="*" />
+            </fileset>
+            <fileset dir="${src}/main/csharp/DistMapClientProj/bin/${build.target}" >
+                <include name="*" />
+            </fileset>
+        </copy>
+    </target>
+
+    <target name="build-csharp" depends="build-csharp-with-mono,build-csharp-with-dotnet" />
+
+    <target name="build" depends="build-java,build-csharp" />
+
+    <!-- run unit tests -->
+
+    <target name="test-java" depends="build-java" >
+        <!-- Run Unit Tests -->
+        <junit printsummary="yes" haltonfailure="no" dir="${classes-test}"
+            errorProperty="build.tests.fail" failureProperty="build.tests.fail" >
+            <classpath>
+                <pathelement location="${classes-test}" />
+                <pathelement location="${Etch.dependency.java.runtime}" />
+                <pathelement location="${Etch.dependency.junit.jar}" />
+            </classpath>
+            <formatter type="xml" />
+            <batchtest fork="true" todir="${test-results}" >
+                <fileset dir="${test-src-java}" >
+                    <include name="**/Test*.java" />
+                </fileset>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="test-csharp" depends="build-csharp" if="BUILD.csharp" >
+         <nunit xmlout="${nunit-results}/NUnitResults.xml">
+             <testassembly name="${src}/test/csharp/DistMapTestProj/bin/${build.target}/DistMapTestProj.dll" />
+         </nunit>
+
+         <xslt style="${Etch.buildSupportDirectory}/NUnitToJUnit.xsl"
+                 in="${nunit-results}/NUnitResults.xml" out="${test-results}/TEST-NUnitResults.xml" />
+   </target>
+
+    <target name="test" depends="build,test-java,test-csharp,done" >
+    </target>
+
+    <target name="done" depends="build" >
+        <echo>
+
+Build Complete!
+
+To run java distributed map, open a cmd window and run these
+commands:
+
+> cd target\bin
+> start java -cp distmap.jar org.apache.etch.examples.distmap.MainDistributedHashTableListener
+> start java -cp distmap.jar org.apache.etch.examples.distmap.MainDistributedHashTableClient
+
+To run csharp distributed map:
+
+> cd target\bin
+> start DistMapListener.exe
+> start DistMapClient.exe
+
+You can mix and match the various clients and listeners.
+
+        </echo>
+    </target>
+
+    <!-- build everything -->
+    <target name="init-debug" >
+        <property name="build.target" value="Debug" />
+    </target>
+
+    <target name="init-release" >
+        <property name="build.target" value="Release" />
+    </target>
+
+     <target name="dist-src" >
+         <copy file="dist-build.xml" tofile="${dist-src}/build.xml" overwrite="true" >
+             <filterset refid="Etch.buildTokens" />
+         </copy>
+        <copy file="README.txt" tofile="${dist-src}/README.txt" overwrite="true" />
+        
+        <copy todir="${dist-src}/src/main/etch" overwrite="true" >
+            <fileset dir="${src}/main/etch" >
+                <exclude name="**/.svn/**" />
+                <include name="**/*.etch" />
+            </fileset>
+        </copy>
+        
+        <copy todir="${dist-src}/src/main/java" overwrite="true" >
+            <fileset dir="${src}/main/java" >
+                <exclude name="**/.svn/**" />
+                <include name="**/*.java" />
+            </fileset>
+        </copy>
+        
+        <copy todir="${dist-src}/src/main/csharp" overwrite="true" >
+            <fileset dir="${src}/main/csharp" >
+                <exclude name="**/.svn/**" />
+                <include name="**/*.cs" />
+            </fileset>
+        </copy>
+        
+        <copy todir="${dist}/examples/distmap" overwrite="true" >
+            <fileset dir="${dist-src}" />
+        </copy>
+    </target>
+    
+    <target name="debug" depends="dist-src,init-debug,test" />
+    <target name="release" depends="dist-src,init-release,test" />
+
+    <!-- clean -->
+    <target name="clean" >
+        <delete dir="${target}" quiet="true" />
+        <delete dir="${src}/main/csharp/DistMapClientProj/bin" quiet="true" />
+        <delete dir="${src}/main/csharp/DistMapClientProj/obj" quiet="true" />
+        <delete dir="${src}/main/csharp/DistMapListenerProj/bin" quiet="true" />
+        <delete dir="${src}/main/csharp/DistMapListenerProj/obj" quiet="true" />
+        <delete dir="${src}/test/csharp/DistMapTestProj/bin" quiet="true" />
+        <delete dir="${src}/test/csharp/DistMapTestProj/obj" quiet="true" />
+    </target>
+</project>
diff --git a/examples/distmap/dist-build.xml b/examples/distmap/dist-build.xml
new file mode 100644
index 0000000..5667089
--- /dev/null
+++ b/examples/distmap/dist-build.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-distmap-example" basedir="." default="build">
+    <description>Distributed Map Example</description>
+
+    <property name="etch.home" location="${basedir}/../.."/>
+    <property name="etch.version" value="@EtchVersion@"/>
+    <property name="etch-java-runtime-name" value="etch-java-runtime-${etch.version}.jar"/>
+
+    <property name="etch-ant-plugin.jar"   location="${etch.home}/lib/etch-ant-plugin-${etch.version}.jar"/>
+    <property name="etch-java-runtime.jar" location="${etch.home}/lib/${etch-java-runtime-name}"/>
+    <property name="etch.dll"              location="${etch.home}/lib/Etch.dll"/>
+
+    <property name="src"               location="${basedir}/src"/>
+    <property name="src-main-etch"     location="${src}/main/etch"/>
+    <property name="src-main-java"     location="${src}/main/java"/>
+    <property name="src-main-csharp"   location="${src}/main/csharp"/>
+    <property name="target"            location="${basedir}/target"/>
+    <property name="generated-sources" location="${target}/generated-sources"/>
+    <property name="gensrc-main-etch-java" location="${generated-sources}/main/etch/java"/>
+    <property name="gensrc-main-etch-csharp" location="${generated-sources}/main/etch/csharp"/>
+    <property name="classes"           location="${target}/classes"/>
+    <property name="bin"               location="${target}/bin"/>
+    
+    <condition property="BUILD.csharp" >
+        <os family="windows" />
+    </condition>    
+
+    <taskdef
+        resource="org/apache/etch/tools/ant/etch.xml"
+        classpath="${etch-ant-plugin.jar}"/>
+
+    <target name="build" depends="build-java, build-csharp, done"/>
+
+    <target name="build-java" depends="gensrc-java">
+        <javac destdir="${classes}" source="1.5" debug="true">
+            <classpath>
+                <pathelement location="${etch-java-runtime.jar}"/>
+            </classpath>
+            <src path="${src-main-java}"/>
+            <src path="${gensrc-main-etch-java}"/>
+        </javac>
+
+        <jar jarfile="${bin}/distmap.jar">
+            <manifest>
+                <attribute name="Class-Path" value="${etch-java-runtime-name}"/>
+            </manifest>
+            <fileset dir="${classes}"/>
+        </jar>
+
+        <copy todir="${bin}" file="${etch-java-runtime.jar}"/>
+    </target>
+
+    <target name="done">
+        <echo>
+
+To run java distributed map, open a cmd window and run these
+commands:
+
+> cd target\bin
+> start java -cp distmap.jar etch.examples.distmap.MainDistributedHashTableListener
+> start java -cp distmap.jar etch.examples.distmap.MainDistributedHashTableClient
+
+To run csharp distributed map:
+
+> cd target\bin
+> start DistMapListener.exe
+> start DistMapClient.exe
+
+You can mix and match the various clients and listeners.
+
+        </echo>
+    </target>
+
+    <target name="build-csharp" depends="gensrc-csharp" if="BUILD.csharp" >
+        <csc
+                debug="true"
+                warnLevel="1"
+                unsafe="false"
+                targetType="exe"
+                incremental="false"
+                mainClass = "etch.examples.distmap.MainDistributedHashTableClient"
+                destFile="${bin}/DistMapClient.exe">
+            <src dir="${src-main-csharp}/DistMapClientProj" includes="**/*.cs"/>
+            <src dir="${src-main-csharp}/etch.examples.distmap" includes="**/*.cs"/>
+            <src dir="${gensrc-main-etch-csharp}" includes="**/*.cs"/>
+            <reference file="${etch.dll}"/>
+        </csc>
+
+        <csc
+                debug="true"
+                warnLevel="1"
+                unsafe="false"
+                targetType="exe"
+                incremental="false"
+                mainClass = "etch.examples.distmap.MainDistributedHashTableListener"
+                destFile="${bin}/DistMapListener.exe">
+            <src dir="${src-main-csharp}/DistMapListenerProj" includes="**/*.cs"/>
+            <src dir="${src-main-csharp}/etch.examples.distmap" includes="**/*.cs"/>
+            <src dir="${gensrc-main-etch-csharp}" includes="**/*.cs"/>
+            <reference file="${etch.dll}"/>
+        </csc>
+
+        <copy todir="${bin}" file="${etch.dll}"/>
+    </target>
+
+    <target name="gensrc" depends="gensrc-java, gensrc-csharp"/>
+
+    <target name="gensrc-java" depends="init">
+        <etch
+            home="${etch.home}"
+            binding="java"
+            quiet="true"
+            outputDir="${gensrc-main-etch-java}"
+            file="${src-main-etch}/DistributedHashTable.etch"/>
+    </target>
+
+    <target name="gensrc-csharp" depends="init">
+        <etch
+            home="${etch.home}"
+            binding="csharp"
+            quiet="true"
+            outputDir="${gensrc-main-etch-csharp}"
+            file="${src-main-etch}/DistributedHashTable.etch"/>
+    </target>
+
+    <target name="init">
+        <mkdir dir="${target}"/>
+        <mkdir dir="${generated-sources}"/>
+        <mkdir dir="${gensrc-main-etch-java}"/>
+        <mkdir dir="${gensrc-main-etch-csharp}"/>
+        <mkdir dir="${classes}"/>
+        <mkdir dir="${bin}"/>
+    </target>
+
+    <target name="clean">
+        <delete dir="${target}"/>
+    </target>
+</project>
diff --git a/examples/distmap/src/main/csharp/DistMapClientProj/DistMapClientProj.csproj b/examples/distmap/src/main/csharp/DistMapClientProj/DistMapClientProj.csproj
new file mode 100644
index 0000000..43a2f65
--- /dev/null
+++ b/examples/distmap/src/main/csharp/DistMapClientProj/DistMapClientProj.csproj
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{7613961B-FD82-40DB-BF99-EEF50BB20887}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>etch.examples.distmap</RootNamespace>
+    <AssemblyName>DistMapClient</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+  <ItemGroup>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\BaseDistributedHashTableClient.cs">
+      <Link>BaseDistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\BaseDistributedHashTableServer.cs">
+      <Link>BaseDistributedHashTableServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\DistributedHashTable.cs">
+      <Link>DistributedHashTable.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\DistributedHashTableClient.cs">
+      <Link>DistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\DistributedHashTableHelper.cs">
+      <Link>DistributedHashTableHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\DistributedHashTableServer.cs">
+      <Link>DistributedHashTableServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\RemoteDistributedHashTable.cs">
+      <Link>RemoteDistributedHashTable.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\RemoteDistributedHashTableClient.cs">
+      <Link>RemoteDistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\RemoteDistributedHashTableServer.cs">
+      <Link>RemoteDistributedHashTableServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\StubDistributedHashTable.cs">
+      <Link>StubDistributedHashTable.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\StubDistributedHashTableClient.cs">
+      <Link>StubDistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\StubDistributedHashTableServer.cs">
+      <Link>StubDistributedHashTableServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\ValueFactoryDistributedHashTable.cs">
+      <Link>ValueFactoryDistributedHashTable.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.distmap\ImplDistributedHashTableClient.cs">
+      <Link>ImplDistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.distmap\MainDistributedHashTableClient.cs">
+      <Link>MainDistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\..\..\binding-csharp\runtime\src\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+    <Reference Include="System" />
+  </ItemGroup>
+</Project>
diff --git a/examples/distmap/src/main/csharp/DistMapClientProj/Properties/AssemblyInfo.cs b/examples/distmap/src/main/csharp/DistMapClientProj/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e3ea962
--- /dev/null
+++ b/examples/distmap/src/main/csharp/DistMapClientProj/Properties/AssemblyInfo.cs
@@ -0,0 +1,48 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("DistMap Client")]
+[assembly: AssemblyDescription("DistMap Client Executable")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Cisco Systems")]
+[assembly: AssemblyProduct("Etch")]
+[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("3dc993f2-72bd-4439-a164-e4fca84ad70e")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+[assembly: AssemblyVersion("0.0.0.1")]
+[assembly: AssemblyFileVersion("0.0.0.1")]
diff --git a/examples/distmap/src/main/csharp/DistMapListenerProj/DistMapListenerProj.csproj b/examples/distmap/src/main/csharp/DistMapListenerProj/DistMapListenerProj.csproj
new file mode 100644
index 0000000..531f328
--- /dev/null
+++ b/examples/distmap/src/main/csharp/DistMapListenerProj/DistMapListenerProj.csproj
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{75F8A513-4500-4AC3-8E97-8B7609A8AEA9}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>etch.examples.distmap</RootNamespace>
+    <AssemblyName>DistMapListener</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+  <ItemGroup>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\BaseDistributedHashTableClient.cs">
+      <Link>BaseDistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\BaseDistributedHashTableServer.cs">
+      <Link>BaseDistributedHashTableServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\DistributedHashTable.cs">
+      <Link>DistributedHashTable.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\DistributedHashTableClient.cs">
+      <Link>DistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\DistributedHashTableHelper.cs">
+      <Link>DistributedHashTableHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\DistributedHashTableServer.cs">
+      <Link>DistributedHashTableServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\RemoteDistributedHashTable.cs">
+      <Link>RemoteDistributedHashTable.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\RemoteDistributedHashTableClient.cs">
+      <Link>RemoteDistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\RemoteDistributedHashTableServer.cs">
+      <Link>RemoteDistributedHashTableServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\StubDistributedHashTable.cs">
+      <Link>StubDistributedHashTable.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\StubDistributedHashTableClient.cs">
+      <Link>StubDistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\StubDistributedHashTableServer.cs">
+      <Link>StubDistributedHashTableServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\ValueFactoryDistributedHashTable.cs">
+      <Link>ValueFactoryDistributedHashTable.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.distmap\ImplDistributedHashTableServer.cs">
+      <Link>ImplDistributedHashTableServer.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.distmap\MainDistributedHashTableListener.cs">
+      <Link>MainDistributedHashTableListener.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\..\..\binding-csharp\runtime\src\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+    <Reference Include="System" />
+  </ItemGroup>
+</Project>
diff --git a/examples/distmap/src/main/csharp/DistMapListenerProj/Properties/AssemblyInfo.cs b/examples/distmap/src/main/csharp/DistMapListenerProj/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..13463ce
--- /dev/null
+++ b/examples/distmap/src/main/csharp/DistMapListenerProj/Properties/AssemblyInfo.cs
@@ -0,0 +1,48 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("DistMap Listener")]
+[assembly: AssemblyDescription("DistMap Listener Executable")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Cisco Systems")]
+[assembly: AssemblyProduct("Etch")]
+[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("71167bc3-220f-4915-b709-708cf59e7d99")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+[assembly: AssemblyVersion("0.0.0.1")]
+[assembly: AssemblyFileVersion("0.0.0.1")]
diff --git a/examples/distmap/src/main/csharp/etch.examples.distmap/ImplDistributedHashTableClient.cs b/examples/distmap/src/main/csharp/etch.examples.distmap/ImplDistributedHashTableClient.cs
new file mode 100644
index 0000000..e63d863
--- /dev/null
+++ b/examples/distmap/src/main/csharp/etch.examples.distmap/ImplDistributedHashTableClient.cs
@@ -0,0 +1,40 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace org.apache.etch.examples.distmap
+{
+	///<summary>Implementation for ImplDistributedHashTableClient</summary>
+	public class ImplDistributedHashTableClient : BaseDistributedHashTableClient
+	{
+		/// <summary>Constructs the ImplDistributedHashTableClient.</summary>
+ 		/// <param name="server">a connection to the server session. Use this to
+ 		/// send a message to the server.</param>
+		public ImplDistributedHashTableClient(RemoteDistributedHashTableServer server)
+		{
+			this.server = server;
+		}
+		
+		/// <summary>A connection to the server session. Use this to
+ 		/// send a message to the server.</summary>
+		private readonly RemoteDistributedHashTableServer server;
+	
+		// TODO: Implement delegates or provide implementation of DistributedHashTableClient
+		// messages from the server	
+	}
+}
\ No newline at end of file
diff --git a/examples/distmap/src/main/csharp/etch.examples.distmap/ImplDistributedHashTableServer.cs b/examples/distmap/src/main/csharp/etch.examples.distmap/ImplDistributedHashTableServer.cs
new file mode 100644
index 0000000..cdef919
--- /dev/null
+++ b/examples/distmap/src/main/csharp/etch.examples.distmap/ImplDistributedHashTableServer.cs
@@ -0,0 +1,107 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using org.apache.etch.examples.distmap.types.DistributedHashTable;
+
+namespace org.apache.etch.examples.distmap
+{
+    ///<summary>Implementation for ImplDistributedHashTableServer</summary>
+    public class ImplDistributedHashTableServer : BaseDistributedHashTableServer
+    {
+        /// <summary>Constructs the ImplDistributedHashTableServer.</summary>
+        /// <param name="client">a connection to the client session. Use this to
+        /// send a message to the client.</param>
+        /// <param name="map"></param>
+        public ImplDistributedHashTableServer(RemoteDistributedHashTableClient client, IDictionary<string, object> map)
+        {
+            this.map = map;
+        }
+
+        private IDictionary<string, object> map;
+
+
+        /// <summary>
+        /// Gets all elements in DHT
+        /// </summary>
+        /// <returns>An array of entries</returns>
+        public override Entry[] getAll()
+        {
+            lock (map)
+            {
+                Entry[] list = new Entry[map.Count];
+                int index = 0;
+                foreach (string str in map.Keys)
+                {
+                    list[index++] = new Entry(str, map[str]);
+                }
+                return list;
+            }
+        }
+        /// <summary>
+        /// Gets an object from DHT
+        /// </summary>
+        /// <param name="key"></param>
+        /// <returns></returns>
+        public override object getObject(string key)
+        {
+            object value;
+            if (!map.TryGetValue(key, out value))
+            {
+                Console.WriteLine(" {0} not found in DHT ", key);
+            }
+
+            return value;
+        }
+
+        /// <summary>
+        /// Puts object in Map
+        /// </summary>
+        /// <param name="key"></param>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public override object putObject(string key, object value)
+        {
+            map.Add(key, value);
+            return value;
+        }
+
+
+        /// <summary>
+        /// Removes Object from DHT
+        /// </summary>
+        /// <param name="key"></param>
+        /// <returns></returns>
+        public override object removeObject(string key)
+        {
+            map.Remove(key);
+            return null;
+        }
+    
+        /// <summary>
+        /// Gets Size of DHT
+        /// </summary>
+        /// <returns></returns>
+        public override int? size()
+        {
+            return map.Count;
+        }
+    }
+}
\ No newline at end of file
diff --git a/examples/distmap/src/main/csharp/etch.examples.distmap/MainDistributedHashTableClient.cs b/examples/distmap/src/main/csharp/etch.examples.distmap/MainDistributedHashTableClient.cs
new file mode 100644
index 0000000..5d5f16b
--- /dev/null
+++ b/examples/distmap/src/main/csharp/etch.examples.distmap/MainDistributedHashTableClient.cs
@@ -0,0 +1,161 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using org.apache.etch.examples.distmap.types.DistributedHashTable;
+
+namespace org.apache.etch.examples.distmap
+{
+    ///<summary>Main implementation for DistributedHashTableClient.</summary>
+    public class MainDistributedHashTableClient : DistributedHashTableHelper.DistributedHashTableClientFactory
+    {
+        ///<summary>Main for DistributedHashTableClient</summary>
+        ///<param name="args">Command Line Arguments</param>
+        public static void Main(String[] args)
+        {
+            // TODO: Change to correct URI
+            string uri = "tcp://localhost:4007";
+
+            RemoteDistributedHashTableServer server = DistributedHashTableHelper.NewServer(uri, null, new MainDistributedHashTableClient());
+
+            // Connect to the service
+            server._StartAndWaitUp(4000);
+
+            const bool myBool1 = true;
+            const sbyte myByte1 = 1;
+            const short myShort1 = 234;
+            const int myInt1 = 345345;
+            const long myLong1 = 456456456456L;
+            const float myFloat1 = 1.234f;
+            const double myDouble1 = 2.345;
+            const string myString1 = "abc";
+
+            object myObj;
+
+            Console.WriteLine("DHT sixe is " + server.size());
+
+            // getAll - DHT is empty
+            foreach (Entry entry in server.getAll())
+                Console.WriteLine("getAll: {0},{1} ", entry.key, entry.value);
+
+            // putObject for each constant type
+            server.putObject("boolean1", myBool1);
+            Console.WriteLine("Put {0} in DHT", myBool1);
+
+            server.putObject("byte1", myByte1);
+            Console.WriteLine("Put {0} in DHT", myByte1);
+
+
+            server.putObject("short1", myShort1);
+            Console.WriteLine("Put {0} in DHT", myShort1);
+
+            server.putObject("int1", myInt1);
+            Console.WriteLine("Put {0} in DHT", myInt1);
+
+            server.putObject("long1", myLong1);
+            Console.WriteLine("Put {0} in DHT", myLong1);
+
+            server.putObject("float1", myFloat1);
+            Console.WriteLine("Put {0} in DHT", myFloat1);
+
+            server.putObject("double1", myDouble1);
+            Console.WriteLine("Put {0} in DHT", myDouble1);
+
+            server.putObject("string1", myString1);
+            Console.WriteLine("Put {0} in DHT", myString1);
+
+            // size - DHT has entries
+            Console.WriteLine("DHT Size is {0} ", server.size());
+
+            // getAll - DHT has entries
+            foreach (Entry entry in server.getAll())
+                Console.WriteLine("getAll: {0} {1} ", entry.key, entry.value);
+
+            // getObject for each constant type
+            myObj = server.getObject("boolean1");
+            Console.WriteLine("Value of myBool1 is {0} ", myObj);
+
+            myObj = server.getObject("byte1");
+            Console.WriteLine("Value of myByte1 is {0} ", myObj);
+
+            myObj = server.getObject("short1");
+            Console.WriteLine("Value of myShort1 is {0} ", myObj);
+
+            myObj = server.getObject("int1");
+            Console.WriteLine("Value of myInt1 is {0} ", myObj);
+
+            myObj = server.getObject("long1");
+            Console.WriteLine("Value of myLong1 is {0} ", myObj);
+
+            myObj = server.getObject("float1");
+            Console.WriteLine("Value of myFloat1 is {0} ", myObj);
+
+            myObj = server.getObject("double1");
+            Console.WriteLine("Value of myDouble1 is {0} ", myObj);
+
+            myObj = server.getObject("string1");
+            Console.WriteLine("Value of myString1 is {0} ", myObj);
+
+            // removeObject for each constant type
+            server.removeObject("boolean1");
+            Console.WriteLine("removing Object boolean1 ");
+
+            server.removeObject("byte1");
+            Console.WriteLine("removing Object byte1 ");
+
+            server.removeObject("short1");
+            Console.WriteLine("removing Object short1 ");
+
+            server.removeObject("int1");
+            Console.WriteLine("removing Object int1 ");
+
+            server.removeObject("long1");
+            Console.WriteLine("removing Object long1 ");
+
+            server.removeObject("float1");
+            Console.WriteLine("removing Object float1 ");
+
+            server.removeObject("double1");
+            Console.WriteLine("removing Object double1 ");
+
+            server.removeObject("string1");
+            Console.WriteLine("removing Object string1 ");
+
+            // size - Verify that DHT is empty after removing all items
+            Console.WriteLine("DHT Size is {0}", server.size());
+
+            // getAll - Verify that DHT is empty after removing all items
+            foreach (Entry entry in server.getAll())
+                Console.WriteLine("getAll: {0} {1} ", entry.key, entry.value);
+
+            Console.WriteLine("Have a nice day!");
+
+            // Disconnect from the service
+            server._StopAndWaitDown(4000);
+        }
+
+        ///<summary>Return a new instance of DistributedHashTableClient.</summary>
+        ///<param name="server">Reference to remote service</param>
+        ///<returns>Client Implementation</returns>
+        public DistributedHashTableClient NewDistributedHashTableClient(RemoteDistributedHashTableServer server)
+        {
+            return new ImplDistributedHashTableClient(server);
+        }
+    }
+}
\ No newline at end of file
diff --git a/examples/distmap/src/main/csharp/etch.examples.distmap/MainDistributedHashTableListener.cs b/examples/distmap/src/main/csharp/etch.examples.distmap/MainDistributedHashTableListener.cs
new file mode 100644
index 0000000..5bfcdf2
--- /dev/null
+++ b/examples/distmap/src/main/csharp/etch.examples.distmap/MainDistributedHashTableListener.cs
@@ -0,0 +1,55 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace org.apache.etch.examples.distmap
+{
+	///<summary>Main implementation for DistributedHashTableListener.</summary>
+	public class MainDistributedHashTableListener : DistributedHashTableHelper.DistributedHashTableServerFactory
+	{
+ 		///<summary>Main for DistributedHashTableListener.</summary>
+		///<param name="args">Command Line Arguments</param>
+		public static void Main(String[] args)
+		{
+			// TODO: Change to correct URI
+			string uri = "tcp://localhost:4007";
+
+            ServerFactory listener = DistributedHashTableHelper.NewListener(uri, null, new MainDistributedHashTableListener());
+			
+			// Start the Listener
+			listener.TransportControl( TransportConsts.START_AND_WAIT_UP, 4000 );
+
+            Console.WriteLine("Listener Started !!!");
+		}
+
+        private IDictionary<string ,object > map = new Dictionary<string, object>();
+
+		///<summary>Return a new instance of DistributedHashTableServer.</summary>
+		///<param name="client">Reference to remote service</param>
+		///<returns>Server Implementation</returns>
+		public DistributedHashTableServer NewDistributedHashTableServer( RemoteDistributedHashTableClient client )
+		{
+			return new ImplDistributedHashTableServer( client,map );
+		}
+	}
+}
\ No newline at end of file
diff --git a/examples/distmap/src/main/etch/DistributedHashTable.etch b/examples/distmap/src/main/etch/DistributedHashTable.etch
new file mode 100644
index 0000000..b6a248a
--- /dev/null
+++ b/examples/distmap/src/main/etch/DistributedHashTable.etch
@@ -0,0 +1,71 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.examples.distmap
+
+/**
+ * The DistributedHashTable example program implements a simple service
+ * for modifying a distributed hash table.
+ */
+service DistributedHashTable
+{
+	/**
+	 * Puts a value in the hash table.
+	 *
+	 * @param key the key for the value.
+	 * @param value the value of the key.
+	 * @return the old value of the key, or null if this is a new entry.
+	 */
+	object putObject(string key, object value)
+
+	/**
+	 * Gets a value from the hash table.
+	 *
+	 * @param key the key for the value.
+	 * @return the value of the key, or null if there is no entry for the key.
+	 */
+	object getObject(string key)
+	
+	/**
+	 * Removes the value from the hash table.
+	 *
+	 * @param key the key for the value.
+	 * @return the old value of the key, or null if there was no entry for
+	 * the key.
+	 */
+	object removeObject(string key)
+ 	
+	/**
+ 	 * An entry in the hash table.
+ 	 * @param key the key for the value.
+ 	 * @param value the value of the key.
+ 	 */
+	struct Entry(string key, object value)
+ 	
+	/**
+ 	 * Gets all entries in the hash table.
+ 	 *
+ 	 * @return an array of all the entries in the hash table.
+ 	 */
+	Entry[] getAll()
+
+	/**
+	 * Gets the number of entries in the hash table.
+	 * @return size of the hash table.
+	 */
+	int size()
+}
\ No newline at end of file
diff --git a/examples/distmap/src/main/etch/readme.txt b/examples/distmap/src/main/etch/readme.txt
new file mode 100644
index 0000000..0c69c29
--- /dev/null
+++ b/examples/distmap/src/main/etch/readme.txt
@@ -0,0 +1,4 @@
+from this directory, etch like this:
+
+etch -b java   -d ../../../target/generated-sources/main/etch/java   DistributedHashTable.etch
+etch -b chsarp -d ../../../target/generated-sources/main/etch/csharp DistributedHashTable.etch
diff --git a/examples/distmap/src/main/java/org/apache/etch/examples/distmap/ImplDistributedHashTableClient.java b/examples/distmap/src/main/java/org/apache/etch/examples/distmap/ImplDistributedHashTableClient.java
new file mode 100644
index 0000000..167ad1e
--- /dev/null
+++ b/examples/distmap/src/main/java/org/apache/etch/examples/distmap/ImplDistributedHashTableClient.java
@@ -0,0 +1,46 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.distmap;
+
+
+/**
+ * Your custom implementation of BaseDistributedHashTableClient. Add methods here to provide
+ * implementations of messages from the server.
+ */
+public class ImplDistributedHashTableClient extends BaseDistributedHashTableClient
+{
+	/**
+	 * Constructs the ImplDistributedHashTableClient.
+	 *
+	 * @param server a connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	public ImplDistributedHashTableClient( RemoteDistributedHashTableServer server )
+	{
+		this.server = server;
+	}
+	
+	@SuppressWarnings("unused")
+	private final RemoteDistributedHashTableServer server;
+
+	// TODO insert methods here to provide implementations of DistributedHashTableClient
+	// messages from the server.
+}
\ No newline at end of file
diff --git a/examples/distmap/src/main/java/org/apache/etch/examples/distmap/ImplDistributedHashTableServer.java b/examples/distmap/src/main/java/org/apache/etch/examples/distmap/ImplDistributedHashTableServer.java
new file mode 100644
index 0000000..560e00e
--- /dev/null
+++ b/examples/distmap/src/main/java/org/apache/etch/examples/distmap/ImplDistributedHashTableServer.java
@@ -0,0 +1,115 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.distmap;
+
+import java.util.Map;
+
+
+/**
+ * Your custom implementation of BaseDistributedHashTableServer. Add methods here to provide
+ * implementations of messages from the client.
+ */
+public class ImplDistributedHashTableServer extends BaseDistributedHashTableServer
+{
+	/**
+	 * Constructs the ImplDistributedHashTableServer.
+	 *
+	 * @param client a connection to the client session. Use this to send a
+	 * message to the client.
+	 * @param map the global map.
+	 */
+	public ImplDistributedHashTableServer( RemoteDistributedHashTableClient client,
+		Map<String, Object> map )
+	{
+		this.client = client;
+		this.map = map;
+	}
+	
+	@SuppressWarnings("unused")
+	private final RemoteDistributedHashTableClient client;
+	
+	private final Map<String, Object> map;
+
+	/**
+	 * Gets all entries in the hash table.
+	 * 
+	 * @return an array of entries
+	 */
+	@Override
+	public Entry[] getAll()
+	{
+		synchronized (map)
+		{
+			Entry[] list = new Entry[map.size()];
+			int index = 0;
+			for (Map.Entry<String, Object> me : map.entrySet())
+				list[index++] = new Entry( me.getKey(), me.getValue() );
+			return list;
+		}
+	}
+
+	/**
+	 * Gets the value to which key is mapped
+	 * 
+	 * @param key key associated with value
+	 * @return the value to which the key is mapped
+	 */
+	@Override
+	public Object getObject( String key )
+	{
+		return map.get( key );
+	}
+
+	/**
+	 * Adds a key-value mapping to the map
+	 * 
+	 * @param key the key
+	 * @param value the value
+	 */
+	@Override
+	public Object putObject( String key, Object value )
+	{
+		return map.put( key, value );
+	}
+
+	/**
+	 * Removes a key-value mapping from the map
+	 * 
+	 * @param key the key
+	 * @return the value associated with key
+	 */
+	@Override
+	public Object removeObject( String key )
+	{
+		return map.remove( key );
+	}
+
+	/**
+	 * Get the number of key-value mappings in this map
+	 * 
+	 * @return the number of key-value mappings in this map
+	 */
+	@Override
+	public Integer size()
+	{
+		return map.size();
+	}
+}
\ No newline at end of file
diff --git a/examples/distmap/src/main/java/org/apache/etch/examples/distmap/MainDistributedHashTableClient.java b/examples/distmap/src/main/java/org/apache/etch/examples/distmap/MainDistributedHashTableClient.java
new file mode 100644
index 0000000..b7df2ff
--- /dev/null
+++ b/examples/distmap/src/main/java/org/apache/etch/examples/distmap/MainDistributedHashTableClient.java
@@ -0,0 +1,168 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.distmap;
+
+import org.apache.etch.examples.distmap.DistributedHashTable.Entry;
+import org.apache.etch.util.Log;
+
+
+/**
+ * Main program for DistributedHashTableClient. This program makes a connection to the
+ * listener created by MainDistributedHashTableListener.
+ */
+public class MainDistributedHashTableClient implements DistributedHashTableHelper.DistributedHashTableClientFactory
+{
+	/**
+	 * Main program for DistributedHashTableClient.
+	 * 
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		String uri = "tcp://localhost:4007";
+		
+		RemoteDistributedHashTableServer server = DistributedHashTableHelper.newServer( uri, null,
+			new MainDistributedHashTableClient() );
+
+		server._startAndWaitUp( 4000 );
+
+		final boolean myBool1 = true;
+		final byte myByte1 = 1;
+		final short myShort1 = 234;
+		final int myInt1 = 345345;
+		final long myLong1 = 456456456456L;
+		final float myFloat1 = 1.234f;
+		final double myDouble1 = 2.345;
+		final String myString1 = "abc";	
+		
+		Object myObj;
+
+		// Start testing
+		Log.addSink( null );
+		
+		// size - DHT is empty
+		Log.report("DHT", "Size", server.size());
+		
+		// getAll - DHT is empty
+		for(Entry entry: server.getAll())
+			Log.report("getAll: ", entry.key, entry.value);
+		
+		// putObject for each constant type
+		server.putObject("boolean1", myBool1);
+		Log.report("putObject", "boolean value", myBool1);
+		
+		server.putObject("byte1", myByte1);
+		Log.report("putObject", "byte value", myByte1);
+		
+		server.putObject("short1", myShort1);
+		Log.report("putObject", "short value", myShort1);
+
+		server.putObject("int1", myInt1);
+		Log.report("putObject", "int value", myInt1);
+
+		server.putObject("long1", myLong1);
+		Log.report("putObject", "long value", myLong1);
+
+		server.putObject("float1", myFloat1);
+		Log.report("putObject", "float value", myFloat1);
+
+		server.putObject("double1", myDouble1);
+		Log.report("putObject", "double value", myDouble1);
+		
+		server.putObject("string1", myString1);
+		Log.report("putObject", "string value", myString1);	
+		
+		// size - DHT has entries
+		Log.report("DHT", "Size", server.size());
+		
+		// getAll - DHT has entries
+		for(Entry entry: server.getAll())
+			Log.report("getAll: ", entry.key, entry.value);
+			
+		// getObject for each constant type
+		myObj = server.getObject("boolean1");
+		Log.report("getObject", "myBool1", myObj);
+		
+		myObj = server.getObject("byte1");
+		Log.report("getObject", "myByte1", myObj);	
+		
+		myObj = server.getObject("short1");
+		Log.report("getObject", "myShort1", myObj);	
+		
+		myObj = server.getObject("int1");
+		Log.report("getObject", "myInt1", myObj);	
+		
+		myObj = server.getObject("long1");
+		Log.report("getObject", "myLong1", myObj);	
+		
+		myObj = server.getObject("float1");
+		Log.report("getObject", "myFloat1", myObj);	
+		
+		myObj = server.getObject("double1");
+		Log.report("getObject", "myDouble1", myObj);	
+		
+		myObj = server.getObject("string1");
+		Log.report("getObject", "myString1", myObj);
+		
+		// removeObject for each constant type
+		myObj = server.removeObject("boolean1");
+		Log.report("removeObject", "boolean value", myObj);
+		
+		myObj = server.removeObject("byte1");
+		Log.report("removeObject", "byte value", myObj);	
+		
+		myObj = server.removeObject("short1");
+		Log.report("removeObject", "short value", myObj);	
+		
+		myObj = server.removeObject("int1");
+		Log.report("removeObject", "int value", myObj);	
+		
+		myObj = server.removeObject("long1");
+		Log.report("removeObject", "long value", myObj);	
+		
+		myObj = server.removeObject("float1");
+		Log.report("removeObject", "float value", myObj);	
+		
+		myObj = server.removeObject("double1");
+		Log.report("removeObject", "double value", myObj);	
+				
+		myObj = server.removeObject("string1");
+		Log.report("removeObject", "string value", myObj);
+		
+		// size - Verify that DHT is empty after removing all items
+		Log.report("DHT", "Size", server.size());
+		
+		// getAll - Verify that DHT is empty after removing all items
+		for(Entry entry: server.getAll())
+			Log.report("getAll: ", entry.key, entry.value);
+				
+		Log.report("Have a nice day!");
+
+		server._stopAndWaitDown( 4000 );
+	}
+
+	public DistributedHashTableClient newDistributedHashTableClient( RemoteDistributedHashTableServer server )
+		throws Exception
+	{
+		return new ImplDistributedHashTableClient( server );
+	}
+}
diff --git a/examples/distmap/src/main/java/org/apache/etch/examples/distmap/MainDistributedHashTableListener.java b/examples/distmap/src/main/java/org/apache/etch/examples/distmap/MainDistributedHashTableListener.java
new file mode 100644
index 0000000..0c8303e
--- /dev/null
+++ b/examples/distmap/src/main/java/org/apache/etch/examples/distmap/MainDistributedHashTableListener.java
@@ -0,0 +1,61 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.distmap;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.util.core.io.Transport;
+
+
+
+/**
+ * Main program for DistributedHashTableServer. This program makes a listener to accept
+ * connections from MainDistributedHashTableClient.
+ */
+public class MainDistributedHashTableListener implements DistributedHashTableHelper.DistributedHashTableServerFactory
+{
+	/**
+	 * Main program for DistributedHashTableServer.
+	 * 
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		String uri = "tcp://0.0.0.0:4007";
+		
+		ServerFactory listener = DistributedHashTableHelper.newListener( uri, null,
+			new MainDistributedHashTableListener() );
+
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+	}
+	
+	private final Map<String, Object> map =
+		Collections.synchronizedMap( new HashMap<String, Object>() );
+
+	public DistributedHashTableServer newDistributedHashTableServer( RemoteDistributedHashTableClient client )
+	{
+		return new ImplDistributedHashTableServer( client, map );
+	}
+}
diff --git a/examples/distmap/src/test/csharp/DistMapTestProj/DistMapTestProj.csproj b/examples/distmap/src/test/csharp/DistMapTestProj/DistMapTestProj.csproj
new file mode 100644
index 0000000..201dd36
--- /dev/null
+++ b/examples/distmap/src/test/csharp/DistMapTestProj/DistMapTestProj.csproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{39699FEE-D21E-42AC-ADD7-22484A985C27}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>DistMapTestProj</RootNamespace>
+    <AssemblyName>DistMapTestProj</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="nunit.framework, Version=2.4.7.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>$(NUNIT_HOME)\bin\nunit.framework.dll</HintPath>
+      <SpecificVersion>False</SpecificVersion>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\BaseDistributedHashTableClient.cs">
+      <Link>BaseDistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\BaseDistributedHashTableServer.cs">
+      <Link>BaseDistributedHashTableServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\DistributedHashTable.cs">
+      <Link>DistributedHashTable.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\DistributedHashTableClient.cs">
+      <Link>DistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\DistributedHashTableHelper.cs">
+      <Link>DistributedHashTableHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\DistributedHashTableServer.cs">
+      <Link>DistributedHashTableServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\RemoteDistributedHashTable.cs">
+      <Link>RemoteDistributedHashTable.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\RemoteDistributedHashTableClient.cs">
+      <Link>RemoteDistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\RemoteDistributedHashTableServer.cs">
+      <Link>RemoteDistributedHashTableServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\StubDistributedHashTable.cs">
+      <Link>StubDistributedHashTable.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\StubDistributedHashTableClient.cs">
+      <Link>StubDistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\StubDistributedHashTableServer.cs">
+      <Link>StubDistributedHashTableServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.distmap\ValueFactoryDistributedHashTable.cs">
+      <Link>ValueFactoryDistributedHashTable.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.distmap\ImplDistributedHashTableClient.cs">
+      <Link>ImplDistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.distmap\ImplDistributedHashTableServer.cs">
+      <Link>ImplDistributedHashTableServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.distmap\MainDistributedHashTableClient.cs">
+      <Link>MainDistributedHashTableClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.distmap\MainDistributedHashTableListener.cs">
+      <Link>MainDistributedHashTableListener.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.distmap\TestDistributedHashTable.cs">
+      <Link>TestDistributedHashTable.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\..\..\binding-csharp\runtime\src\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/examples/distmap/src/test/csharp/DistMapTestProj/Properties/AssemblyInfo.cs b/examples/distmap/src/test/csharp/DistMapTestProj/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..9b98660
--- /dev/null
+++ b/examples/distmap/src/test/csharp/DistMapTestProj/Properties/AssemblyInfo.cs
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("DistMapTest Project")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Cisco Systems, Inc.")]
+[assembly: AssemblyProduct("DistMapTestProj")]
+[assembly: AssemblyCopyright("Copyright ©  2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("dc803e45-8232-4255-b615-c96d1ded9df8")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/examples/distmap/src/test/csharp/etch.examples.distmap/TestDistributedHashTable.cs b/examples/distmap/src/test/csharp/etch.examples.distmap/TestDistributedHashTable.cs
new file mode 100644
index 0000000..d8e6290
--- /dev/null
+++ b/examples/distmap/src/test/csharp/etch.examples.distmap/TestDistributedHashTable.cs
@@ -0,0 +1,233 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+using org.apache.etch.examples.distmap.types.DistributedHashTable;
+
+namespace org.apache.etch.examples.distmap
+{
+
+    /// <summary>
+    /// Unit Tests to test DistributedHashTable
+    /// </summary>
+    [TestFixture]
+    public class TestDistributedHashTable
+    {
+        private static RemoteDistributedHashTableServer server;
+
+        private static ServerFactory listener;
+
+        public const bool myBool1 = true;
+        public const sbyte myByte1 = 127;
+        public const short myShort1 = 32767;
+        public const int myInt1 = 2147483647;
+        public const long myLong1 = 9223372036854775807L;
+        public const float myFloat1 = 3.4028235e38f;
+        public const double myDouble1 = 1.7976931348623157e308d;
+        public const string myString1 = "abc";
+
+        [TestFixtureSetUp]
+        public void StartListener()
+        {
+            String uri = "tcp://localhost:4010";
+
+            MainDistributedHashTableListener implFactory = new MainDistributedHashTableListener();
+            listener = DistributedHashTableHelper.NewListener(uri, null, implFactory);
+
+            listener.TransportControl(TransportConsts.START_AND_WAIT_UP, 4000);
+
+            Console.WriteLine("Listener Started");
+
+        }
+
+        [SetUp]
+        public void MakeConnection()
+        {
+            String uri = "tcp://localhost:4010";
+
+            MainDistributedHashTableClient client = new MainDistributedHashTableClient();
+            server = DistributedHashTableHelper.NewServer(uri, null, client);
+
+            server._StartAndWaitUp(4000);
+        }
+
+        [ Test ]
+        public void TestBoolean()
+        {
+            server.putObject("boolean1",myBool1);
+            Object myObj = server.getObject("boolean1");
+            Assert.AreEqual(myBool1,myObj);
+
+            server.removeObject("boolean1");
+            myObj = server.getObject("boolean1");
+            Assert.IsNull(myObj);
+        }
+
+        [Test]
+        public void TestByte()
+        {
+            server.putObject("byte1", myByte1);
+            Object myObj = server.getObject("byte1");
+            Assert.AreEqual(myByte1, myObj);
+
+            server.removeObject("byte1");
+            myObj = server.getObject("byte1");
+            Assert.IsNull(myObj);
+        }
+
+        [Test]
+        public void TestShort()
+        {
+            server.putObject("short1", myShort1);
+            Object myObj = server.getObject("short1");
+            Assert.AreEqual(myShort1, myObj);
+
+            server.removeObject("short1");
+            myObj = server.getObject("short1");
+            Assert.IsNull(myObj);
+        }
+
+        [Test]
+        public void TestInt()
+        {
+            server.putObject("int1", myInt1);
+            Object myObj = server.getObject("int1");
+            Assert.AreEqual(myInt1, myObj);
+
+            server.removeObject("int1");
+            myObj = server.getObject("int1");
+            Assert.IsNull(myObj);
+        }
+
+
+        [Test]
+        public void TestLong()
+        {
+            server.putObject("long1", myLong1);
+            Object myObj = server.getObject("long1");
+            Assert.AreEqual(myLong1, myObj);
+
+            server.removeObject("long1");
+            myObj = server.getObject("long1");
+            Assert.IsNull(myObj);
+        }
+
+        [Test]
+        public void TestFloat()
+        {
+            server.putObject("float1", myFloat1);
+            Object myObj = server.getObject("float1");
+            Assert.AreEqual(myFloat1, myObj);
+
+            server.removeObject("float1");
+            myObj = server.getObject("float1");
+            Assert.IsNull(myObj);
+        }
+
+        [Test]
+        public void TestDouble()
+        {
+            server.putObject("double1", myDouble1);
+            Object myObj = server.getObject("double1");
+            Assert.AreEqual(myDouble1, myObj);
+
+            server.removeObject("double1");
+            myObj = server.getObject("double1");
+            Assert.IsNull(myObj);
+        }
+
+        [Test]
+        public void TestString()
+        {
+            server.putObject("string1", myString1);
+            Object myObj = server.getObject("string1");
+            Assert.AreEqual(myString1, myObj);
+
+            server.removeObject("string1");
+            myObj = server.getObject("string1");
+            Assert.IsNull(myObj);
+        }
+
+        [Test]
+        public void TestSize()
+        {
+            server.putObject("int1", myInt1);
+            server.putObject("string1", "abc");
+
+            int? size = server.size();
+            Assert.AreEqual(2,size);
+
+            server.removeObject("int1");
+            server.removeObject("string1");
+
+            size = server.size();
+            Assert.AreEqual(0, size);
+        }
+
+        [Test]
+        public void TestGetAll()
+        {
+            int? size = server.size();
+            Assert.AreEqual(0,size);
+
+            server.putObject("int1", myInt1);
+            server.putObject("string1", "abc");
+
+            int count = 0;
+            foreach (Entry entry in server.getAll())
+            {
+                if (entry.key != null && entry.value != null)
+                    count++;
+            }
+
+            Assert.AreEqual(2,count);
+
+            server.removeObject("int1");
+            server.removeObject("string1");
+
+            size = server.size();
+            Assert.AreEqual(0,size);
+            
+        }
+
+
+        [TearDown]
+        public void CloseConnection()
+        {
+            if (server != null)
+            {
+                server._Stop();
+            } 
+        }
+
+        [TestFixtureTearDown]
+        public void StopListener()
+        {
+            if (listener != null)
+            {
+                listener.TransportControl(TransportConsts.STOP_AND_WAIT_DOWN,4000);
+                listener = null;
+            }
+        }
+    
+    }
+}
\ No newline at end of file
diff --git a/examples/distmap/src/test/java/org/apache/etch/examples/distmap/TestRemoteDistributedHashTableServer.java b/examples/distmap/src/test/java/org/apache/etch/examples/distmap/TestRemoteDistributedHashTableServer.java
new file mode 100644
index 0000000..d3cee62
--- /dev/null
+++ b/examples/distmap/src/test/java/org/apache/etch/examples/distmap/TestRemoteDistributedHashTableServer.java
@@ -0,0 +1,376 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.distmap;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.examples.distmap.DistributedHashTable.Entry;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.core.io.Transport;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+/**
+ * Tests the RemoteDistributedHashTableServer interface. Start the
+ * TestRemoteDistributedHashTableListener first.
+ */
+public class TestRemoteDistributedHashTableServer
+{
+	final boolean myBool1 = true;
+	final byte myByte1 = 127;
+	final short myShort1 = 32767;
+	final int myInt1 = 2147483647;
+	final long myLong1 = 9223372036854775807l;
+	final float myFloat1 = 3.4028235e38f;
+	final double myDouble1 = 1.7976931348623157e308d;
+	final String myString1 = "abc";
+	RemoteDistributedHashTableServer server;
+	
+	final Map<String, Object> map =
+		Collections.synchronizedMap( new HashMap<String, Object>() );
+	
+	/** transport */
+	public static ServerFactory listener;
+
+	/**
+	 * Connect to service
+	 * @throws Exception 
+	 */
+	@BeforeClass
+	public static void startRemoteDistributedHashTableListener()
+		throws Exception
+	{
+		Log.addSink(null);
+		Log.report("StartRemoteDistributedHashTableListener");
+			
+		String uri = "tcp://localhost:4007";
+		MainDistributedHashTableListener implFactory = new MainDistributedHashTableListener();
+		listener = DistributedHashTableHelper.newListener( uri, null, implFactory );
+
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+	
+		Log.report( "StartDistributedHashTableRemoteListener",
+				"status", "up",
+				"listener", listener );
+	}
+
+	/**
+	 * Shut down listener
+	 * @throws Exception
+	 */
+	@AfterClass
+	public static void shutListener()
+		throws Exception
+	{
+		if (listener != null)
+		{
+			listener.transportControl( Transport.STOP_AND_WAIT_DOWN, 4000 );
+			listener = null;
+		}
+	}	
+	
+	/**
+	 * Connect client to serve
+	 * @throws Exception
+	 */
+	@Before
+	public void makeConnection()
+		throws Exception
+	{
+		String uri = "tcp://localhost:4007";
+
+		server = DistributedHashTableHelper.newServer( uri, null, new MainDistributedHashTableClient() );
+
+		server._startAndWaitUp( 4000 );
+	}
+
+	/**
+	 * Shutdown connection to server
+	 * @throws Exception
+	 */
+	@After
+	public void shutConnection()
+		throws Exception
+	{
+		if (server != null)
+		{
+			server._stop();
+		}
+	}
+
+	/**
+	 * Verify that putObject, getObject and removeObject
+	 * work for a boolean type 
+	 * @throws Exception
+	 */
+	@Test
+	public void testBoolean()
+		throws Exception
+	{
+		Object myObj = server.putObject("boolean1", myBool1);
+		assertNull( myObj );
+
+		myObj = server.getObject("boolean1");
+		assertEquals( myBool1, myObj );
+
+		server.removeObject("boolean1");
+		myObj = server.getObject("boolean1");
+		assertNull( myObj );
+	}
+	
+	/**
+	 * Verify that putObject, getObject and removeObject
+	 * work for a byte type 
+	 * @throws Exception
+	 */
+	@Test
+	public void testByte()
+		throws Exception
+	{
+		Object myObj = server.putObject("byte1", myByte1);
+		assertNull( myObj );
+
+		myObj = server.getObject("byte1");
+		assertEquals( myByte1, myObj );
+
+		server.removeObject("byte1");
+		myObj = server.getObject("byte1");
+		assertNull( myObj );
+	}
+
+	/**
+	 * Verify that putObject, getObject and removeObject
+	 * work for a short type 
+	 * @throws Exception
+	 */
+	@Test
+	public void testShort()
+		throws Exception
+	{
+		Object myObj = server.putObject("short1", myShort1);
+		assertNull( myObj );
+
+		myObj = server.getObject("short1");
+		assertEquals( myShort1, myObj );
+
+		server.removeObject("short1");
+		myObj = server.getObject("short1");
+		assertNull( myObj );
+	}
+
+	/**
+	 * Verify that putObject, getObject and removeObject
+	 * work for an int type 
+	 * @throws Exception
+	 */
+	@Test
+	public void testInt()
+		throws Exception
+	{
+		Object myObj = server.putObject("int1", myInt1);
+		assertNull( myObj );
+
+		myObj = server.getObject("int1");
+		assertEquals( myInt1, myObj );
+
+		server.removeObject("int1");
+		myObj = server.getObject("int1");
+		assertNull( myObj );
+	}
+
+	/**
+	 * Verify that putObject, getObject and removeObject
+	 * work for a long type 
+	 * @throws Exception
+	 */
+	@Test
+	public void testLong()
+		throws Exception
+	{
+		Object myObj = server.putObject("long1", myLong1);
+		assertNull( myObj );
+
+		myObj = server.getObject("long1");
+		assertEquals( myLong1, myObj );
+
+		server.removeObject("long1");
+		myObj = server.getObject("long1");
+		assertNull( myObj );
+	}
+
+	/**
+	 * Verify that putObject, getObject and removeObject
+	 * work for a float type 
+	 * @throws Exception
+	 */
+	@Test
+	public void testFloat()
+		throws Exception
+	{
+		Object myObj = server.putObject("float1", myFloat1);
+		assertNull( myObj );
+
+		myObj = server.getObject("float1");
+		assertEquals( myFloat1, myObj );
+
+		server.removeObject("float1");
+		myObj = server.getObject("float1");
+		assertNull( myObj );
+	}
+
+	/**
+	 * Verify that putObject, getObject and removeObject
+	 * work for a double type 
+	 * @throws Exception
+	 */
+	@Test
+	public void testDouble()
+		throws Exception
+	{
+		Object myObj = server.putObject("double1", myDouble1);
+		assertNull( myObj );
+
+		myObj = server.getObject("double1");
+		assertEquals( myDouble1, myObj );
+
+		server.removeObject("double1");
+		myObj = server.getObject("double1");
+		assertNull( myObj );
+	}
+
+	/**
+	 * Verify that putObject, getObject and removeObject
+	 * work for a string type 
+	 * @throws Exception
+	 */
+	@Test
+	public void testString()
+		throws Exception
+	{
+		Object myObj = server.putObject("string1", myString1);
+		assertNull( myObj );
+
+		myObj = server.getObject("string1");
+		assertEquals( myString1, myObj );
+
+		server.removeObject("string1");
+		myObj = server.getObject("string1");
+		assertNull( myObj );
+	}
+	
+	/**
+	 * Verify size
+	 * @throws Exception
+	 */
+	@Test
+	public void testSize()
+		throws Exception
+	{
+		/*
+		 * Verify that size is initially zero
+		 */
+		int size = server.size();
+		assertEquals(size, 0);
+
+		/*
+		 * Add items and verify size
+		 */
+		server.putObject("string1", "abc");
+		server.putObject("string2", "xyz");
+		server.putObject("int1", 0);
+		server.putObject("int2", 125);
+
+		size = server.size();
+		assertEquals(size,4);
+		
+		/*
+		 * Remove items and verify size
+		 */
+		server.removeObject("string1");
+		server.removeObject("string2");
+		server.removeObject("int1");
+		server.removeObject("int2");
+
+		size = server.size();
+		assertEquals(size, 0);
+	}
+	
+	/**
+	 * Verify that getAll returns all entries 
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetAll()
+		throws Exception
+	{
+		/*
+		 * Verify that map is empty to start
+		 */
+		int size = server.size();
+		assertEquals(size, 0);
+
+		/*
+		 * Put items in map
+		 */
+		server.putObject("string1", "abc");
+		server.putObject("string2", "xyz");
+		server.putObject("int1", 0);
+		server.putObject("int2", 125);
+
+		/*
+		 * Verify that 4 items were inserted into the map
+		 */
+		int counter = 0;
+		for(Entry entry: server.getAll())
+		{
+			if(entry.key != null && entry.value != null)
+			{
+				counter++;
+			}
+		}
+
+		assertEquals(counter, 4);
+
+		/*
+		 * Remove all items added to map
+		 */
+		server.removeObject("string1");
+		server.removeObject("string2");
+		server.removeObject("int1");
+		server.removeObject("int2");
+
+		/*
+		 * Verify that map is empty when all known items are removed
+		 */
+		size = server.size();
+		assertEquals(size, 0);
+	}
+}
diff --git a/examples/example/README.txt b/examples/example/README.txt
new file mode 100644
index 0000000..3921fa0
--- /dev/null
+++ b/examples/example/README.txt
@@ -0,0 +1,30 @@
+To get started with the example you will need jdk 1.5.0_x,
+where x is pretty recent (>= 15), or any release of jdk 1.6.
+You will also need ant 1.7.0, with ant .net plugin if you
+want to build csharp. You will also need microsoft .net
+sdk 2.0 for csharp builds.
+
+To build:
+
+> ant
+
+This will run the default target which will build both java
+and csharp programs. You can also use build-java or build-csharp
+targets to build only java or only csharp.
+
+To run java example example, open a cmd window and run these
+commands:
+
+> cd target\bin
+> start java -cp example.jar etch.examples.example.MainExmapleListener
+> start java -cp example.jar etch.examples.example.MainExampleClient
+
+To run csharp example:
+
+> cd target\bin
+> start exampleListener.exe
+> start exampleClient.exe
+
+Now modify the example to implement the service however you like.
+
+You can mix and match the various clients and listeners.
diff --git a/examples/example/build.xml b/examples/example/build.xml
new file mode 100644
index 0000000..94c13bd
--- /dev/null
+++ b/examples/example/build.xml
@@ -0,0 +1,324 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-example-example" basedir="." default="help" >
+    <description>Example Example</description>
+    <property name="Etch.basedir" location="${basedir}/../.." />
+    <import file="${Etch.basedir}/build-support/etch.includes.xml" />
+
+    <!-- TODO better computation of etch.home, etch.version -->
+    <property environment="env" />
+
+    <!-- compute ETCH_HOME -->
+    <property name="build.ETCH_HOME" location="${basedir}/../../target/Installers/dist" />
+    <condition property="etch.home" value="${env.ETCH_HOME}" >
+        <isset property="${env.ETCH_HOME}" />
+    </condition>
+    <condition property="etch.home" value="${build.ETCH_HOME}" >
+        <not><isset property="etch.home" /></not>
+    </condition>
+
+    <property name="Etch.dependency.junit.jar"
+        location="${default.junit.lib}/junit-4.3.1.jar" />
+
+    <property name="Etch.buildSupportDirectory" location="../../build-support" />
+
+    <!-- compute etch.version -->
+    <condition property="etch.version" value="${Etch.version}" >
+        <not><isset property="etch.version" /></not>
+    </condition>
+
+    <!-- Csharp Support -->
+    <condition property="USE.dotnet" >
+        <and>
+            <os family="windows" />
+            <available file="${env.windir}/Microsoft.NET/Framework/v2.0.50727/msbuild.exe" />
+        </and>
+    </condition>
+    <condition property="USE.mono" >
+        <and>
+            <not><os family="windows" /></not>
+            <!-- TODO mono support is not fully baked, use -DUSE.mono to test -->
+            <!-- <available file="${env.MONO_HOME}/bin/mdtool" /> -->
+            <isset property="USE.mono" />
+        </and>
+    </condition>
+    <condition property="BUILD.csharp" >
+        <or>
+            <isset property="USE.dotnet" />
+            <isset property="USE.mono" />
+        </or>
+    </condition>
+
+    <!-- import etch task -->
+    <taskdef
+        onerror="report"
+        resource="org/apache/etch/tools/ant/etch.xml"
+        classpath="${etch.home}/lib/etch-ant-plugin-${etch.version}.jar" />
+
+    <!-- import dotnet task -->
+    <condition property="ant.dotnet.jar" value="ant-dotnet-1.0.jar" >
+        <not><isset property="ant.dotnet.jar" /></not>
+    </condition>
+
+    <taskdef
+        onerror="report"
+        resource="org/apache/ant/dotnet/antlib.xml"
+        classpath="${ant.dotnet.jar}" />
+
+    <macrodef name="mdtool" >
+        <attribute name="dir"         default="." />
+        <attribute name="failonerror" default="false" />
+        <attribute name="project"     default="project.csproj" />
+        <attribute name="target"      default="${build.target}" />
+        <sequential>
+            <exec executable="${env.MONO_HOME}/bin/mdtool" dir="@{dir}" failonerror="@{failonerror}" >
+                <arg value="build" />
+                <arg value="--buildfile:@{project}" />
+            </exec>
+        </sequential>
+    </macrodef>
+
+    <!-- set properties -->
+    <property name="src"               location="${basedir}/src" />
+    <property name="main-src-java"     location="${src}/main/java" />
+    <property name="test-src-java"     location="${src}/test/java" />
+    <property name="target"            location="${basedir}/target" />
+    <property name="dist-src"          location="${target}/dist-src" />
+    <property name="generated-sources" location="${target}/generated-sources" />
+    <property name="gen-src-java"      location="${generated-sources}/main/etch/java" />
+    <property name="gen-src-csharp"    location="${generated-sources}/main/etch/csharp" />
+    <property name="bin"               location="${target}/bin" />
+    <property name="classes"           location="${target}/classes" />
+    <property name="classes-test"      location="${target}/classes-test" />
+    <property name="test-results"      location="${target}/test-results" />
+    <property name="nunit-results"     location="${target}/nunit-results" />
+    <property name="dist"              location="${basedir}/../../target/Installers/dist" />
+
+    <!-- initialize -->
+    <target name="init" >
+        <mkdir dir="${target}" />
+        <mkdir dir="${dist-src}" />
+        <mkdir dir="${generated-sources}" />
+        <mkdir dir="${gen-src-java}" />
+        <mkdir dir="${gen-src-csharp}" />
+        <mkdir dir="${bin}" />
+        <mkdir dir="${classes}" />
+        <mkdir dir="${classes-test}" />
+        <mkdir dir="${test-results}" />
+        <mkdir dir="${nunit-results}" />
+    </target>
+
+    <!-- build the server -->
+    <target name="generate-sources" depends="init" >
+        <!-- generate sources -->
+
+        <etch home="${etch.home}"
+              file="${src}/main/etch/Example.etch"
+              binding="java"
+              outputDir="${gen-src-java}" />
+
+        <etch home="${etch.home}"
+              file="${src}/main/etch/Example.etch"
+              binding="csharp"
+              outputDir="${gen-src-csharp}" />
+    </target>
+
+    <property name="etch-java-runtime-name"
+        value="etch-java-runtime-${etch.version}.jar" />
+
+    <property name="Etch.dependency.java.runtime"
+        location="${etch.home}/lib/${etch-java-runtime-name}" />
+
+    <target name="build-java" depends="generate-sources" >
+        <!-- compile sources -->
+
+        <javac target="1.5" destdir="${classes}" >
+            <src path="${gen-src-java}" />
+            <src path="${main-src-java}" />
+            <classpath>
+                <pathelement location="${Etch.dependency.java.runtime}" />
+            </classpath>
+        </javac>
+
+        <javac target="1.5" destdir="${classes-test}" >
+            <src path="${gen-src-java}" />
+            <src path="${main-src-java}" />
+            <src path="${test-src-java}" />
+            <classpath>
+                <pathelement location="${Etch.dependency.java.runtime}" />
+                <pathelement location="${Etch.dependency.junit.jar}" />
+            </classpath>
+        </javac>
+
+        <!-- Create Jar -->
+        <jar jarfile="${bin}/example.jar" >
+            <manifest>
+                <attribute name="Class-Path" value="${etch-java-runtime-name}" />
+            </manifest>
+            <fileset dir="${classes}" >
+                <include name="**/*" />
+            </fileset>
+        </jar>
+
+        <!-- copy in dependencies -->
+        <copy todir="${bin}" file="${Etch.dependency.java.runtime}" />
+    </target>
+
+    <target name="build-csharp-with-mono" depends="generate-sources" if="USE.mono" >
+        <mdtool dir="${src}/main/csharp/ExampleClientProj" project="ExampleClientProj.csproj" />
+        <mdtool dir="${src}/main/csharp/ExampleListenerProj" project="ExampleListenerProj.csproj" />
+    </target>
+
+    <target name="build-csharp-with-dotnet" depends="generate-sources" if="USE.dotnet" >
+        <msbuild buildfile="${src}/main/csharp/ExampleListenerProj/ExampleListenerProj.csproj" >
+            <property name="Configuration" value="${build.target}" />
+        </msbuild>
+        <msbuild buildfile="${src}/main/csharp/ExampleClientProj/ExampleClientProj.csproj" >
+            <property name="Configuration" value="${build.target}" />
+        </msbuild>
+        <msbuild buildfile="${src}/test/csharp/ExampleTestProj/ExampleTestProj.csproj" >
+            <property name="Configuration" value="${build.target}" />
+        </msbuild>
+        <copy todir="${bin}" >
+            <fileset dir="${src}/main/csharp/ExampleListenerProj/bin/${build.target}" >
+                <include name="*" />
+            </fileset>
+            <fileset dir="${src}/main/csharp/ExampleClientProj/bin/${build.target}" >
+                <include name="*" />
+            </fileset>
+        </copy>
+    </target>
+
+    <target name="build-csharp" depends="build-csharp-with-mono,build-csharp-with-dotnet" />
+
+    <target name="build" depends="build-java,build-csharp" />
+
+    <!-- run unit tests -->
+
+    <target name="test-java" depends="build-java" >
+        <!-- Run Unit Tests -->
+        <junit printsummary="yes" haltonfailure="no" dir="${classes-test}"
+            errorProperty="build.tests.fail" failureProperty="build.tests.fail" >
+            <classpath>
+                <pathelement location="${classes-test}" />
+                <pathelement location="${Etch.dependency.java.runtime}" />
+                <pathelement location="${Etch.dependency.junit.jar}" />
+            </classpath>
+            <formatter type="xml" />
+            <batchtest fork="true" todir="${test-results}" >
+                <fileset dir="${test-src-java}" >
+                    <include name="**/Test*.java" />
+                </fileset>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="test-csharp" depends="build-csharp" if="BUILD.csharp" >
+         <nunit xmlout="${nunit-results}/NUnitResults.xml">
+             <testassembly name="${src}/test/csharp/ExampleTestProj/bin/${build.target}/ExampleTestProj.dll" />
+         </nunit>
+
+         <xslt style="${Etch.buildSupportDirectory}/NUnitToJUnit.xsl"
+                 in="${nunit-results}/NUnitResults.xml" out="${test-results}/TEST-NUnitResults.xml" />
+   </target>
+
+    <target name="test" depends="build,test-java,test-csharp,done" >
+    </target>
+
+    <target name="done" depends="build" >
+        <echo>
+
+Build Complete!
+
+To run java example example, open a cmd window and run these
+commands:
+
+> cd target\bin
+> start java -cp example.jar org.apache.etch.examples.example.MainExmapleListener
+> start java -cp example.jar org.apache.etch.examples.example.MainExampleClient
+
+To run csharp example:
+
+> cd target\bin
+> start exampleListener.exe
+> start exampleClient.exe
+
+Now modify the example to implement the service however you like.
+
+You can mix and match the various clients and listeners.
+
+        </echo>
+    </target>
+
+    <!-- build everything -->
+    <target name="init-debug" >
+        <property name="build.target" value="Debug" />
+    </target>
+
+    <target name="init-release" >
+        <property name="build.target" value="Release" />
+    </target>
+    
+    <target name="dist-src" >
+        <copy file="dist-build.xml" tofile="${dist-src}/build.xml" overwrite="true" >
+            <filterset refid="Etch.buildTokens" />
+        </copy>    
+        <copy file="README.txt" tofile="${dist-src}/README.txt" overwrite="true" />
+        
+        <copy todir="${dist-src}/src/main/etch" overwrite="true" >
+            <fileset dir="${src}/main/etch" >
+                <exclude name="**/.svn/**" />
+                <include name="**/*.etch" />
+            </fileset>
+        </copy>
+        
+        <copy todir="${dist-src}/src/main/java" overwrite="true" >
+            <fileset dir="${src}/main/java" >
+                <exclude name="**/.svn/**" />
+                <include name="**/*.java" />
+            </fileset>
+        </copy>
+        
+        <copy todir="${dist-src}/src/main/csharp" overwrite="true" >
+            <fileset dir="${src}/main/csharp" >
+                <exclude name="**/.svn/**" />
+                <include name="**/*.cs" />
+            </fileset>
+        </copy>
+        
+        <copy todir="${dist}/examples/example" overwrite="true" >
+            <fileset dir="${dist-src}" />
+        </copy>
+    </target>
+
+    <target name="debug" depends="dist-src,init-debug,test" />
+    <target name="release" depends="dist-src,init-release,test" />
+
+    <!-- clean -->
+    <target name="clean" >
+        <delete dir="${target}" quiet="true" />
+        <delete dir="${src}/main/csharp/ExampleClientProj/bin" quiet="true" />
+        <delete dir="${src}/main/csharp/ExampleClientProj/obj" quiet="true" />
+        <delete dir="${src}/main/csharp/ExampleListenerProj/bin" quiet="true" />
+        <delete dir="${src}/main/csharp/ExampleListenerProj/obj" quiet="true" />
+        <delete dir="${src}/test/csharp/ExampleTestProj/bin" quiet="true" />
+        <delete dir="${src}/test/csharp/ExampleTestProj/obj" quiet="true" />
+    </target>
+</project>
diff --git a/examples/example/dist-build.xml b/examples/example/dist-build.xml
new file mode 100644
index 0000000..33b3072
--- /dev/null
+++ b/examples/example/dist-build.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-example-example" basedir="." default="build">
+    <description>Example Example</description>
+
+    <property name="etch.home" location="${basedir}/../.."/>
+    <property name="etch.version" value="@EtchVersion@"/>
+    <property name="etch-java-runtime-name" value="etch-java-runtime-${etch.version}.jar"/>
+
+    <property name="etch-ant-plugin.jar"   location="${etch.home}/lib/etch-ant-plugin-${etch.version}.jar"/>
+    <property name="etch-java-runtime.jar" location="${etch.home}/lib/${etch-java-runtime-name}"/>
+    <property name="etch.dll"              location="${etch.home}/lib/Etch.dll"/>
+
+    <property name="src"               location="${basedir}/src"/>
+    <property name="src-main-etch"     location="${src}/main/etch"/>
+    <property name="src-main-java"     location="${src}/main/java"/>
+    <property name="src-main-csharp"   location="${src}/main/csharp"/>
+    <property name="target"            location="${basedir}/target"/>
+    <property name="generated-sources" location="${target}/generated-sources"/>
+    <property name="gensrc-main-etch-java" location="${generated-sources}/main/etch/java"/>
+    <property name="gensrc-main-etch-csharp" location="${generated-sources}/main/etch/csharp"/>
+    <property name="classes"           location="${target}/classes"/>
+    <property name="bin"               location="${target}/bin"/>
+    
+    <condition property="BUILD.csharp" >
+        <os family="windows" />
+    </condition>    
+
+    <taskdef
+        resource="org/apache/etch/tools/ant/etch.xml"
+        classpath="${etch-ant-plugin.jar}"/>
+
+    <target name="build" depends="build-java, build-csharp, done"/>
+
+    <target name="build-java" depends="gensrc-java">
+        <javac destdir="${classes}" source="1.5" debug="true">
+            <classpath>
+                <pathelement location="${etch-java-runtime.jar}"/>
+            </classpath>
+            <src path="${src-main-java}"/>
+            <src path="${gensrc-main-etch-java}"/>
+        </javac>
+
+        <jar jarfile="${bin}/example.jar">
+            <manifest>
+                <attribute name="Class-Path" value="${etch-java-runtime-name}"/>
+            </manifest>
+            <fileset dir="${classes}"/>
+        </jar>
+
+        <copy todir="${bin}" file="${etch-java-runtime.jar}"/>
+    </target>
+
+    <target name="done">
+        <echo>
+
+To run java example example, open a cmd window and run these
+commands:
+
+> cd target\bin
+> start java -cp example.jar etch.examples.example.MainExmapleListener
+> start java -cp example.jar etch.examples.example.MainExampleClient
+
+To run csharp example:
+
+> cd target\bin
+> start exampleListener.exe
+> start exampleClient.exe
+
+Now modify the example to implement the service however you like.
+
+You can mix and match the various clients and listeners.
+
+        </echo>
+    </target>
+
+    <target name="build-csharp" depends="gensrc-csharp" if="BUILD.csharp" >
+        <csc
+                debug="true"
+                warnLevel="1"
+                unsafe="false"
+                targetType="exe"
+                incremental="false"
+                mainClass = "etch.examples.example.MainExampleClient"
+                destFile="${bin}/exampleClient.exe">
+            <src dir="${src-main-csharp}/exampleClientProj" includes="**/*.cs"/>
+            <src dir="${src-main-csharp}/etch.examples.example" includes="**/*.cs"/>
+            <src dir="${gensrc-main-etch-csharp}" includes="**/*.cs"/>
+            <reference file="${etch.dll}"/>
+        </csc>
+
+        <csc
+                debug="true"
+                warnLevel="1"
+                unsafe="false"
+                targetType="exe"
+                incremental="false"
+                mainClass = "etch.examples.example.MainExampleListener"
+                destFile="${bin}/exampleListener.exe">
+            <src dir="${src-main-csharp}/exampleListenerProj" includes="**/*.cs"/>
+            <src dir="${src-main-csharp}/etch.examples.example" includes="**/*.cs"/>
+            <src dir="${gensrc-main-etch-csharp}" includes="**/*.cs"/>
+            <reference file="${etch.dll}"/>
+        </csc>
+
+        <copy todir="${bin}" file="${etch.dll}"/>
+    </target>
+
+    <target name="gensrc" depends="gensrc-java, gensrc-csharp"/>
+
+    <target name="gensrc-java" depends="init">
+        <etch
+            home="${etch.home}"
+            binding="java"
+            quiet="true"
+            outputDir="${gensrc-main-etch-java}"
+            file="${src-main-etch}/Example.etch"/>
+    </target>
+
+    <target name="gensrc-csharp" depends="init">
+        <etch
+            home="${etch.home}"
+            binding="csharp"
+            quiet="true"
+            outputDir="${gensrc-main-etch-csharp}"
+            file="${src-main-etch}/Example.etch"/>
+    </target>
+
+    <target name="init">
+        <mkdir dir="${target}"/>
+        <mkdir dir="${generated-sources}"/>
+        <mkdir dir="${gensrc-main-etch-java}"/>
+        <mkdir dir="${gensrc-main-etch-csharp}"/>
+        <mkdir dir="${classes}"/>
+        <mkdir dir="${bin}"/>
+    </target>
+
+    <target name="clean">
+        <delete dir="${target}"/>
+    </target>
+</project>
diff --git a/examples/example/src/main/csharp/ExampleClientProj/ExampleClientProj.csproj b/examples/example/src/main/csharp/ExampleClientProj/ExampleClientProj.csproj
new file mode 100644
index 0000000..c60dc90
--- /dev/null
+++ b/examples/example/src/main/csharp/ExampleClientProj/ExampleClientProj.csproj
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{38953BC0-A834-4939-A25F-8C7F2C7F8758}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>etch.examples.example</RootNamespace>
+    <AssemblyName>ExampleClient</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\BaseExampleClient.cs">
+      <Link>BaseExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\BaseExampleServer.cs">
+      <Link>BaseExampleServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\Example.cs">
+      <Link>Example.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\ExampleClient.cs">
+      <Link>ExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\ExampleHelper.cs">
+      <Link>ExampleHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\ExampleServer.cs">
+      <Link>ExampleServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\RemoteExample.cs">
+      <Link>RemoteExample.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\RemoteExampleClient.cs">
+      <Link>RemoteExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\RemoteExampleServer.cs">
+      <Link>RemoteExampleServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\StubExample.cs">
+      <Link>StubExample.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\StubExampleClient.cs">
+      <Link>StubExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\StubExampleServer.cs">
+      <Link>StubExampleServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\ValueFactoryExample.cs">
+      <Link>ValueFactoryExample.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.example\ImplExampleClient.cs">
+      <Link>ImplExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.example\MainExampleClient.cs">
+      <Link>MainExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\..\..\binding-csharp\runtime\src\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/examples/example/src/main/csharp/ExampleClientProj/Properties/AssemblyInfo.cs b/examples/example/src/main/csharp/ExampleClientProj/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b43368a
--- /dev/null
+++ b/examples/example/src/main/csharp/ExampleClientProj/Properties/AssemblyInfo.cs
@@ -0,0 +1,48 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Example Client")]
+[assembly: AssemblyDescription("Example Client Executable")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Cisco Systems Inc")]
+[assembly: AssemblyProduct("Etch")]
+[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("8de2f683-6bdc-4559-890b-b188d7fcc790")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+[assembly: AssemblyVersion("0.0.0.1")]
+[assembly: AssemblyFileVersion("0.0.0.1")]
diff --git a/examples/example/src/main/csharp/ExampleListenerProj/ExampleListenerProj.csproj b/examples/example/src/main/csharp/ExampleListenerProj/ExampleListenerProj.csproj
new file mode 100644
index 0000000..430a21e
--- /dev/null
+++ b/examples/example/src/main/csharp/ExampleListenerProj/ExampleListenerProj.csproj
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{7EEA2F47-0D96-4187-B9EF-CA0B9E839841}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>etch.examples.example</RootNamespace>
+    <AssemblyName>ExampleListener</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\BaseExampleClient.cs">
+      <Link>BaseExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\BaseExampleServer.cs">
+      <Link>BaseExampleServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\Example.cs">
+      <Link>Example.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\ExampleClient.cs">
+      <Link>ExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\ExampleHelper.cs">
+      <Link>ExampleHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\ExampleServer.cs">
+      <Link>ExampleServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\RemoteExample.cs">
+      <Link>RemoteExample.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\RemoteExampleClient.cs">
+      <Link>RemoteExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\RemoteExampleServer.cs">
+      <Link>RemoteExampleServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\StubExample.cs">
+      <Link>StubExample.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\StubExampleClient.cs">
+      <Link>StubExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\StubExampleServer.cs">
+      <Link>StubExampleServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\ValueFactoryExample.cs">
+      <Link>ValueFactoryExample.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.example\ImplExampleServer.cs">
+      <Link>ImplExampleServer.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.example\MainExampleListener.cs">
+      <Link>MainExampleListener.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\..\..\binding-csharp\runtime\src\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/examples/example/src/main/csharp/ExampleListenerProj/Properties/AssemblyInfo.cs b/examples/example/src/main/csharp/ExampleListenerProj/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..50f3328
--- /dev/null
+++ b/examples/example/src/main/csharp/ExampleListenerProj/Properties/AssemblyInfo.cs
@@ -0,0 +1,48 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Example Listener")]
+[assembly: AssemblyDescription("Example Listener Executable")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Etch")]
+[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("cf339233-1189-43b8-b609-dd7b7b2c2a42")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+[assembly: AssemblyVersion("0.0.0.1")]
+[assembly: AssemblyFileVersion("0.0.0.1")]
diff --git a/examples/example/src/main/csharp/etch.examples.example/ImplExampleClient.cs b/examples/example/src/main/csharp/etch.examples.example/ImplExampleClient.cs
new file mode 100644
index 0000000..a3a4c17
--- /dev/null
+++ b/examples/example/src/main/csharp/etch.examples.example/ImplExampleClient.cs
@@ -0,0 +1,40 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace org.apache.etch.examples.example
+{
+	///<summary>Implementation for ImplExampleClient</summary>
+	public class ImplExampleClient : BaseExampleClient
+	{
+		/// <summary>Constructs the ImplExampleClient.</summary>
+ 		/// <param name="server">a connection to the server session. Use this to
+ 		/// send a message to the server.</param>
+		public ImplExampleClient(RemoteExampleServer server)
+		{
+			this.server = server;
+		}
+		
+		/// <summary>A connection to the server session. Use this to
+ 		/// send a message to the server.</summary>
+		private readonly RemoteExampleServer server;
+	
+		// TODO: Implement delegates or provide implementation of ExampleClient
+		// messages from the server	
+	}
+}
\ No newline at end of file
diff --git a/examples/example/src/main/csharp/etch.examples.example/ImplExampleServer.cs b/examples/example/src/main/csharp/etch.examples.example/ImplExampleServer.cs
new file mode 100644
index 0000000..e2530b5
--- /dev/null
+++ b/examples/example/src/main/csharp/etch.examples.example/ImplExampleServer.cs
@@ -0,0 +1,40 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace org.apache.etch.examples.example
+{
+	///<summary>Implementation for ImplExampleServer</summary>
+	public class ImplExampleServer : BaseExampleServer
+	{
+		/// <summary>Constructs the ImplExampleServer.</summary>
+ 		/// <param name="client">a connection to the client session. Use this to
+ 		/// send a message to the client.</param>
+		public ImplExampleServer(RemoteExampleClient client)
+		{
+			this.client = client;
+		}
+		
+		/// <summary>A connection to the client session. Use this to
+ 		/// send a message to the client.</summary>
+		private readonly RemoteExampleClient client;
+	
+		// TODO: Implement delegates or provide implementation of ExampleServer
+		// messages from the client	
+	}
+}
\ No newline at end of file
diff --git a/examples/example/src/main/csharp/etch.examples.example/MainExampleClient.cs b/examples/example/src/main/csharp/etch.examples.example/MainExampleClient.cs
new file mode 100644
index 0000000..bb73cb5
--- /dev/null
+++ b/examples/example/src/main/csharp/etch.examples.example/MainExampleClient.cs
@@ -0,0 +1,53 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace org.apache.etch.examples.example
+{
+	///<summary>Main implementation for ExampleClient.</summary>
+	public class MainExampleClient : ExampleHelper.ExampleClientFactory
+	{
+		///<summary>Main for ExampleClient</summary>
+		///<param name="args">Command Line Arguments</param>
+		public static void Main(String[] args)
+		{
+			// TODO: Change to correct URI
+			string uri = "tcp://localhost:4002";
+			
+			RemoteExampleServer server = ExampleHelper.NewServer( uri, null, new MainExampleClient());
+		
+			// Connect to the service
+			server._StartAndWaitUp( 4000 );
+
+			// TODO: Insert Your Code Here
+
+			// Disconnect from the service
+			server._StopAndWaitDown( 4000 );			
+		}
+
+		///<summary>Return a new instance of ExampleClient.</summary>
+		///<param name="server">Reference to remote service</param>
+		///<returns>Client Implementation</returns>
+		public ExampleClient NewExampleClient( RemoteExampleServer server )
+		{
+			return new ImplExampleClient( server );
+		}
+	}
+}
\ No newline at end of file
diff --git a/examples/example/src/main/csharp/etch.examples.example/MainExampleListener.cs b/examples/example/src/main/csharp/etch.examples.example/MainExampleListener.cs
new file mode 100644
index 0000000..40f1364
--- /dev/null
+++ b/examples/example/src/main/csharp/etch.examples.example/MainExampleListener.cs
@@ -0,0 +1,50 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace org.apache.etch.examples.example
+{
+	///<summary>Main implementation for ExampleListener.</summary>
+	public class MainExampleListener : ExampleHelper.ExampleServerFactory
+	{
+ 		///<summary>Main for ExampleListener.</summary>
+		///<param name="args">Command Line Arguments</param>
+		public static void Main(String[] args)
+		{
+			// TODO: Change to correct URI
+			string uri = "tcp://localhost:4002";
+			
+            ServerFactory listener = ExampleHelper.NewListener(uri, null, new MainExampleListener());
+			
+			// Start the Listener
+			listener.TransportControl( TransportConsts.START_AND_WAIT_UP, 4000 );
+		}
+
+		///<summary>Return a new instance of ExampleServer.</summary>
+		///<param name="client">Reference to remote service</param>
+		///<returns>Server Implementation</returns>
+		public ExampleServer NewExampleServer( RemoteExampleClient client )
+		{
+			return new ImplExampleServer( client );
+		}
+	}
+}
\ No newline at end of file
diff --git a/examples/example/src/main/etch/Example.etch b/examples/example/src/main/etch/Example.etch
new file mode 100644
index 0000000..4c6c714
--- /dev/null
+++ b/examples/example/src/main/etch/Example.etch
@@ -0,0 +1,116 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.examples.example
+
+/**
+ * Service version of hello world.
+ */
+service Example
+{
+	/** the number of times to perform the action */
+	const int COUNT = 4
+	
+	/** a simple view of time */
+	enum Times
+	(
+		/** the past */
+		YESTERDAY,
+		/** right now */
+		TODAY,
+		/** the future */
+		TOMORROW
+	)
+	
+	/** a way to speak about places */
+	struct Point
+	(
+		/** the x-coordinate value */
+		double x,
+		/** the y-coordinate value */
+		double y,
+		/** the z-coordinate value */
+		double z
+	)
+	
+	/**
+	 * Exception thrown if ping doesn't work.
+	 * @param msg the explanation.
+	 */
+	exception PongException ( string msg )
+	
+	/**
+	 * Says hello to the server.
+	 * @param msg a greeting for the server.
+	 * @param d the current date.
+	 * @return the id of our hello
+	 */
+	@Timeout( 1234 )
+	@Direction( Server )
+	int helloServer( string msg, Datetime d )
+	
+	/**
+	 * Says hello to the client.
+	 * @param msg a greeting for the client.
+	 * @return the id of our hello
+	 */
+	@Timeout( 2345 )
+	@Direction( Client )
+	int helloClient( string msg )
+	
+	/**
+	 * Says hello to the client or server.
+	 * @param msg a greeting for the client or server.
+	 * @return the id of our hello
+	 */
+	@Timeout( 3456 )
+	@Direction( Both )
+	int hello( string msg )
+	
+	/**
+	 * Says howdy to the server. Oneway.
+	 * @param msg a greeting for the server.
+	 */
+	@Oneway
+	@Direction( Server )
+	void howdyServer( string msg )
+	
+	/**
+	 * Says howdy to the client. Oneway.
+	 * @param msg a greeting for the client.
+	 */
+	@Oneway
+	@Direction( Client )
+	void howdyClient( string msg )
+	
+	/**
+	 * Says howdy to the client or server. Oneway.
+	 * @param msg a greeting for the client or server.
+	 */
+	@Oneway
+	@Direction( Both )
+	void howdy( string msg )
+	
+	/**
+	 * Pings the other side.
+	 * @throws PongException
+	 */
+	@Timeout( 4567 )
+	@Direction( Both )
+	@AsyncReceiver( Queued )
+	void ping() throws PongException
+}
diff --git a/examples/example/src/main/java/org/apache/etch/examples/example/ImplExampleClient.java b/examples/example/src/main/java/org/apache/etch/examples/example/ImplExampleClient.java
new file mode 100644
index 0000000..b5116ea
--- /dev/null
+++ b/examples/example/src/main/java/org/apache/etch/examples/example/ImplExampleClient.java
@@ -0,0 +1,49 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.example;
+
+/**
+ * Your custom implementation of BaseExampleClient. Add methods here to provide
+ * implementations of messages from the server.
+ */
+public class ImplExampleClient extends BaseExampleClient
+{
+	/**
+	 * Constructs the ImplExampleClient.
+	 *
+	 * @param server a connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	public ImplExampleClient( RemoteExampleServer server )
+	{
+		this.server = server;
+	}
+	
+	/**
+	 * A connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	@SuppressWarnings( "unused" )
+	private final RemoteExampleServer server;
+
+	// TODO insert methods here to provide implementations of ExampleClient
+	// messages from the server.
+}
\ No newline at end of file
diff --git a/examples/example/src/main/java/org/apache/etch/examples/example/ImplExampleServer.java b/examples/example/src/main/java/org/apache/etch/examples/example/ImplExampleServer.java
new file mode 100644
index 0000000..0bb604c
--- /dev/null
+++ b/examples/example/src/main/java/org/apache/etch/examples/example/ImplExampleServer.java
@@ -0,0 +1,49 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.example;
+
+/**
+ * Your custom implementation of BaseExampleServer. Add methods here to provide
+ * implementations of messages from the client.
+ */
+public class ImplExampleServer extends BaseExampleServer
+{
+	/**
+	 * Constructs the ImplExampleServer.
+	 *
+	 * @param client a connection to the client session. Use this to send a
+	 * message to the client.
+	 */
+	public ImplExampleServer( RemoteExampleClient client )
+	{
+		this.client = client;
+	}
+	
+	/**
+	 * A connection to the client session. Use this to send a
+	 * message to the client.
+	 */
+	@SuppressWarnings( "unused" )
+	private final RemoteExampleClient client;
+
+	// TODO insert methods here to provide implementations of ExampleServer
+	// messages from the client.
+}
\ No newline at end of file
diff --git a/examples/example/src/main/java/org/apache/etch/examples/example/MainExampleClient.java b/examples/example/src/main/java/org/apache/etch/examples/example/MainExampleClient.java
new file mode 100644
index 0000000..f736c86
--- /dev/null
+++ b/examples/example/src/main/java/org/apache/etch/examples/example/MainExampleClient.java
@@ -0,0 +1,57 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.example;
+
+/**
+ * Main program for ExampleClient. This program makes a connection to the
+ * listener created by MainExampleListener.
+ */
+public class MainExampleClient implements ExampleHelper.ExampleClientFactory
+{
+	/**
+	 * Main program for ExampleClient.
+	 * 
+	 * @param args command line arguments.
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		// TODO Change to correct URI
+		String uri = "tcp://localhost:4001";
+		
+		RemoteExampleServer server = ExampleHelper.newServer( uri, null,
+			new MainExampleClient() );
+
+		// Connect to the service
+		server._startAndWaitUp( 4000 );
+
+		// TODO Insert Your Code Here
+
+		// Disconnect from the service
+		server._stopAndWaitDown( 4000 );
+	}
+
+	public ExampleClient newExampleClient( RemoteExampleServer server )
+		throws Exception
+	{
+		return new ImplExampleClient( server );
+	}
+}
diff --git a/examples/example/src/main/java/org/apache/etch/examples/example/MainExampleListener.java b/examples/example/src/main/java/org/apache/etch/examples/example/MainExampleListener.java
new file mode 100644
index 0000000..048dd6a
--- /dev/null
+++ b/examples/example/src/main/java/org/apache/etch/examples/example/MainExampleListener.java
@@ -0,0 +1,54 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.example;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.util.core.io.Transport;
+
+/**
+ * Main program for ExampleServer. This program makes a listener to accept
+ * connections from MainExampleClient.
+ */
+public class MainExampleListener implements ExampleHelper.ExampleServerFactory
+{
+	/**
+	 * Main program for ExampleServer.
+	 * 
+	 * @param args command line arguments.
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		// TODO Change to correct URI
+		String uri = "tcp://0.0.0.0:4001";
+		
+		ServerFactory listener = ExampleHelper.newListener( uri, null,
+			new MainExampleListener() );
+
+		// Start the Listener
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+	}
+
+	public ExampleServer newExampleServer( RemoteExampleClient client )
+	{
+		return new ImplExampleServer( client );
+	}
+}
diff --git a/examples/example/src/test/csharp/ExampleTestProj/ExampleTestProj.csproj b/examples/example/src/test/csharp/ExampleTestProj/ExampleTestProj.csproj
new file mode 100644
index 0000000..9cc6a8b
--- /dev/null
+++ b/examples/example/src/test/csharp/ExampleTestProj/ExampleTestProj.csproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{36991AC6-21DE-4F7A-8672-8CFCC8AF70C7}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>ExampleTestProj</RootNamespace>
+    <AssemblyName>ExampleTestProj</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="nunit.framework, Version=2.4.7.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>$(NUNIT_HOME)\bin\nunit.framework.dll</HintPath>
+      <SpecificVersion>False</SpecificVersion>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\BaseExampleClient.cs">
+      <Link>BaseExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\BaseExampleServer.cs">
+      <Link>BaseExampleServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\Example.cs">
+      <Link>Example.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\ExampleClient.cs">
+      <Link>ExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\ExampleHelper.cs">
+      <Link>ExampleHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\ExampleServer.cs">
+      <Link>ExampleServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\RemoteExample.cs">
+      <Link>RemoteExample.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\RemoteExampleClient.cs">
+      <Link>RemoteExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\RemoteExampleServer.cs">
+      <Link>RemoteExampleServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\StubExample.cs">
+      <Link>StubExample.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\StubExampleClient.cs">
+      <Link>StubExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\StubExampleServer.cs">
+      <Link>StubExampleServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.example\ValueFactoryExample.cs">
+      <Link>ValueFactoryExample.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.example\ImplExampleClient.cs">
+      <Link>ImplExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.example\ImplExampleServer.cs">
+      <Link>ImplExampleServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.example\MainExampleClient.cs">
+      <Link>MainExampleClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.example\MainExampleListener.cs">
+      <Link>MainExampleListener.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.example\TestExampleServer.cs">
+      <Link>TestExampleServer.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\..\..\binding-csharp\runtime\src\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/examples/example/src/test/csharp/ExampleTestProj/Properties/AssemblyInfo.cs b/examples/example/src/test/csharp/ExampleTestProj/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e8ea7da
--- /dev/null
+++ b/examples/example/src/test/csharp/ExampleTestProj/Properties/AssemblyInfo.cs
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ExampleTestProj")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ExampleTestProj")]
+[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f67c3b21-4b0e-4135-99b2-3386039086bb")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/examples/example/src/test/csharp/etch.examples.example/TestExampleServer.cs b/examples/example/src/test/csharp/etch.examples.example/TestExampleServer.cs
new file mode 100644
index 0000000..96ebf71
--- /dev/null
+++ b/examples/example/src/test/csharp/etch.examples.example/TestExampleServer.cs
@@ -0,0 +1,96 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+
+namespace org.apache.etch.examples.example
+{
+
+    /// <summary>
+    /// Unit Tests to test Example
+    /// </summary>
+    /// 
+    [TestFixture]
+    public class TestExampleServer
+    {
+        private static RemoteExampleServer server;
+
+        private static ServerFactory listener;
+
+        [TestFixtureSetUp]
+        public void StartListener()
+        {
+            String uri = "tcp://localhost:4010";
+
+            MainExampleListener implFactory = new MainExampleListener();
+            listener = ExampleHelper.NewListener(uri, null, implFactory);
+
+            listener.TransportControl(TransportConsts.START_AND_WAIT_UP, 4000);
+
+            Console.WriteLine("Listener Started");
+
+        }
+
+        [SetUp]
+        public void MakeConnection()
+        {
+            String uri = "tcp://localhost:4010";
+
+            MainExampleClient client = new MainExampleClient();
+            server = ExampleHelper.NewServer(uri, null, client);
+
+            server._StartAndWaitUp(4000);
+        }
+
+        [Test]
+        public void TestConnection()
+        {
+            Assert.IsNotNull(server);
+        }
+
+        [TearDown]
+        public void CloseConnection()
+        {
+            if (server != null)
+            {
+                server._Stop();
+            }
+        }
+
+        [TestFixtureTearDown]
+        public void StopListener()
+        {
+            if (listener != null)
+            {
+                listener.TransportControl(TransportConsts.STOP_AND_WAIT_DOWN, 4000);
+                listener = null;
+            }
+        }
+
+
+
+
+
+    }
+
+
+}
\ No newline at end of file
diff --git a/examples/example/src/test/java/org/apache/etch/examples/example/TestExampleServer.java b/examples/example/src/test/java/org/apache/etch/examples/example/TestExampleServer.java
new file mode 100644
index 0000000..60416a9
--- /dev/null
+++ b/examples/example/src/test/java/org/apache/etch/examples/example/TestExampleServer.java
@@ -0,0 +1,119 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.example;
+
+
+import junit.framework.Assert;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.core.io.Transport;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * 
+ *
+ */
+public class TestExampleServer
+{
+	
+	/** transport */
+	public static ServerFactory listener;
+	
+	RemoteExampleServer server;
+
+	/**
+	 * @throws Exception
+	 */
+	@BeforeClass
+	public static void startListener() throws Exception
+	{
+		Log.addSink(null);
+		Log.report("StartExampleListener");
+			
+		String uri = "tcp://localhost:4800";
+		MainExampleListener implFactory = new MainExampleListener();
+		listener = ExampleHelper.newListener( uri, null, implFactory );
+
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+	
+		Log.report( "StartExampleListener",
+				"status", "up",
+				"listener", listener );
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	@AfterClass
+	public static void stopListener() throws Exception
+	{
+		if (listener != null)
+		{
+			listener.transportControl( Transport.STOP_AND_WAIT_DOWN, 4000 );
+			listener = null;
+		}
+	}
+	
+	/**
+	 * Connect client to serve
+	 * @throws Exception
+	 */
+	@Before
+	public void makeConnection()
+		throws Exception
+	{
+		String uri = "tcp://localhost:4800";
+
+		server = ExampleHelper.newServer( uri, null, new MainExampleClient() );
+
+		server._startAndWaitUp( 4000 );
+	}
+
+	/**
+	 * Shutdown connection to server
+	 * @throws Exception
+	 */
+	@After
+	public void shutConnection()
+		throws Exception
+	{
+		if (server != null)
+		{
+			server._stop();
+		}
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test
+	public void checkConnection() throws Exception
+	{
+		Assert.assertNotNull(server);
+	}
+
+
+}
diff --git a/examples/perf/README.txt b/examples/perf/README.txt
new file mode 100644
index 0000000..b19ec8a
--- /dev/null
+++ b/examples/perf/README.txt
@@ -0,0 +1,28 @@
+To get started with the example you will need jdk 1.5.0_x,
+where x is pretty recent (>= 15), or any release of jdk 1.6.
+You will also need ant 1.7.0, with ant .net plugin if you
+want to build csharp. You will also need microsoft .net
+sdk 2.0 for csharp builds.
+
+To build:
+
+> ant
+
+This will run the default target which will build both java
+and csharp programs. You can also use build-java or build-csharp
+targets to build only java or only csharp.
+
+To run java performance example, open a cmd window and run these
+commands:
+
+> cd target\bin
+> start java -cp perf.jar etch.examples.perf.MainPerfListener
+> start java -cp perf.jar etch.examples.perf.MainPerfClient
+
+To run csharp example:
+
+> cd target\bin
+> start perfListener.exe
+> start perfClient.exe
+
+You can mix and match the various clients and listeners.
diff --git a/examples/perf/build.xml b/examples/perf/build.xml
new file mode 100644
index 0000000..f09ca33
--- /dev/null
+++ b/examples/perf/build.xml
@@ -0,0 +1,322 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-perf-example" basedir="." default="help" >
+    <description>Perf Example</description>
+    <property name="Etch.basedir" location="${basedir}/../.." />
+    <import file="${Etch.basedir}/build-support/etch.includes.xml" />
+
+    <!-- TODO better computation of etch.home, etch.version -->
+    <property environment="env" />
+
+    <!-- compute ETCH_HOME -->
+    <property name="build.ETCH_HOME" location="${basedir}/../../target/Installers/dist" />
+    <condition property="etch.home" value="${env.ETCH_HOME}" >
+        <isset property="${env.ETCH_HOME}" />
+    </condition>
+    <condition property="etch.home" value="${build.ETCH_HOME}" >
+        <not><isset property="etch.home" /></not>
+    </condition>
+
+    <property name="Etch.dependency.junit.jar"
+        location="${default.junit.lib}/junit-4.3.1.jar" />
+
+    <property name="Etch.buildSupportDirectory" location="../../build-support" />
+
+    <!-- compute etch.version -->
+    <condition property="etch.version" value="${Etch.version}" >
+        <not><isset property="etch.version" /></not>
+    </condition>
+
+    <!-- Csharp Support -->
+    <condition property="USE.dotnet" >
+        <and>
+            <os family="windows" />
+            <available file="${env.windir}/Microsoft.NET/Framework/v2.0.50727/msbuild.exe" />
+        </and>
+    </condition>
+    <condition property="USE.mono" >
+        <and>
+            <not><os family="windows" /></not>
+            <!-- TODO mono support is not fully baked, use -DUSE.mono to test -->
+            <!-- <available file="${env.MONO_HOME}/bin/mdtool" /> -->
+            <isset property="USE.mono" />
+        </and>
+    </condition>
+    <condition property="BUILD.csharp" >
+        <or>
+            <isset property="USE.dotnet" />
+            <isset property="USE.mono" />
+        </or>
+    </condition>
+
+    <!-- import etch task -->
+    <taskdef
+        onerror="report"
+        resource="org/apache/etch/tools/ant/etch.xml"
+        classpath="${etch.home}/lib/etch-ant-plugin-${etch.version}.jar" />
+
+    <!-- import dotnet task -->
+    <condition property="ant.dotnet.jar" value="ant-dotnet-1.0.jar" >
+        <not><isset property="ant.dotnet.jar" /></not>
+    </condition>
+
+    <taskdef
+        onerror="report"
+        resource="org/apache/ant/dotnet/antlib.xml"
+        classpath="${ant.dotnet.jar}" />
+
+    <macrodef name="mdtool" >
+        <attribute name="dir"         default="." />
+        <attribute name="failonerror" default="false" />
+        <attribute name="project"     default="project.csproj" />
+        <attribute name="target"      default="${build.target}" />
+        <sequential>
+            <exec executable="${env.MONO_HOME}/bin/mdtool" dir="@{dir}" failonerror="@{failonerror}" >
+                <arg value="build" />
+                <arg value="--buildfile:@{project}" />
+            </exec>
+        </sequential>
+    </macrodef>
+
+    <!-- set properties -->
+    <property name="src"               location="${basedir}/src" />
+    <property name="main-src-java"     location="${src}/main/java" />
+    <property name="test-src-java"     location="${src}/test/java" />
+    <property name="target"            location="${basedir}/target" />
+    <property name="dist-src"          location="${target}/dist-src" />
+    <property name="generated-sources" location="${target}/generated-sources" />
+    <property name="gen-src-java"      location="${generated-sources}/main/etch/java" />
+    <property name="gen-src-csharp"    location="${generated-sources}/main/etch/csharp" />
+    <property name="bin"               location="${target}/bin" />
+    <property name="classes"           location="${target}/classes" />
+    <property name="classes-test"      location="${target}/classes-test" />
+    <property name="test-results"      location="${target}/test-results" />
+    <property name="nunit-results"     location="${target}/nunit-results" />
+    <property name="dist"              location="${basedir}/../../target/Installers/dist" />
+
+    <!-- initialize -->
+    <target name="init" >
+        <mkdir dir="${target}" />
+        <mkdir dir="${dist-src}" />
+        <mkdir dir="${generated-sources}" />
+        <mkdir dir="${gen-src-java}" />
+        <mkdir dir="${gen-src-csharp}" />
+        <mkdir dir="${bin}" />
+        <mkdir dir="${classes}" />
+        <mkdir dir="${classes-test}" />
+        <mkdir dir="${test-results}" />
+        <mkdir dir="${nunit-results}" />
+    </target>
+
+    <!-- build the server -->
+    <target name="generate-sources" depends="init" >
+        <!-- generate sources -->
+
+        <etch home="${etch.home}"
+              file="${src}/main/etch/Perf.etch"
+              binding="java"
+              outputDir="${gen-src-java}" />
+
+        <etch home="${etch.home}"
+              file="${src}/main/etch/Perf.etch"
+              binding="csharp"
+              outputDir="${gen-src-csharp}" />
+    </target>
+
+    <property name="etch-java-runtime-name"
+        value="etch-java-runtime-${etch.version}.jar" />
+
+    <property name="Etch.dependency.java.runtime"
+        location="${etch.home}/lib/${etch-java-runtime-name}" />
+
+    <target name="build-java" depends="generate-sources" >
+        <!-- compile sources -->
+
+        <javac target="1.5" destdir="${classes}" >
+            <src path="${gen-src-java}" />
+            <src path="${main-src-java}" />
+            <classpath>
+                <pathelement location="${Etch.dependency.java.runtime}" />
+            </classpath>
+        </javac>
+
+        <javac target="1.5" destdir="${classes-test}" >
+            <src path="${gen-src-java}" />
+            <src path="${main-src-java}" />
+            <src path="${test-src-java}" />
+            <classpath>
+                <pathelement location="${Etch.dependency.java.runtime}" />
+                <pathelement location="${Etch.dependency.junit.jar}" />
+            </classpath>
+        </javac>
+
+        <!-- Create Jar -->
+        <jar jarfile="${bin}/perf.jar" >
+            <manifest>
+                <attribute name="Class-Path" value="${etch-java-runtime-name}" />
+            </manifest>
+            <fileset dir="${classes}" >
+                <include name="**/*" />
+            </fileset>
+        </jar>
+
+        <!-- copy in dependencies -->
+        <copy todir="${bin}" file="${Etch.dependency.java.runtime}" />
+    </target>
+
+    <target name="build-csharp-with-mono" depends="generate-sources" if="USE.mono" >
+        <mdtool dir="${src}/main/csharp/PerfClientProj" project="PerfClientProj.csproj" />
+        <mdtool dir="${src}/main/csharp/PerfListenerProj" project="PerfListenerProj.csproj" />
+    </target>
+
+    <target name="build-csharp-with-dotnet" depends="generate-sources" if="USE.dotnet" >
+        <msbuild buildfile="${src}/main/csharp/PerfListenerProj/PerfListenerProj.csproj" >
+            <property name="Configuration" value="${build.target}" />
+        </msbuild>
+        <msbuild buildfile="${src}/main/csharp/PerfClientProj/PerfClientProj.csproj" >
+            <property name="Configuration" value="${build.target}" />
+        </msbuild>
+        <msbuild buildfile="${src}/test/csharp/PerfTestProj/PerfTestProj.csproj" >
+            <property name="Configuration" value="${build.target}" />
+        </msbuild>
+        <copy todir="${bin}" >
+            <fileset dir="${src}/main/csharp/PerfListenerProj/bin/${build.target}" >
+                <include name="*" />
+            </fileset>
+            <fileset dir="${src}/main/csharp/PerfClientProj/bin/${build.target}" >
+                <include name="*" />
+            </fileset>
+        </copy>
+    </target>
+
+    <target name="build-csharp" depends="build-csharp-with-mono,build-csharp-with-dotnet" />
+
+    <target name="build" depends="build-java,build-csharp" />
+
+    <!-- run unit tests -->
+
+    <target name="test-java" depends="build-java" >
+        <!-- Run Unit Tests -->
+        <junit printsummary="yes" haltonfailure="no" dir="${classes-test}"
+            errorProperty="build.tests.fail" failureProperty="build.tests.fail" >
+            <classpath>
+                <pathelement location="${classes-test}" />
+                <pathelement location="${Etch.dependency.java.runtime}" />
+                <pathelement location="${Etch.dependency.junit.jar}" />
+            </classpath>
+            <formatter type="xml" />
+            <batchtest fork="true" todir="${test-results}" >
+                <fileset dir="${test-src-java}" >
+                    <include name="**/Test*.java" />
+                </fileset>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="test-csharp" depends="build-csharp" if="BUILD.csharp" >
+         <nunit xmlout="${nunit-results}/NUnitResults.xml">
+             <testassembly name="${src}/test/csharp/PerfTestProj/bin/${build.target}/PerfTestProj.dll" />
+         </nunit>
+
+         <xslt style="${Etch.buildSupportDirectory}/NUnitToJUnit.xsl"
+                 in="${nunit-results}/NUnitResults.xml" out="${test-results}/TEST-NUnitResults.xml" />
+   </target>
+
+    <target name="test" depends="build,test-java,test-csharp,done" >
+    </target>
+
+    <target name="done" depends="build" >
+        <echo>
+
+Build Complete!
+
+To run java performance example, open a cmd window and run these
+commands:
+
+> cd target\bin
+> start java -cp perf.jar org.apache.etch.examples.perf.MainPerfListener
+> start java -cp perf.jar org.apache.etch.examples.perf.MainPerfClient
+
+To run csharp example:
+
+> cd target\bin
+> start perfListener.exe
+> start perfClient.exe
+
+You can mix and match the various clients and listeners.
+
+        </echo>
+    </target>
+
+    <!-- build everything -->
+    <target name="init-debug" >
+        <property name="build.target" value="Debug" />
+    </target>
+
+    <target name="init-release" >
+        <property name="build.target" value="Release" />
+    </target>
+
+   <target name="dist-src" >
+       <copy file="dist-build.xml" tofile="${dist-src}/build.xml" overwrite="true" >
+           <filterset refid="Etch.buildTokens" />
+       </copy>    
+        <copy file="README.txt" tofile="${dist-src}/README.txt" overwrite="true" />
+        
+        <copy todir="${dist-src}/src/main/etch" overwrite="true" >
+            <fileset dir="${src}/main/etch" >
+                <exclude name="**/.svn/**" />
+                <include name="**/*.etch" />
+            </fileset>
+        </copy>
+        
+        <copy todir="${dist-src}/src/main/java" overwrite="true" >
+            <fileset dir="${src}/main/java" >
+                <exclude name="**/.svn/**" />
+                <include name="**/*.java" />
+            </fileset>
+        </copy>
+        
+        <copy todir="${dist-src}/src/main/csharp" overwrite="true" >
+            <fileset dir="${src}/main/csharp" >
+                <exclude name="**/.svn/**" />
+                <include name="**/*.cs" />
+            </fileset>
+        </copy>
+        
+        <copy todir="${dist}/examples/perf" overwrite="true" >
+            <fileset dir="${dist-src}" />
+        </copy>
+    </target>
+
+    <target name="debug" depends="dist-src,init-debug,test" />
+    <target name="release" depends="dist-src,init-release,test" />
+
+    <!-- clean -->
+    <target name="clean" >
+        <delete dir="${target}" quiet="true" />
+        <delete dir="${src}/main/csharp/PerfClientProj/bin" quiet="true" />
+        <delete dir="${src}/main/csharp/PerfClientProj/obj" quiet="true" />
+        <delete dir="${src}/main/csharp/PerfListenerProj/bin" quiet="true" />
+        <delete dir="${src}/main/csharp/PerfListenerProj/obj" quiet="true" />
+        <delete dir="${src}/test/csharp/PerfTestProj/bin" quiet="true" />
+        <delete dir="${src}/test/csharp/PerfTestProj/obj" quiet="true" />
+    </target>
+</project>
diff --git a/examples/perf/dist-build.xml b/examples/perf/dist-build.xml
new file mode 100644
index 0000000..50dba72
--- /dev/null
+++ b/examples/perf/dist-build.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-perf-perf" basedir="." default="build">
+    <description>Perf Perf</description>
+
+    <property name="etch.home" location="${basedir}/../.."/>
+    <property name="etch.version" value="@EtchVersion@"/>
+    <property name="etch-java-runtime-name" value="etch-java-runtime-${etch.version}.jar"/>
+
+    <property name="etch-ant-plugin.jar"   location="${etch.home}/lib/etch-ant-plugin-${etch.version}.jar"/>
+    <property name="etch-java-runtime.jar" location="${etch.home}/lib/${etch-java-runtime-name}"/>
+    <property name="etch.dll"              location="${etch.home}/lib/Etch.dll"/>
+
+    <property name="src"               location="${basedir}/src"/>
+    <property name="src-main-etch"     location="${src}/main/etch"/>
+    <property name="src-main-java"     location="${src}/main/java"/>
+    <property name="src-main-csharp"   location="${src}/main/csharp"/>
+    <property name="target"            location="${basedir}/target"/>
+    <property name="generated-sources" location="${target}/generated-sources"/>
+    <property name="gensrc-main-etch-java" location="${generated-sources}/main/etch/java"/>
+    <property name="gensrc-main-etch-csharp" location="${generated-sources}/main/etch/csharp"/>
+    <property name="classes"           location="${target}/classes"/>
+    <property name="bin"               location="${target}/bin"/>
+    
+    <condition property="BUILD.csharp" >
+        <os family="windows" />
+    </condition>    
+
+    <taskdef
+        resource="org/apache/etch/tools/ant/etch.xml"
+        classpath="${etch-ant-plugin.jar}"/>
+
+    <target name="build" depends="build-java, build-csharp, done"/>
+
+    <target name="build-java" depends="gensrc-java">
+        <javac destdir="${classes}" source="1.5" debug="true">
+            <classpath>
+                <pathelement location="${etch-java-runtime.jar}"/>
+            </classpath>
+            <src path="${src-main-java}"/>
+            <src path="${gensrc-main-etch-java}"/>
+        </javac>
+
+        <jar jarfile="${bin}/perf.jar">
+            <manifest>
+                <attribute name="Class-Path" value="${etch-java-runtime-name}"/>
+            </manifest>
+            <fileset dir="${classes}"/>
+        </jar>
+
+        <copy todir="${bin}" file="${etch-java-runtime.jar}"/>
+    </target>
+
+    <target name="done">
+        <echo>
+
+To run java performance example, open a cmd window and run these
+commands:
+
+> cd target\bin
+> start java -cp perf.jar etch.examples.perf.MainPerfListener
+> start java -cp perf.jar etch.examples.perf.MainPerfClient
+
+To run csharp example:
+
+> cd target\bin
+> start perfListener.exe
+> start perfClient.exe
+
+You can mix and match the various clients and listeners.
+
+        </echo>
+    </target>
+
+    <target name="build-csharp" depends="gensrc-csharp" if="BUILD.csharp" >
+        <csc
+                debug="true"
+                warnLevel="1"
+                unsafe="false"
+                targetType="exe"
+                incremental="false"
+                mainClass = "etch.examples.perf.MainPerfClient"
+                destFile="${bin}/perfClient.exe">
+            <src dir="${src-main-csharp}/perfClientProj" includes="**/*.cs"/>
+            <src dir="${src-main-csharp}/etch.examples.perf" includes="**/*.cs"/>
+            <src dir="${gensrc-main-etch-csharp}" includes="**/*.cs"/>
+            <reference file="${etch.dll}"/>
+        </csc>
+
+        <csc
+                debug="true"
+                warnLevel="1"
+                unsafe="false"
+                targetType="exe"
+                incremental="false"
+                mainClass = "etch.examples.perf.MainPerfListener"
+                destFile="${bin}/perfListener.exe">
+            <src dir="${src-main-csharp}/perfListenerProj" includes="**/*.cs"/>
+            <src dir="${src-main-csharp}/etch.examples.perf" includes="**/*.cs"/>
+            <src dir="${gensrc-main-etch-csharp}" includes="**/*.cs"/>
+            <reference file="${etch.dll}"/>
+        </csc>
+
+        <copy todir="${bin}" file="${etch.dll}"/>
+    </target>
+
+    <target name="gensrc" depends="gensrc-java, gensrc-csharp"/>
+
+    <target name="gensrc-java" depends="init">
+        <etch
+            home="${etch.home}"
+            binding="java"
+            quiet="true"
+            outputDir="${gensrc-main-etch-java}"
+            file="${src-main-etch}/Perf.etch"/>
+    </target>
+
+    <target name="gensrc-csharp" depends="init">
+        <etch
+            home="${etch.home}"
+            binding="csharp"
+            quiet="true"
+            outputDir="${gensrc-main-etch-csharp}"
+            file="${src-main-etch}/Perf.etch"/>
+    </target>
+
+    <target name="init">
+        <mkdir dir="${target}"/>
+        <mkdir dir="${generated-sources}"/>
+        <mkdir dir="${gensrc-main-etch-java}"/>
+        <mkdir dir="${gensrc-main-etch-csharp}"/>
+        <mkdir dir="${classes}"/>
+        <mkdir dir="${bin}"/>
+    </target>
+
+    <target name="clean">
+        <delete dir="${target}"/>
+    </target>
+</project>
diff --git a/examples/perf/src/main/csharp/PerfClientProj/PerfClientProj.csproj b/examples/perf/src/main/csharp/PerfClientProj/PerfClientProj.csproj
new file mode 100644
index 0000000..56d8ea8
--- /dev/null
+++ b/examples/perf/src/main/csharp/PerfClientProj/PerfClientProj.csproj
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{D2AA03D8-1555-4A9B-8618-FF12A15BBB6E}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>etch.examples.perf</RootNamespace>
+    <AssemblyName>PerfClient</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\BasePerfClient.cs">
+      <Link>BasePerfClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\BasePerfServer.cs">
+      <Link>BasePerfServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\Perf.cs">
+      <Link>Perf.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\PerfClient.cs">
+      <Link>PerfClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\PerfHelper.cs">
+      <Link>PerfHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\PerfServer.cs">
+      <Link>PerfServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\RemotePerf.cs">
+      <Link>RemotePerf.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\RemotePerfClient.cs">
+      <Link>RemotePerfClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\RemotePerfServer.cs">
+      <Link>RemotePerfServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\StubPerf.cs">
+      <Link>StubPerf.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\StubPerfClient.cs">
+      <Link>StubPerfClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\StubPerfServer.cs">
+      <Link>StubPerfServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\ValueFactoryPerf.cs">
+      <Link>ValueFactoryPerf.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.perf\ImplPerfClient.cs">
+      <Link>ImplPerfClient.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.perf\ImplPerfServer.cs">
+      <Link>ImplPerfServer.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.perf\MainPerfClient.cs">
+      <Link>MainPerfClient.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\..\..\binding-csharp\runtime\src\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/examples/perf/src/main/csharp/PerfClientProj/Properties/AssemblyInfo.cs b/examples/perf/src/main/csharp/PerfClientProj/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e4ecf5b
--- /dev/null
+++ b/examples/perf/src/main/csharp/PerfClientProj/Properties/AssemblyInfo.cs
@@ -0,0 +1,48 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Perf Client")]
+[assembly: AssemblyDescription("Perf Client Executable")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Cisco Systems")]
+[assembly: AssemblyProduct("Etch")]
+[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("7369eb5c-6f20-4f29-866b-204e95bdb5cd")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+[assembly: AssemblyVersion("0.0.0.1")]
+[assembly: AssemblyFileVersion("0.0.0.1")]
diff --git a/examples/perf/src/main/csharp/PerfListenerProj/PerfListenerProj.csproj b/examples/perf/src/main/csharp/PerfListenerProj/PerfListenerProj.csproj
new file mode 100644
index 0000000..f3a8c61
--- /dev/null
+++ b/examples/perf/src/main/csharp/PerfListenerProj/PerfListenerProj.csproj
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{4B9CE732-601A-4A74-A1D5-AF78251FEDD2}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>etch.examples.perf</RootNamespace>
+    <AssemblyName>PerfListener</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\BasePerfClient.cs">
+      <Link>BasePerfClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\BasePerfServer.cs">
+      <Link>BasePerfServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\Perf.cs">
+      <Link>Perf.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\PerfClient.cs">
+      <Link>PerfClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\PerfHelper.cs">
+      <Link>PerfHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\PerfServer.cs">
+      <Link>PerfServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\RemotePerf.cs">
+      <Link>RemotePerf.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\RemotePerfClient.cs">
+      <Link>RemotePerfClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\RemotePerfServer.cs">
+      <Link>RemotePerfServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\StubPerf.cs">
+      <Link>StubPerf.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\StubPerfClient.cs">
+      <Link>StubPerfClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\StubPerfServer.cs">
+      <Link>StubPerfServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\ValueFactoryPerf.cs">
+      <Link>ValueFactoryPerf.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.perf\ImplPerfServer.cs">
+      <Link>ImplPerfServer.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.perf\MainPerfListener.cs">
+      <Link>MainPerfListener.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\..\..\binding-csharp\runtime\src\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/examples/perf/src/main/csharp/PerfListenerProj/Properties/AssemblyInfo.cs b/examples/perf/src/main/csharp/PerfListenerProj/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..4ad86ea
--- /dev/null
+++ b/examples/perf/src/main/csharp/PerfListenerProj/Properties/AssemblyInfo.cs
@@ -0,0 +1,48 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Perf Listener")]
+[assembly: AssemblyDescription("Perf Listener Executable")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Etch")]
+[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c74cf3bd-758b-4e40-9537-e1793f0fdcce")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+[assembly: AssemblyVersion("0.0.0.1")]
+[assembly: AssemblyFileVersion("0.0.0.1")]
diff --git a/examples/perf/src/main/csharp/etch.examples.perf/ImplPerfClient.cs b/examples/perf/src/main/csharp/etch.examples.perf/ImplPerfClient.cs
new file mode 100644
index 0000000..17b5c1d
--- /dev/null
+++ b/examples/perf/src/main/csharp/etch.examples.perf/ImplPerfClient.cs
@@ -0,0 +1,42 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+namespace org.apache.etch.examples.perf
+{
+	///<summary>Implementation for ImplPerfClient</summary>
+	public class ImplPerfClient : BasePerfClient
+	{
+		/// <summary>Constructs the ImplPerfClient.</summary>
+ 		/// <param name="server">a connection to the server session. Use this to
+ 		/// send a message to the server.</param>
+		public ImplPerfClient(RemotePerfServer server)
+		{
+			this.server = server;
+		}
+		
+		/// <summary>A connection to the server session. Use this to
+ 		/// send a message to the server.</summary>
+#pragma warning disable 219
+		private readonly RemotePerfServer server;
+#pragma warning restore 219
+	
+		// TODO: Implement delegates or provide implementation of PerfClient
+		// messages from the server	
+	}
+}
\ No newline at end of file
diff --git a/examples/perf/src/main/csharp/etch.examples.perf/ImplPerfServer.cs b/examples/perf/src/main/csharp/etch.examples.perf/ImplPerfServer.cs
new file mode 100644
index 0000000..89e0ab1
--- /dev/null
+++ b/examples/perf/src/main/csharp/etch.examples.perf/ImplPerfServer.cs
@@ -0,0 +1,72 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+
+namespace org.apache.etch.examples.perf
+{
+    public class ImplPerfServer : BasePerfServer
+    {
+        public ImplPerfServer(RemotePerfClient client)
+        {
+            this.client = client;
+        }
+
+#pragma warning disable 219
+        private readonly RemotePerfClient client;
+#pragma warning restore 219
+
+        #region PerfServer Members
+
+        public override int? add(int? x, int? y)
+        {
+            return x + y;
+        }
+
+        public override int? sum(int[] values)
+        {
+            int sum = 0;
+            foreach (int value in values)
+                sum += value;
+            return sum;
+        }
+
+        public override void report(int? code, string msg)
+        {
+            // do nothing
+        }
+
+        public override types.Perf.Point dist(types.Perf.Point a, types.Perf.Point b)
+        {
+            return new types.Perf.Point(b.x - a.x, b.y - a.y);
+        }
+
+        public override DateTime? add2(DateTime? ts, long? ms)
+        {
+            return ts.Value + new TimeSpan(ms.Value*10000);
+        }
+
+        public override void report2(DateTime? ts, int? code, string msg)
+        {
+            // do nothing.
+        }
+
+        #endregion
+    }
+}
diff --git a/examples/perf/src/main/csharp/etch.examples.perf/MainPerfClient.cs b/examples/perf/src/main/csharp/etch.examples.perf/MainPerfClient.cs
new file mode 100644
index 0000000..5bef127
--- /dev/null
+++ b/examples/perf/src/main/csharp/etch.examples.perf/MainPerfClient.cs
@@ -0,0 +1,145 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using org.apache.etch.examples.perf.types.Perf;
+
+namespace org.apache.etch.examples.perf
+{
+    ///<summary>Main implementation for PerfClient.</summary>
+    public class MainPerfClient : PerfHelper.PerfClientFactory, PerfHelper.PerfServerFactory
+    {
+        ///<summary>Main for PerfClient</summary>
+        ///<param name="args">Command Line Arguments</param>
+        public static void Main(String[] args)
+        {
+            const string uri = "tcp://localhost:4004";
+            bool startListener = false;
+            const int maxWaitTime = 4000;
+
+            ServerFactory listener;
+
+            if (startListener)
+            {
+                listener = PerfHelper.NewListener(uri, null, new MainPerfClient());
+                listener.TransportControl(TransportConsts.START_AND_WAIT_UP, maxWaitTime);
+            }
+            else
+            {
+                listener = null;
+            }
+
+            MainPerfClient implFactory = new MainPerfClient();
+
+            // run a preliminary test
+
+            {
+                RemotePerfServer server = PerfHelper.NewServer(uri, null, implFactory);
+
+                // Connect to the service
+                server._StartAndWaitUp(maxWaitTime);
+
+                Assertion.Check(server.add(2, 3) == 5, "server.add(2, 3) == 5");
+
+                Assertion.Check(server.add(3, 4) == 7, "server.add( 3, 4 ) == 7");
+
+                Assertion.Check(server.sum(new int[] {1, 2, 3}) == 6,
+                                "server.sum( new int[] { 1, 2, 3 } ) == 6");
+
+                Assertion.Check(server.sum(new int[] {2, 3, 4}) == 9,
+                                "server.sum( new int[] { 2, 3, 4 } ) == 9");
+
+                server.report(18, "starting");
+
+                server.report(19, "stopping");
+
+                Point r = server.dist(new Point(1, 2), new Point(3, 5));
+                Assertion.Check(r.x == 2, "r.x == 2");
+                Assertion.Check(r.y == 3, "r.y == 3");
+
+                r = server.dist(new Point(10, 9), new Point(4, 5));
+                Assertion.Check(r.x == -6, "r.x == -6");
+                Assertion.Check(r.y == -4, "r.y == -4");
+
+                DateTime t0 = DateTime.Now;
+                long adj = 3600000L;
+
+                DateTime? t1 = server.add2(t0, adj);
+                TimeSpan ts = t1.Value - t0;
+                //Console.WriteLine("ts = {0}", ts.Ticks);
+                Assertion.Check(IsNearly(ts.Ticks / 10000, adj, 1),
+                    String.Format("server.add2( {0}, {1} ) => {2} [bogus!]", t0, adj, t1));
+
+                t1 = server.add2(t0, -adj);
+                ts = t1.Value - t0;
+                //Console.WriteLine("ts = {0}", ts.Ticks);
+                Assertion.Check(IsNearly(ts.Ticks / 10000, -adj, 1),
+                    String.Format("server.add2( {0}, {1} ) => {2} [bogus!]", t0, -adj, t1));
+
+                server.report2(DateTime.Now, 20, "begin");
+
+                server.report2(DateTime.Now, 21, "end");
+
+                // Disconnect from the service
+                server._StopAndWaitDown(maxWaitTime);
+            }
+
+            const int runtime = 60;
+            const int trials = 3;
+            //const bool full = false;
+
+			new PerfTest( "add", runtime, trials,
+                delegate(long n)
+			    {
+					    RemotePerfServer server = PerfHelper.NewServer( uri, null, implFactory );
+					    server._StartAndWaitUp( maxWaitTime );
+    					
+					    while (n-- > 0)
+						    server.add( 1000000000, 2000000000 );
+    					
+					    server._StopAndWaitDown( maxWaitTime );
+			    }).Run();
+
+            if (listener != null)
+                listener.TransportControl(TransportConsts.STOP_AND_WAIT_DOWN, maxWaitTime);
+
+            Console.WriteLine("done");
+        }
+
+        private static bool IsNearly(long a, long b, long diff)
+        {
+            return Math.Abs(a - b) <= diff;
+        }
+
+        ///<summary>Return a new instance of PerfClient.</summary>
+        ///<param name="server">Reference to remote service</param>
+        ///<returns>Client Implementation</returns>
+        public PerfClient NewPerfClient(RemotePerfServer server)
+        {
+            return new ImplPerfClient(server);
+        }
+
+        public PerfServer NewPerfServer(RemotePerfClient client)
+        {
+            return new ImplPerfServer(client);
+        }
+    }
+}
\ No newline at end of file
diff --git a/examples/perf/src/main/csharp/etch.examples.perf/MainPerfListener.cs b/examples/perf/src/main/csharp/etch.examples.perf/MainPerfListener.cs
new file mode 100644
index 0000000..3223a18
--- /dev/null
+++ b/examples/perf/src/main/csharp/etch.examples.perf/MainPerfListener.cs
@@ -0,0 +1,52 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace org.apache.etch.examples.perf
+{
+	///<summary>Main implementation for PerfListener.</summary>
+	public class MainPerfListener : PerfHelper.PerfServerFactory
+	{
+ 		///<summary>Main for PerfListener.</summary>
+		///<param name="args">Command Line Arguments</param>
+		public static void Main(String[] args)
+		{
+            const string uri = "tcp://localhost:4004";
+			
+            ServerFactory listener = PerfHelper.NewListener(uri, null,
+                new MainPerfListener());
+			
+			// Start the Listener
+			listener.TransportControl( TransportConsts.START_AND_WAIT_UP, 4000 );
+
+            Console.WriteLine("ready");
+		}
+
+		///<summary>Return a new instance of PerfServer.</summary>
+		///<param name="client">Reference to remote service</param>
+		///<returns>Server Implementation</returns>
+		public PerfServer NewPerfServer( RemotePerfClient client )
+		{
+			return new ImplPerfServer( client );
+		}
+	}
+}
\ No newline at end of file
diff --git a/examples/perf/src/main/etch/Perf.etch b/examples/perf/src/main/etch/Perf.etch
new file mode 100644
index 0000000..781acb6
--- /dev/null
+++ b/examples/perf/src/main/etch/Perf.etch
@@ -0,0 +1,77 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.examples.perf
+
+/** A service to test performance */
+service Perf
+{
+	/**
+	 * Adds two integers and returns the sum.
+	 * @param x the first integer.
+	 * @param y the second integer.
+	 * @return the sum of x and y.
+	 */
+	int add( int x, int y )
+	
+	/**
+	 * Adds an array of integers and returns the sum.
+	 * @param values an array of integers to be summed.
+	 * @return the sum of values.
+	 */
+	int sum( int[] values )
+	
+	/**
+	 * Reports the event defined by code and a descriptive message.
+	 * @param code a simple code describing the event.
+	 * @param msg a descriptive message.
+	 */
+	@Oneway
+	void report( int code, string msg )
+	
+	/**
+	 * A two dimensional coordinate.
+	 * @param x the x-axis coordinate.
+	 * @param y the y-axis coordinate.
+	 */
+	struct Point ( int x, int y )
+	
+	/**
+	 * Calculates the distance between two points.
+	 * @param a a point
+	 * @param b a point
+	 * @return b-a
+	 */
+	Point dist( Point a, Point b )
+	
+	/**
+	 * Adds the specified number of milliseconds to the timestamp.
+	 * @param ts the timestamp.
+	 * @param ms the number of milliseconds to add.
+	 * @return the adjusted timestamp.
+	 */
+	Datetime add2( Datetime ts, long ms )
+	
+	/**
+	 * Reports the event defined by ts, code, and msg.
+	 * @param ts the event timestamp
+	 * @param code a simple code describing the event.
+	 * @param msg a descriptive message.
+	 */
+	@Oneway
+	void report2( Datetime ts, int code, string msg )
+}
diff --git a/examples/perf/src/main/etch/readme.txt b/examples/perf/src/main/etch/readme.txt
new file mode 100644
index 0000000..092cbce
--- /dev/null
+++ b/examples/perf/src/main/etch/readme.txt
@@ -0,0 +1,4 @@
+from this directory, etch like this:
+
+etch -b java   -d ../../../target/generated-sources/main/etch/java   Perf.etch
+etch -b chsarp -d ../../../target/generated-sources/main/etch/csharp Perf.etch
diff --git a/examples/perf/src/main/java/org/apache/etch/examples/perf/ImplPerfClient.java b/examples/perf/src/main/java/org/apache/etch/examples/perf/ImplPerfClient.java
new file mode 100644
index 0000000..8350640
--- /dev/null
+++ b/examples/perf/src/main/java/org/apache/etch/examples/perf/ImplPerfClient.java
@@ -0,0 +1,46 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.perf;
+
+
+/**
+ * Your custom implementation of BasePerfClient. Add methods here to provide
+ * implementations of messages from the server.
+ */
+public class ImplPerfClient extends BasePerfClient
+{
+	/**
+	 * Constructs the ImplPerfClient.
+	 *
+	 * @param server a connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	public ImplPerfClient( RemotePerfServer server )
+	{
+		this.server = server;
+	}
+	
+	@SuppressWarnings("unused")
+	private final RemotePerfServer server;
+
+	// TODO insert methods here to provide implementations of PerfClient
+	// messages from the server.
+}
\ No newline at end of file
diff --git a/examples/perf/src/main/java/org/apache/etch/examples/perf/ImplPerfServer.java b/examples/perf/src/main/java/org/apache/etch/examples/perf/ImplPerfServer.java
new file mode 100644
index 0000000..d6e0ebd
--- /dev/null
+++ b/examples/perf/src/main/java/org/apache/etch/examples/perf/ImplPerfServer.java
@@ -0,0 +1,138 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.perf;
+
+import java.util.Date;
+
+import org.apache.etch.util.core.io.Session;
+
+
+
+/**
+ * Your custom implementation of BasePerfServer. Add methods here to provide
+ * implementations of messages from the client.
+ */
+public class ImplPerfServer extends BasePerfServer
+{
+	/**
+	 * Constructs the ImplPerfServer.
+	 *
+	 * @param client a connection to the client session. Use this to send a
+	 * message to the client.
+	 */
+	public ImplPerfServer( RemotePerfClient client )
+	{
+		this.client = client;
+//		name = "ImplPerfServer@"+Integer.toString( hashCode(), 36 );
+//		Log.report( "ImplPerfServerUp", "instance", this );
+//		t0 = System.nanoTime();
+	}
+	
+	@SuppressWarnings("unused")
+	private final RemotePerfClient client;
+	
+//	private final String name;
+	
+//	private final long t0;
+	
+//	@Override
+//	public String toString()
+//	{
+//		return name;
+//	}
+	
+	@Override
+	public Integer add( Integer x, Integer y )
+	{
+//		adds++;
+		return x + y;
+	}
+	
+//	private int adds;
+
+	@Override
+	public Integer sum( int[] values )
+	{
+//		sums++;
+		int sum = 0;
+		for (int value: values)
+			sum += value;
+		return sum;
+	}
+	
+//	private int sums;
+
+	@Override
+	public void report( Integer code, String msg )
+	{
+//		reports++;
+	}
+	
+//	private int reports;
+	
+	@Override
+	public Point dist( Point a, Point b )
+	{
+//		dists++;
+		return new Point( b.x - a.x, b.y - a.y );
+	}
+	
+//	private int dists;
+	
+	@Override
+	public Date add2( Date ts, Long ms )
+	{
+//		add2s++;
+		return new Date( ts.getTime()+ms );
+	}
+	
+//	private int add2s;
+	
+	@Override
+	public void report2( Date ts, Integer code, String msg )
+	{
+//		report2s++;
+	}
+	
+//	private int report2s;
+
+	@Override
+	public void _sessionNotify( Object event ) throws Exception
+	{
+		if (event == Session.DOWN)
+		{
+//			double time = (System.nanoTime() - t0) / 1000000000.0;
+//			int total = adds + sums + reports + dists + add2s + report2s;
+//			double rate = total / time;
+//			Log.report( "ImplPerfServerDown",
+//				"instance", this,
+//				"adds", adds,
+//				"sums", sums,
+//				"reports", reports,
+//				"dists", dists,
+//				"add2s", add2s,
+//				"report2s", report2s,
+//				"total", total,
+//				"time", time,
+//				"rate", rate );
+		}
+	}
+}
\ No newline at end of file
diff --git a/examples/perf/src/main/java/org/apache/etch/examples/perf/MainPerfClient.java b/examples/perf/src/main/java/org/apache/etch/examples/perf/MainPerfClient.java
new file mode 100644
index 0000000..60b4ad6
--- /dev/null
+++ b/examples/perf/src/main/java/org/apache/etch/examples/perf/MainPerfClient.java
@@ -0,0 +1,346 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.perf;
+
+import java.util.Date;
+
+import org.apache.etch.bindings.java.support.Mailbox;
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.examples.perf.Perf.Point;
+import org.apache.etch.examples.perf.PerfHelper.PerfClientFactory;
+import org.apache.etch.examples.perf.PerfHelper.PerfServerFactory;
+import org.apache.etch.util.Assertion;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.PerfTest;
+import org.apache.etch.util.core.io.Transport;
+
+
+/**
+ * Main program for PerfClient. This program makes a connection to the listener
+ * created by MainPerfListener.
+ */
+public class MainPerfClient implements PerfClientFactory, PerfServerFactory
+{
+	private static String uri;
+
+	private static int maxWaitTime;
+
+	private static int runtime;
+
+	private static int trials;
+
+	private static boolean full;
+
+	private static int[] threadCounts;
+
+	private static boolean startListener;
+
+	private static MainPerfClient implFactory;
+
+	/**
+	 * Main program for PerfClient.
+	 * 
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		Log.addSink( null );
+		Log.report( "MainPerfClient" );
+
+		uri = "tcp://localhost:4004";
+		maxWaitTime = 4000;
+		runtime = 4;
+		trials = 3;
+		full = false;
+		threadCounts = new int[]
+		{
+			1
+		};
+		startListener = args.length == 1 && args[0].equals( "startListener" );
+
+		implFactory = new MainPerfClient();
+
+		final ServerFactory listener;
+
+		if (startListener)
+		{
+			listener = PerfHelper.newListener( uri, null, implFactory );
+			listener.transportControl( Transport.START_AND_WAIT_UP, maxWaitTime );
+		}
+		else
+		{
+			listener = null;
+		}
+
+		// make sure test interfaces work.
+		
+		qualify();
+
+		// run tests
+
+		for (int nThreads : threadCounts)
+		{
+			perfAdd( nThreads );
+			perfAsyncAdd( nThreads );
+			perfReport( nThreads );
+			if (full)
+			{
+				perfSum( nThreads );
+				perfDist( nThreads );
+				perfAdd2( nThreads );
+				perfReport2( nThreads );
+			}
+		}
+
+		if (listener != null)
+			listener.transportControl( Transport.STOP_AND_WAIT_DOWN, maxWaitTime );
+	}
+
+	private static void perfReport2( int threads ) throws Exception
+	{
+		new PerfTest( "report2", runtime, trials, threads )
+		{
+			@Override
+			public void run( long n ) throws Exception
+			{
+				RemotePerfServer server = startServer();
+				
+				final Date d = new Date();
+				
+				while (n-- > 0)
+					server
+						.report2( d, 23,
+						// 50 characters:
+							"this message describes the specifics of a code 23." );
+
+				// sync up with message stream.
+				Assertion.check( server.add( 8, 9 ) == 17,
+					"server.add( 8, 9 ) == 17" );
+
+				stopServer( server );
+			}
+		}.run();
+	}
+
+	private static void perfAdd2( int threads ) throws Exception
+	{
+		new PerfTest( "add2", runtime, trials, threads )
+		{
+			@Override
+			public void run( long n ) throws Exception
+			{
+				RemotePerfServer server = startServer();
+
+				final Date d = new Date();
+				final long adj = 3600000L; // 1 hour
+
+				while (n-- > 0)
+					server.add2( d, adj );
+
+				stopServer( server );
+			}
+		}.run();
+	}
+
+	private static void perfDist( int threads ) throws Exception
+	{
+		new PerfTest( "dist", runtime, trials, threads )
+		{
+			@Override
+			public void run( long n ) throws Exception
+			{
+				RemotePerfServer server = startServer();
+				
+				final int X = 1000000000;
+				final int Y = 2000000000;
+
+				while (n-- > 0)
+					server.dist( new Point( 1, 2 ), new Point( X, Y ) );
+
+				stopServer( server );
+			}
+		}.run();
+	}
+
+	private static void perfSum( int threads ) throws Exception
+	{
+		final int[] values = new int[1000];
+		for (int i = 0; i < values.length; i++)
+			values[i] = i;
+
+		new PerfTest( "sum-" + values.length, runtime, trials, threads )
+		{
+			@Override
+			public void run( long n ) throws Exception
+			{
+				RemotePerfServer server = startServer();
+
+				while (n-- > 0)
+					server.sum( values );
+
+				stopServer( server );
+			}
+		}.run();
+	}
+
+	private static void perfReport( int threads ) throws Exception
+	{
+		new PerfTest( "report", runtime, trials, threads )
+		{
+			@Override
+			public void run( long n ) throws Exception
+			{
+				RemotePerfServer server = startServer();
+
+				while (n-- > 0)
+					server.report( 23,
+					// 50 characters:
+						"this message describes the specifics of a code 23." );
+
+				// sync up with message stream.
+				Assertion.check( server.add( 8, 9 ) == 17,
+					"server.add( 8, 9 ) == 17" );
+
+				stopServer( server );
+			}
+		}.run();
+	}
+
+	private static void perfAsyncAdd( int threads ) throws Exception
+	{
+		new PerfTest( "async add", runtime, trials, threads )
+		{
+			@Override
+			public void run( long n ) throws Exception
+			{
+				RemotePerfServer server = startServer();
+				
+				final int X = 1000000000;
+				final int Y = 2000000000;
+
+				if (n-- > 0)
+				{
+					Mailbox mb1 = server._async._begin_add( X, Y );
+					while (n-- > 0)
+					{
+						Mailbox mb2 = server._async._begin_add( X, Y );
+						server._async._end_add( mb1 );
+						mb1 = mb2;
+					}
+					server._async._end_add( mb1 );
+				}
+
+				stopServer( server );
+			}
+		}.run();
+	}
+
+	private static void perfAdd( int threads ) throws Exception
+	{
+		new PerfTest( "add", runtime, trials, threads )
+		{
+			@Override
+			public void run( long n ) throws Exception
+			{
+				RemotePerfServer server = startServer();
+				
+				final int X = 1000000000;
+				final int Y = 2000000000;
+
+				while (n-- > 0)
+					server.add( X, Y );
+
+				stopServer( server );
+			}
+		}.run();
+	}
+
+	private static RemotePerfServer startServer() throws Exception
+	{
+		RemotePerfServer server = PerfHelper.newServer( uri, null, implFactory );
+		server._startAndWaitUp( maxWaitTime );
+		return server;
+	}
+
+	private static void stopServer( RemotePerfServer server ) throws Exception
+	{
+		server._stopAndWaitDown( maxWaitTime );
+	}
+
+	private static void qualify() throws Exception
+	{
+		RemotePerfServer server = startServer();
+
+		Assertion.check( server.add( 2, 3 ) == 5, "server.add( 2, 3 ) == 5" );
+
+		Assertion.check( server.add( 3, 4 ) == 7, "server.add( 3, 4 ) == 7" );
+
+		Assertion.check( server.sum( new int[]
+		{
+			1, 2, 3
+		} ) == 6, "server.sum( new int[] { 1, 2, 3 } ) == 6" );
+
+		Assertion.check( server.sum( new int[]
+		{
+			2, 3, 4
+		} ) == 9, "server.sum( new int[] { 2, 3, 4 } ) == 9" );
+
+		server.report( 18, "starting" );
+
+		server.report( 19, "stopping" );
+
+		Point r = server.dist( new Point( 1, 2 ), new Point( 3, 5 ) );
+		Assertion.check( r.x == 2, "r.x == 2" );
+		Assertion.check( r.y == 3, "r.y == 3" );
+
+		r = server.dist( new Point( 10, 9 ), new Point( 4, 5 ) );
+		Assertion.check( r.x == -6, "r.x == -6" );
+		Assertion.check( r.y == -4, "r.y == -4" );
+
+		Date t0 = new Date();
+		long adj = 3600000L;
+
+		Date t1 = server.add2( t0, adj );
+		Assertion.check( t1.getTime() - t0.getTime() == adj, String.format(
+			"server.add2( %s, %s ) => %s [bogus!]", t0, adj, t1 ) );
+
+		t1 = server.add2( t0, -adj );
+		Assertion.check( t1.getTime() - t0.getTime() == -adj, String.format(
+			"server.add2( %s, %s ) => %s [bogus!]", t0, -adj, t1 ) );
+
+		server.report2( new Date(), 20, "begin" );
+
+		server.report2( new Date(), 21, "end" );
+
+		stopServer( server );
+	}
+
+	public PerfClient newPerfClient( RemotePerfServer server ) throws Exception
+	{
+		return new ImplPerfClient( server );
+	}
+
+	public PerfServer newPerfServer( RemotePerfClient client ) throws Exception
+	{
+		return new ImplPerfServer( client );
+	}
+}
diff --git a/examples/perf/src/main/java/org/apache/etch/examples/perf/MainPerfListener.java b/examples/perf/src/main/java/org/apache/etch/examples/perf/MainPerfListener.java
new file mode 100644
index 0000000..f4056d7
--- /dev/null
+++ b/examples/perf/src/main/java/org/apache/etch/examples/perf/MainPerfListener.java
@@ -0,0 +1,58 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.perf;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.core.io.Transport;
+
+/**
+ * Main program for PerfServer. This program makes a listener to accept
+ * connections from MainPerfClient.
+ */
+public class MainPerfListener implements PerfHelper.PerfServerFactory
+{
+	/**
+	 * Main program for PerfServer.
+	 * 
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main( String ... args ) throws Exception
+	{
+		Log.addSink( null );
+		Log.report( "MainPerfListener" );
+		
+		final String uri = "tcp://localhost:4004";
+		
+		ServerFactory listener = PerfHelper.newListener( uri, null,
+			new MainPerfListener() );
+
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+		
+		System.out.println( "ready" );
+	}
+
+	public PerfServer newPerfServer( RemotePerfClient client )
+	{
+		return new ImplPerfServer( client );
+	}
+}
diff --git a/examples/perf/src/test/csharp/PerfTestProj/PerfTestProj.csproj b/examples/perf/src/test/csharp/PerfTestProj/PerfTestProj.csproj
new file mode 100644
index 0000000..a848dc3
--- /dev/null
+++ b/examples/perf/src/test/csharp/PerfTestProj/PerfTestProj.csproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{47FDB15C-6DE2-4191-A41C-1993B714B4CD}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>PerfTestProj</RootNamespace>
+    <AssemblyName>PerfTestProj</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="nunit.framework, Version=2.4.7.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>$(NUNIT_HOME)\bin\nunit.framework.dll</HintPath>
+      <SpecificVersion>False</SpecificVersion>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\BasePerfClient.cs">
+      <Link>BasePerfClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\BasePerfServer.cs">
+      <Link>BasePerfServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\Perf.cs">
+      <Link>Perf.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\PerfClient.cs">
+      <Link>PerfClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\PerfHelper.cs">
+      <Link>PerfHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\PerfServer.cs">
+      <Link>PerfServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\RemotePerf.cs">
+      <Link>RemotePerf.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\RemotePerfClient.cs">
+      <Link>RemotePerfClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\RemotePerfServer.cs">
+      <Link>RemotePerfServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\StubPerf.cs">
+      <Link>StubPerf.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\StubPerfClient.cs">
+      <Link>StubPerfClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\StubPerfServer.cs">
+      <Link>StubPerfServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.examples.perf\ValueFactoryPerf.cs">
+      <Link>ValueFactoryPerf.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.perf\ImplPerfClient.cs">
+      <Link>ImplPerfClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.perf\ImplPerfServer.cs">
+      <Link>ImplPerfServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.perf\MainPerfClient.cs">
+      <Link>MainPerfClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.examples.perf\MainPerfListener.cs">
+      <Link>MainPerfListener.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.examples.perf\TestPerfServer.cs">
+      <Link>TestPerfServer.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\..\..\binding-csharp\runtime\src\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/examples/perf/src/test/csharp/PerfTestProj/Properties/AssemblyInfo.cs b/examples/perf/src/test/csharp/PerfTestProj/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b564cf2
--- /dev/null
+++ b/examples/perf/src/test/csharp/PerfTestProj/Properties/AssemblyInfo.cs
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("PerfTestProj")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("PerfTestProj")]
+[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("281472ff-b634-4e2a-93dd-9591e7b875f6")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/examples/perf/src/test/csharp/etch.examples.perf/TestPerfServer.cs b/examples/perf/src/test/csharp/etch.examples.perf/TestPerfServer.cs
new file mode 100644
index 0000000..49a5897
--- /dev/null
+++ b/examples/perf/src/test/csharp/etch.examples.perf/TestPerfServer.cs
@@ -0,0 +1,127 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+using org.apache.etch.examples.perf.types.Perf;
+
+namespace org.apache.etch.examples.perf
+{
+
+    /// <summary>
+    /// Unit Tests to test Perf
+    /// </summary>
+    /// 
+    [TestFixture]
+    public class TestPerfServer
+    {
+        private static RemotePerfServer server;
+
+        private static ServerFactory listener;
+
+        [TestFixtureSetUp]
+        public void StartListener()
+        {
+            String uri = "tcp://localhost:4010";
+
+            MainPerfListener implFactory = new MainPerfListener();
+            listener = PerfHelper.NewListener(uri, null, implFactory);
+
+            listener.TransportControl(TransportConsts.START_AND_WAIT_UP, 4000);
+
+            Console.WriteLine("Listener Started");
+
+        }
+
+        [SetUp]
+        public void MakeConnection()
+        {
+            String uri = "tcp://localhost:4010";
+
+            MainPerfClient client = new MainPerfClient();
+            server = PerfHelper.NewServer(uri, null, client);
+
+            server._StartAndWaitUp(4000);
+        }
+
+        [Test]
+        public void CheckConnection()
+        {
+            Assert.IsNotNull(server);
+        }
+
+        [Test]
+        public void TestAdd()
+        {
+            int? result = server.add(3, 5);
+            Assert.AreEqual(8, result);
+        }
+
+        [Test]
+        public void TestAdd2()
+        {
+            DateTime? d = DateTime.Now;
+            long? ms = 1000;
+            DateTime? expectedDate = d.Value + new TimeSpan(ms.Value * 10000);
+            DateTime? retDate = server.add2(d, ms);
+            Assert.AreEqual(expectedDate.Value.ToString(), retDate.Value.ToString());
+        }
+
+        [Test]
+        public void TestSum()
+        {
+            int[] a = { 1, 2, 3 };
+            int? result = server.sum(a);
+            Assert.AreEqual(6, result);
+        }
+
+        [Test]
+        public void TestDistance()
+        {
+            Point a = new Point(2, 3);
+            Point b = new Point(4, 5);
+            Point result = server.dist(a, b);
+            Assert.AreEqual(2, result.x);
+            Assert.AreEqual(2, result.y);
+        }
+
+
+        [TearDown]
+        public void CloseConnection()
+        {
+            if (server != null)
+            {
+                server._Stop();
+            }
+        }
+
+        [TestFixtureTearDown]
+        public void StopListener()
+        {
+            if (listener != null)
+            {
+                listener.TransportControl(TransportConsts.STOP_AND_WAIT_DOWN, 4000);
+                listener = null;
+            }
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/examples/perf/src/test/java/org/apache/etch/examples/perf/TestPerfServer.java b/examples/perf/src/test/java/org/apache/etch/examples/perf/TestPerfServer.java
new file mode 100644
index 0000000..49ccb9f
--- /dev/null
+++ b/examples/perf/src/test/java/org/apache/etch/examples/perf/TestPerfServer.java
@@ -0,0 +1,167 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.examples.perf;
+
+import java.util.Date;
+
+import junit.framework.Assert;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.examples.perf.Perf.Point;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.core.io.Transport;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+/** */
+public class TestPerfServer
+{
+
+	/** transport */
+	public static ServerFactory listener;
+	
+	RemotePerfServer server;
+
+	/**
+	 * @throws Exception
+	 */
+	@BeforeClass
+	public static void startListener() throws Exception
+	{
+		Log.addSink(null);
+		Log.report("StartExampleListener");
+			
+		String uri = "tcp://localhost:4009";
+		MainPerfListener implFactory = new MainPerfListener();
+		listener = PerfHelper.newListener( uri, null, implFactory );
+
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+	
+		Log.report( "StartExampleListener",
+				"status", "up",
+				"listener", listener );
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	@AfterClass
+	public static void stopListener() throws Exception
+	{
+		if (listener != null)
+		{
+			listener.transportControl( Transport.STOP_AND_WAIT_DOWN, 4000 );
+			listener = null;
+		}
+	}
+	
+	/**
+	 * Connect client to serve
+	 * @throws Exception
+	 */
+	@Before
+	public void makeConnection()
+		throws Exception
+	{
+		String uri = "tcp://localhost:4009";
+
+		server = PerfHelper.newServer( uri, null, new MainPerfClient() );
+
+		server._startAndWaitUp( 4000 );
+	}
+
+	/**
+	 * Shutdown connection to server
+	 * @throws Exception
+	 */
+	@After
+	public void shutConnection()
+		throws Exception
+	{
+		if (server != null)
+		{
+			server._stop();
+		}
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test
+	public void checkConnection() throws Exception
+	{
+		Assert.assertNotNull(server);
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test
+	public void testAdd() throws Exception
+	{
+		int result = server.add( 3, 5 );
+		Assert.assertEquals( 8, result);
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test
+	public void testAdd2() throws Exception
+	{
+		Date d = new Date();
+		long ms = 1000;
+		Date retDate = server.add2( d, ms );
+		Assert.assertEquals( new Date(d.getTime() + ms), retDate );
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test
+	public void testSum() throws Exception
+	{
+		int[] a = {1,2,3};
+		int result = server.sum( a );
+		Assert.assertEquals( 6, result );
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test
+	public void testDistance() throws Exception
+	{
+		Point a = new Point(2,3);
+		Point b = new Point(4,5);
+		Point result = server.dist( a, b );
+		Assert.assertEquals( 2, result.getX().intValue() );
+		Assert.assertEquals( 2, result.getY().intValue() );
+		
+	}
+	
+
+
+}
diff --git a/installers/build.xml b/installers/build.xml
new file mode 100644
index 0000000..b903810
--- /dev/null
+++ b/installers/build.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="installers" basedir="." default="help">
+    <description>Installers, .zip and .tar.gz packages</description>
+    <property name="Etch.basedir" location="${basedir}/.." />
+    <import file="${Etch.basedir}/build-support/etch.includes.xml" />
+
+    <!-- Static properties of the sub-project -->
+    <property name="proj"                 location="${Etch.basedir}/installers" />
+    <property name="target"               location="${proj}/target" />
+    <property name="packageName"          value="${Etch.longname}" />
+
+    <!-- INIT TARGET -->
+    <!-- Modify this target to define project specific properties that can only be set at runtime -->
+    <target name="do-init">
+        <delete dir="${target}" failonerror="false" quiet="true" />
+        <mkdir dir="${Etch.dist}" />
+        <mkdir dir="${target}" />
+    </target>
+
+    <!-- CLEAN TARGET -->
+    <target name="do-clean">
+        <delete dir="${target}" />
+    </target>
+
+    <!-- BUILD TARGET -->
+
+    <target name="do-txts">
+        <copy file="${Etch.basedir}/LICENSE.txt" todir="${Etch.dist}" />
+        <copy file="${Etch.basedir}/ChangeLog.txt" todir="${Etch.dist}" />
+        <copy file="${Etch.basedir}/README.txt" tofile="${Etch.dist}/README.txt" />
+        <copy file="${Etch.basedir}/RELEASE_NOTES.txt" tofile="${Etch.dist}/RELEASE_NOTES.txt" />
+        <copy file="${Etch.basedir}/NOTICE.txt" tofile="${Etch.dist}/NOTICE.txt" />
+        <copy file="${proj}/etch-maven-install.bat" todir="${Etch.dist}/maven" >
+            <filterset refid="Etch.buildTokens" />
+        </copy>
+    </target>
+
+    <target name="do-zips" >
+        <!-- create zipped binary distribution -->
+        <zip destfile="${target}/${packageName}.zip" >
+            <zipfileset dir="${Etch.dist}" prefix="${packageName}/" >
+                <exclude name="bin/etch" />
+            </zipfileset>
+            <zipfileset dir="${Etch.dist}" prefix="${packageName}/" filemode="755" >
+                <include name="bin/etch" />
+            </zipfileset>                
+        </zip>
+
+        <!-- create tar-gzip binary distribution -->
+        <tar destfile="${target}/${packageName}.tar.gz" compression="gzip" >
+            <tarfileset dir="${Etch.dist}" prefix="${packageName}/">
+                <exclude name="bin/etch" />
+            </tarfileset>
+            <tarfileset dir="${Etch.dist}" prefix="${packageName}/" filemode="755" >
+                <include name="bin/etch" />
+            </tarfileset>
+        </tar>
+    </target>
+
+    <target name="do-nsis" if="NSIS.enabled" >
+        <makensis destfile="${target}/${packageName}-setup.exe" root="${Etch.basedir}" dir="installers" script="etch-full-installer" />        
+    </target>
+
+    <target name="do-build" depends="do-txts,do-nsis,do-zips" />
+
+    <!-- TEST TARGET -->
+    <target name="do-test">
+		<available property="build.tests.fail" file="${Etch.runtime.tests.fail}"/>
+    </target>
+
+    <!-- POSTBUILD TARGET -->
+    <target name="do-postbuild">
+        <mkdir dir="${Etch.basedir}/target/Installers" />
+        <copy todir="${Etch.basedir}/target/Installers/packages" >
+            <fileset dir="${target}">
+                <include name="**/*.zip" />
+                <include name="**/*.exe" />
+                <include name="**/*.tar.gz" />
+            </fileset>
+        </copy>
+    </target>
+
+    <target name="do-publish" if="build.tests.fail">
+        <!-- Set flag file if any tests failed -->
+        <touch file="${Etch.runtime.tests.fail}"/>
+    </target>
+
+</project>
diff --git a/installers/etch-full-installer.nsi b/installers/etch-full-installer.nsi
new file mode 100644
index 0000000..69d875c
--- /dev/null
+++ b/installers/etch-full-installer.nsi
@@ -0,0 +1,213 @@
+# Licensed to the Apache Software Foundation (ASF) under one   *
+# or more contributor license agreements.  See the NOTICE file *
+# distributed with this work for additional information        *
+# regarding copyright ownership.  The ASF licenses this file   *
+# to you under the Apache License, Version 2.0 (the            *
+# "License"); you may not use this file except in compliance   *
+# with the License.  You may obtain a copy of the License at   *
+#                                                              *
+#   http://www.apache.org/licenses/LICENSE-2.0                 *
+#                                                              *
+# Unless required by applicable law or agreed to in writing,   *
+# software distributed under the License is distributed on an  *
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+# KIND, either express or implied.  See the License for the    *
+# specific language governing permissions and limitations      *
+# under the License.                                           *
+!define PRODUCT_NAME "Apache Etch"
+!ifndef PRODUCT_VERSION
+    !define PRODUCT_VERSION "1.0"
+!endif
+!define PRODUCT_PUBLISHER "Apache Software Foundation"
+!define PRODUCT_WEB_SITE "http://incubator.apache.org/projects/etch.html"
+!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}-${PRODUCT_VERSION}"
+!define PRODUCT_UNINST_ROOT_KEY "HKLM"
+!ifndef ROOT_DIRECTORY
+    !define ROOT_DIRECTORY "..\target\Installers\dist"
+!endif
+!ifndef OUT_FILE
+    !define OUT_FILE "apache-etch-${PRODUCT_VERSION}-win32-setup.exe"
+!endif
+
+!include WinMessages.nsh
+
+Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
+OutFile "${OUT_FILE}"
+LoadLanguageFile "${NSISDIR}\Contrib\Language files\English.nlf"
+InstallDir "$PROGRAMFILES\${PRODUCT_PUBLISHER}\apache-etch-${PRODUCT_VERSION}"
+Icon "${NSISDIR}\Contrib\Graphics\Icons\pixel-install.ico"
+UninstallIcon "${NSISDIR}\Contrib\Graphics\Icons\pixel-uninstall.ico"
+DirText "Setup will install $(^Name) in the following folder.$\r$\n$\r$\nTo install in a different folder, click Browse and select another folder."
+LicenseText "If you accept all the terms of the agreement, choose I Agree to continue. You must accept the agreement to install $(^Name)."
+LicenseData "${ROOT_DIRECTORY}\LICENSE.txt"
+#BrandingText "${PRODUCT_PUBLISHER}"
+XPStyle on
+ShowInstDetails show
+ShowUnInstDetails show
+#SetCompressor /SOLID zlib
+LicenseBkColor ffffff
+InstallColors 000000 ffffff
+
+# Usage:
+# Push "Substring"
+# Push "Body"
+# Call StrContains
+# Pop 0/1
+Function contains
+  Exch $R1 ; Substring
+  Exch 1
+  Exch $R2 ; Body
+  Push $R0 ; return value
+  Exch 2
+  Exch 1
+  Push $R3 ; Length of Substring
+  Push $R4 ; Length of Body
+  Push $R5 ; i
+  Push $R6 ; temp
+
+  StrCpy $R0 ""
+  StrLen $R3 $R1
+  StrLen $R4 $R2
+  StrCpy $R5 -1
+  loop:
+    IntOp $R5 $R5 + 1 ; ++i
+    StrCpy $R6 $R2 $R3 $R5 ; temp = Body[i.. i + length of Substring]
+    StrCmp $R6 $R1 found ; if temp = Substring -> found
+    StrCmp $R5 $R4 done ; if i = length of body -> done
+    GoTo loop
+  found:
+    StrCpy $R0 $R1
+  done:
+  Pop $R6
+  Pop $R5
+  Pop $R4
+  Pop $R3
+  Pop $R2
+  Pop $R1
+  Exch $R0
+FunctionEnd
+
+Section "CheckSection" SEC01
+  ReadRegStr $R0 ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString"
+  StrCmp $R0 "" +4 0 # Check if Etch is installed
+    MessageBox MB_ICONINFORMATION|MB_OKCANCEL "${PRODUCT_NAME}-${PRODUCT_VERSION} is already installed. Do you wish to re-install?" /SD IDOK IDOK +3 IDCANCEL 0
+      MessageBox MB_ICONINFORMATION|MB_OK "${PRODUCT_NAME} was not installed." /SD IDOK
+      Quit
+SectionEnd
+
+Section "MainSection"
+  SetOutPath $INSTDIR
+  SetOverwrite try
+  File /r "${ROOT_DIRECTORY}\*"
+  WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "ETCH_HOME" "$INSTDIR"
+  ReadRegStr $R0 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "Path"
+  StrCpy $R1 "%ETCH_HOME%\bin"
+  Push $R0
+  Push $R1
+  Call Contains
+  Pop $R2
+  StrCmp $R2 "" 0 +2
+  WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "Path" "$R0;%ETCH_HOME%\bin"
+  # This tells windows to refresh the environment variables
+  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
+SectionEnd
+
+Section -AdditionalIcons
+  SetOutPath $INSTDIR
+#  WriteIniStr "$INSTDIR\etch-homepage.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
+  CreateDirectory "$SMPROGRAMS\$(^Name)"
+#  CreateShortCut "$SMPROGRAMS\$(^Name)\Apache Etch Homepage.lnk" "$INSTDIR\etch-homepage.url"
+  CreateShortCut "$SMPROGRAMS\$(^Name)\Uninstall Apache Etch.lnk" "$INSTDIR\uninst.exe"
+SectionEnd
+
+Section -Post
+  WriteUninstaller "$INSTDIR\uninst.exe"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
+SectionEnd
+
+
+Function un.onUninstSuccess
+  HideWindow
+  MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) was successfully removed from your computer." /SD IDOK
+FunctionEnd
+
+Function un.onInit
+  MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove $(^Name) and all of its components?" /SD IDOK IDYES +2
+  Abort
+FunctionEnd
+
+# Usage:
+# Push "String to cut"
+# Push "Body text"
+# Call Slice
+# Pop $R0 ; "New String"
+# Pop $R1 ; Cut done? 0/1
+Function un.slice
+  Exch $R0 ; input string
+  Exch
+  Exch $R1 ; to cut
+  Push $R2
+  Push $R3
+  Push $R4
+  Push $R5
+
+  StrLen $R3 $R1
+  StrCpy $R4 -1
+  StrCpy $R5 0
+
+  Loop:
+
+    IntOp $R4 $R4 + 1
+    StrCpy $R2 $R0 $R3 $R4
+    StrCmp $R2 "" Done
+    StrCmp $R2 $R1 0 Loop
+
+    StrCpy $R5 1
+
+    StrCmp $R4 0 0 +3
+    StrCpy $R1 ""
+    Goto +2
+    StrCpy $R1 $R0 $R4
+    StrLen $R2 $R0
+    IntOp $R4 $R2 - $R4
+    IntOp $R4 $R4 - $R3
+    IntCmp $R4 0 0 0 +3
+    StrCpy $R2 ""
+    Goto +2
+    StrCpy $R2 $R0 "" -$R4
+    StrCpy $R0 $R1$R2
+
+  Done:
+  StrCpy $R1 $R5
+
+  Pop $R5
+  Pop $R4
+  Pop $R3
+  Pop $R2
+  Exch $R1 ; slice? 0/1
+  Exch
+  Exch $R0 ; output string
+FunctionEnd
+
+Section Uninstall
+  SetOutPath "$PROGRAMFILES\${PRODUCT_PUBLISHER}"
+  RMDir /r $INSTDIR
+  RMDir /r "$SMPROGRAMS\$(^Name)"
+  DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
+  DeleteRegValue HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "ETCH_HOME"
+  # Replace Path with de-Etch'ed path
+  ReadRegStr $R0 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "Path"
+  StrCpy $R1 ";%ETCH_HOME%\bin"
+  Push $R1
+  Push $R0
+  Call un.slice
+  Pop $R0
+  WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "Path" "$R0"
+  # This tells windows to refresh the environment variables
+  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
+  SetAutoClose true
+SectionEnd
diff --git a/installers/etch-maven-install.bat b/installers/etch-maven-install.bat
new file mode 100644
index 0000000..710ec8b
--- /dev/null
+++ b/installers/etch-maven-install.bat
@@ -0,0 +1,49 @@
+@rem  Licensed to the Apache Software Foundation (ASF) under one   *
+@rem  or more contributor license agreements.  See the NOTICE file *
+@rem  distributed with this work for additional information        *
+@rem  regarding copyright ownership.  The ASF licenses this file   *
+@rem  to you under the Apache License, Version 2.0 (the            *
+@rem  "License"); you may not use this file except in compliance   *
+@rem  with the License.  You may obtain a copy of the License at   *
+@rem                                                               *
+@rem    http://www.apache.org/licenses/LICENSE-2.0                 *
+@rem                                                               *
+@rem  Unless required by applicable law or agreed to in writing,   *
+@rem  software distributed under the License is distributed on an  *
+@rem  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+@rem  KIND, either express or implied.  See the License for the    *
+@rem  specific language governing permissions and limitations      *
+@rem  under the License.                                           *
+@echo off
+
+rem This .bat file installs the etch-java-runtime jar file to the local maven
+rem repository. It assumes either M2_HOME or MAVEN_HOME is set in the
+rem environment to match the maven installation, or "mvn" command is in the
+rem search path.
+
+setlocal
+
+rem Define the etch home directory and artifact particulars
+
+set ETCH_HOME=%~dp0..
+set GROUP=etch.etch
+set ARTIFACTS=etch-ant-plugin, etch-compiler, etch-csharp-compiler, etch-java-compiler, etch-java-runtime, etch-xml-compiler
+set VERSION=@EtchVersion@
+
+if "%M2_HOME%" == "" goto try_maven_home
+set MVN=%M2_HOME%\bin\mvn.bat
+if not exist "%MVN%" goto try_maven_home
+goto run_mvn
+
+:try_maven_home
+if "%MAVEN_HOME%" == "" goto try_path
+set MVN=%MAVEN_HOME%\bin\mvn.bat
+if not exist "%MVN%" goto try_path
+goto run_mvn
+
+:try_path
+set MVN=mvn.bat
+
+:run_mvn
+FOR %%A IN (%ARTIFACTS%) DO CALL "%MVN%" install:install-file "-Dfile=%ETCH_HOME%\lib\%%A-%VERSION%.jar" -DgroupId=%GROUP% -DartifactId=%%A -Dversion=%VERSION% -Dpackaging=jar
+FOR %%A IN (%ARTIFACTS%) DO CALL "%MVN%" install:install-file "-Dfile=%ETCH_HOME%\lib\%%A-%VERSION%-src.zip" -DgroupId=%GROUP% -DartifactId=%%A -Dversion=%VERSION% -Dpackaging=jar -Dclassifier=sources
diff --git a/interoptester/example/interoptest1.xml b/interoptester/example/interoptest1.xml
new file mode 100644
index 0000000..79be5b9
--- /dev/null
+++ b/interoptester/example/interoptest1.xml
@@ -0,0 +1,191 @@
+<interoptest>
+	<run test="java-java">
+		<arg name="suri" value="tcp://127.0.0.1:4001"/>
+		<arg name="curi" value="tcp://127.0.0.1:4001"/>
+	</run>
+	
+	<run test="java-java">
+		<arg name="suri" value="tcp://127.0.0.1:4002?filter=KeepAlive"/>
+		<arg name="curi" value="tcp://127.0.0.1:4002?filter=KeepAlive"/>
+	</run>
+	
+	<run test="java-java">
+		<arg name="suri" value="tls://127.0.0.1:4003"/>
+		<arg name="svmarg1" value="-Djavax.net.ssl.keyStore=interoptester/example/keys/my.keystore"/>
+		<arg name="svmarg2" value="-Djavax.net.ssl.keyStorePassword=snort1"/>
+		<arg name="curi" value="tls://127.0.0.1:4003?TlsConnection.authReqd=false"/>
+	</run>
+	
+	<run test="java-csharp">
+		<arg name="suri" value="tcp://127.0.0.1:4001"/>
+		<arg name="curi" value="tcp://127.0.0.1:4001"/>
+	</run>
+	
+	<run test="csharp-java">
+		<arg name="suri" value="tcp://127.0.0.1:4001"/>
+		<arg name="curi" value="tcp://127.0.0.1:4001"/>
+	</run>
+	
+	<run test="csharp-csharp">
+		<arg name="suri" value="tcp://127.0.0.1:4001"/>
+		<arg name="curi" value="tcp://127.0.0.1:4001"/>
+	</run>
+	
+	<tests>
+		<test name="java-java">
+			<params>
+				<param name="suri" default=""/>
+				<param name="svmarg1" default=""/>
+				<param name="svmarg2" default=""/>
+				<param name="curi" default=""/>
+				<param name="cvmarg1" default=""/>
+				<param name="cvmarg2" default=""/>
+			</params>
+			<support>
+				<prog name="java_MainIOTListener">
+					<arg name="uri" value="{suri}"/>
+					<arg name="vmarg1" value="{svmarg1}"/>
+					<arg name="vmarg2" value="{svmarg2}"/>
+				</prog>
+			</support>
+			<jig>
+				<prog name="java_MainIOTClient">
+					<arg name="uri" value="{curi}"/>
+					<arg name="vmarg1" value="{cvmarg1}"/>
+					<arg name="vmarg2" value="{cvmarg2}"/>
+				</prog>
+			</jig>
+		</test>
+		
+		<test name="java-csharp">
+			<params>
+				<param name="suri" default=""/>
+				<param name="svmarg1" default=""/>
+				<param name="svmarg2" default=""/>
+				<param name="curi" default=""/>
+				<param name="cvmarg1" default=""/>
+				<param name="cvmarg2" default=""/>
+			</params>
+			<support>
+				<prog name="csharp_MainIOTListener">
+					<arg name="uri" value="{suri}"/>
+				</prog>
+			</support>
+			<jig>
+				<prog name="java_MainIOTClient">
+					<arg name="uri" value="{curi}"/>
+					<arg name="vmarg1" value="{cvmarg1}"/>
+					<arg name="vmarg2" value="{cvmarg2}"/>
+				</prog>
+			</jig>
+		</test>
+		
+		<test name="csharp-java">
+			<params>
+				<param name="suri" default=""/>
+				<param name="svmarg1" default=""/>
+				<param name="svmarg2" default=""/>
+				<param name="curi" default=""/>
+				<param name="cvmarg1" default=""/>
+				<param name="cvmarg2" default=""/>
+			</params>
+			<support>
+				<prog name="java_MainIOTListener">
+					<arg name="uri" value="{suri}"/>
+					<arg name="vmarg1" value="{svmarg1}"/>
+					<arg name="vmarg2" value="{svmarg2}"/>
+				</prog>
+			</support>
+			<jig>
+				<prog name="csharp_MainIOTClient">
+					<arg name="uri" value="{curi}"/>
+				</prog>
+			</jig>
+		</test>
+		
+		<test name="csharp-csharp">
+			<params>
+				<param name="suri" default=""/>
+				<param name="svmarg1" default=""/>
+				<param name="svmarg2" default=""/>
+				<param name="curi" default=""/>
+				<param name="cvmarg1" default=""/>
+				<param name="cvmarg2" default=""/>
+			</params>
+			<support>
+				<prog name="csharp_MainIOTListener">
+					<arg name="uri" value="{suri}"/>
+				</prog>
+			</support>
+			<jig>
+				<prog name="csharp_MainIOTClient">
+					<arg name="uri" value="{curi}"/>
+				</prog>
+			</jig>
+		</test>
+	</tests>
+	
+	<programs>
+		<program name="java_MainIOTListener">
+			<params>
+				<param name="uri" default=""/>
+				<param name="vmarg1" default=""/>
+				<param name="vmarg2" default=""/>
+			</params>
+			<stdouttag>SOUT</stdouttag>
+			<stderrtag>SERR</stderrtag>
+			<tokens>
+				<token>java</token>
+				<token>{vmarg1}</token>
+				<token>{vmarg2}</token>
+				<token>-cp</token>
+				<token>bin;../etch/bin</token>
+				<token>org.apache.etch.interoptester.example.iot.MainIOTListener</token>
+				<token>{uri}</token>
+			</tokens>
+		</program>
+		
+		<program name="java_MainIOTClient">
+			<params>
+				<param name="uri" default=""/>
+				<param name="vmarg1" default=""/>
+				<param name="vmarg2" default=""/>
+			</params>
+			<stdouttag>COUT</stdouttag>
+			<stderrtag>CERR</stderrtag>
+			<tokens>
+				<token>java</token>
+				<token>{vmarg1}</token>
+				<token>{vmarg2}</token>
+				<token>-cp</token>
+				<token>bin;../etch/bin;../../wks/tools/junit/4.3.1/junit-4.3.1.jar</token>
+				<token>org.apache.etch.interoptester.example.iot.MainIOTClient</token>
+				<token>{uri}</token>
+			</tokens>
+		</program>
+		
+		<program name="csharp_MainIOTListener">
+			<params>
+				<param name="uri" default=""/>
+			</params>
+			<stdouttag>SOUT</stdouttag>
+			<stderrtag>SERR</stderrtag>
+			<tokens>
+				<token>interoptester/example/src/main/csharp/IOTListenerProj/bin/Debug/IOTListenerProj.exe</token>
+				<token>{uri}</token>
+			</tokens>
+		</program>
+		
+		<program name="csharp_MainIOTClient">
+			<params>
+				<param name="uri" default=""/>
+			</params>
+			<stdouttag>COUT</stdouttag>
+			<stderrtag>CERR</stderrtag>
+			<tokens>
+				<token>interoptester/example/src/main/csharp/IOTClientProj/bin/Debug/IOTClientProj.exe</token>
+				<token>{uri}</token>
+			</tokens>
+		</program>
+	</programs>
+</interoptest>
diff --git a/interoptester/example/keys/my.keystore b/interoptester/example/keys/my.keystore
new file mode 100644
index 0000000..aed873e
--- /dev/null
+++ b/interoptester/example/keys/my.keystore
Binary files differ
diff --git a/interoptester/example/src/main/csharp/IOTClientProj/IOTClientProj.csproj b/interoptester/example/src/main/csharp/IOTClientProj/IOTClientProj.csproj
new file mode 100644
index 0000000..06b093a
--- /dev/null
+++ b/interoptester/example/src/main/csharp/IOTClientProj/IOTClientProj.csproj
@@ -0,0 +1,97 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{14D7A923-0CB4-442A-9499-7F0C25C239EE}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>IOTClientProj</RootNamespace>
+    <AssemblyName>IOTClientProj</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\BaseIOTClient.cs">
+      <Link>BaseIOTClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\BaseIOTServer.cs">
+      <Link>BaseIOTServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\IOT.cs">
+      <Link>IOT.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\IOTClient.cs">
+      <Link>IOTClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\IOTHelper.cs">
+      <Link>IOTHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\IOTServer.cs">
+      <Link>IOTServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\RemoteIOT.cs">
+      <Link>RemoteIOT.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\RemoteIOTClient.cs">
+      <Link>RemoteIOTClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\RemoteIOTServer.cs">
+      <Link>RemoteIOTServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\StubIOT.cs">
+      <Link>StubIOT.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\StubIOTClient.cs">
+      <Link>StubIOTClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\StubIOTServer.cs">
+      <Link>StubIOTServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\ValueFactoryIOT.cs">
+      <Link>ValueFactoryIOT.cs</Link>
+    </Compile>
+    <Compile Include="..\ImplIOTClient.cs">
+      <Link>ImplIOTClient.cs</Link>
+    </Compile>
+    <Compile Include="..\MainIOTClient.cs">
+      <Link>MainIOTClient.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\..\..\binding-csharp\runtime\src\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/interoptester/example/src/main/csharp/IOTClientProj/Properties/AssemblyInfo.cs b/interoptester/example/src/main/csharp/IOTClientProj/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f7197ee
--- /dev/null
+++ b/interoptester/example/src/main/csharp/IOTClientProj/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("IOTClientProj")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("comer family")]
+[assembly: AssemblyProduct("IOTClientProj")]
+[assembly: AssemblyCopyright("Copyright © comer family 2009")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c2299770-fc6d-4f6b-b515-6d3885ec0d9f")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/interoptester/example/src/main/csharp/IOTListenerProj/IOTListenerProj.csproj b/interoptester/example/src/main/csharp/IOTListenerProj/IOTListenerProj.csproj
new file mode 100644
index 0000000..2ad4fb2
--- /dev/null
+++ b/interoptester/example/src/main/csharp/IOTListenerProj/IOTListenerProj.csproj
@@ -0,0 +1,97 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{5EED552A-09C1-42D0-9E0A-7822B0EC3603}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>IOTListenerProj</RootNamespace>
+    <AssemblyName>IOTListenerProj</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\BaseIOTClient.cs">
+      <Link>BaseIOTClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\BaseIOTServer.cs">
+      <Link>BaseIOTServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\IOT.cs">
+      <Link>IOT.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\IOTClient.cs">
+      <Link>IOTClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\IOTHelper.cs">
+      <Link>IOTHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\IOTServer.cs">
+      <Link>IOTServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\RemoteIOT.cs">
+      <Link>RemoteIOT.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\RemoteIOTClient.cs">
+      <Link>RemoteIOTClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\RemoteIOTServer.cs">
+      <Link>RemoteIOTServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\StubIOT.cs">
+      <Link>StubIOT.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\StubIOTClient.cs">
+      <Link>StubIOTClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\StubIOTServer.cs">
+      <Link>StubIOTServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.interoptester.example.iot\ValueFactoryIOT.cs">
+      <Link>ValueFactoryIOT.cs</Link>
+    </Compile>
+    <Compile Include="..\ImplIOTServer.cs">
+      <Link>ImplIOTServer.cs</Link>
+    </Compile>
+    <Compile Include="..\MainIOTListener.cs">
+      <Link>MainIOTListener.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\..\..\binding-csharp\runtime\src\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/interoptester/example/src/main/csharp/IOTListenerProj/Properties/AssemblyInfo.cs b/interoptester/example/src/main/csharp/IOTListenerProj/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ff21cef
--- /dev/null
+++ b/interoptester/example/src/main/csharp/IOTListenerProj/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("IOTListenerProj")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("comer family")]
+[assembly: AssemblyProduct("IOTListenerProj")]
+[assembly: AssemblyCopyright("Copyright © comer family 2009")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("832cd217-01fe-4f47-afc3-4835aa52ebb6")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/interoptester/example/src/main/csharp/ImplIOTClient.cs b/interoptester/example/src/main/csharp/ImplIOTClient.cs
new file mode 100644
index 0000000..61aa3bb
--- /dev/null
+++ b/interoptester/example/src/main/csharp/ImplIOTClient.cs
@@ -0,0 +1,36 @@
+// This file automatically generated by:
+//   Apache Etch 1.1.0-incubating (LOCAL-0) / csharp 1.1.0-incubating (LOCAL-0)
+//   Mon Feb 16 11:13:50 CST 2009
+// This file is automatically created for your convenience and will not be
+// overwritten once it exists! Please edit this file as necessary to implement
+// your service logic.
+
+using System;
+
+
+
+using org.apache.etch.interoptester.example.iot.types.IOT;
+
+///<summary>Your custom implementation of BaseIOTClient. Add methods here to provide
+///implementation of messages from the server. </summary>
+namespace org.apache.etch.interoptester.example.iot
+{
+	///<summary>Implementation for ImplIOTClient</summary>
+	public class ImplIOTClient : BaseIOTClient
+	{
+		/// <summary>Constructs the ImplIOTClient.</summary>
+ 		/// <param name="server">a connection to the server session. Use this to
+ 		/// send a message to the server.</param>
+		public ImplIOTClient(RemoteIOTServer server)
+		{
+			this.server = server;
+		}
+		
+		/// <summary>A connection to the server session. Use this to
+ 		/// send a message to the server.</summary>
+		private readonly RemoteIOTServer server;
+	
+		// TODO: Implement delegates or provide implementation of IOTClient
+		// messages from the server	
+	}
+}
\ No newline at end of file
diff --git a/interoptester/example/src/main/csharp/ImplIOTServer.cs b/interoptester/example/src/main/csharp/ImplIOTServer.cs
new file mode 100644
index 0000000..fa2805c
--- /dev/null
+++ b/interoptester/example/src/main/csharp/ImplIOTServer.cs
@@ -0,0 +1,42 @@
+// This file automatically generated by:
+//   Apache Etch 1.1.0-incubating (LOCAL-0) / csharp 1.1.0-incubating (LOCAL-0)
+//   Mon Feb 16 11:13:50 CST 2009
+// This file is automatically created for your convenience and will not be
+// overwritten once it exists! Please edit this file as necessary to implement
+// your service logic.
+
+using System;
+
+
+
+using org.apache.etch.interoptester.example.iot.types.IOT;
+
+///<summary>Your custom implementation of BaseIOTServer. Add methods here to provide
+///implementation of messages from the client. </summary>
+namespace org.apache.etch.interoptester.example.iot
+{
+	///<summary>Implementation for ImplIOTServer</summary>
+	public class ImplIOTServer : BaseIOTServer
+	{
+		/// <summary>Constructs the ImplIOTServer.</summary>
+ 		/// <param name="client">a connection to the client session. Use this to
+ 		/// send a message to the client.</param>
+		public ImplIOTServer(RemoteIOTClient client)
+		{
+			this.client = client;
+		}
+		
+		/// <summary>A connection to the client session. Use this to
+ 		/// send a message to the client.</summary>
+		private readonly RemoteIOTClient client;
+
+        public override int? add(int? x, int? y)
+        {
+            if (x == null)
+                throw new ArgumentNullException("x");
+            if (y == null)
+                throw new ArgumentNullException("y");
+            return x + y;
+        }
+	}
+}
\ No newline at end of file
diff --git a/interoptester/example/src/main/csharp/MainIOTClient.cs b/interoptester/example/src/main/csharp/MainIOTClient.cs
new file mode 100644
index 0000000..f28e267
--- /dev/null
+++ b/interoptester/example/src/main/csharp/MainIOTClient.cs
@@ -0,0 +1,78 @@
+// This file automatically generated by:
+//   Apache Etch 1.1.0-incubating (LOCAL-0) / csharp 1.1.0-incubating (LOCAL-0)
+//   Mon Feb 16 11:13:50 CST 2009
+// This file is automatically created for your convenience and will not be
+// overwritten once it exists! Please edit this file as necessary to implement
+// your service logic.
+
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace org.apache.etch.interoptester.example.iot
+{
+	///<summary>Main implementation for IOTClient.</summary>
+	public class MainIOTClient : IOTHelper.IOTClientFactory
+	{
+		///<summary>Main for IOTClient</summary>
+		///<param name="args">Command Line Arguments</param>
+		public static void Main(String[] args)
+        {
+            if (args.Length > 1)
+            {
+                Console.WriteLine("usage: MainIOTClient [uri]");
+                return;
+            }
+		
+			string uri = args.Length > 0 ? args[0] : "tcp://localhost:4001";
+			
+			RemoteIOTServer server = IOTHelper.NewServer( uri, null, new MainIOTClient());
+		
+			// Connect to the service
+			server._StartAndWaitUp( 4000 );
+
+            Assertion.Check(server.add(2, 3) == 5, "server.add(2, 3) == 5");
+
+            try
+            {
+                server.add(null, 3);
+                Assertion.Check(false, "false");
+            }
+            catch
+            {
+                // ignore.
+            }
+
+            try
+            {
+                server.add(2, null);
+                Assertion.Check(false, "false");
+            }
+            catch
+            {
+                // ignore.
+            }
+
+            try
+            {
+                server.add(null, null);
+                Assertion.Check(false, "false");
+            }
+            catch
+            {
+                // ignore.
+            }
+
+			// Disconnect from the service
+			server._StopAndWaitDown( 4000 );
+            Console.WriteLine("done");
+		}
+
+		///<summary>Return a new instance of IOTClient.</summary>
+		///<param name="server">Reference to remote service</param>
+		///<returns>Client Implementation</returns>
+		public IOTClient NewIOTClient( RemoteIOTServer server )
+		{
+			return new ImplIOTClient( server );
+		}
+	}
+}
\ No newline at end of file
diff --git a/interoptester/example/src/main/csharp/MainIOTListener.cs b/interoptester/example/src/main/csharp/MainIOTListener.cs
new file mode 100644
index 0000000..ab6a878
--- /dev/null
+++ b/interoptester/example/src/main/csharp/MainIOTListener.cs
@@ -0,0 +1,47 @@
+// This file automatically generated by:
+//   Apache Etch 1.1.0-incubating (LOCAL-0) / csharp 1.1.0-incubating (LOCAL-0)
+//   Mon Feb 16 11:13:50 CST 2009
+// This file is automatically created for your convenience and will not be
+// overwritten once it exists! Please edit this file as necessary to implement
+// your service logic.
+
+using System;
+
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+using org.apache.etch.interoptester.example.iot.types.IOT;
+
+namespace org.apache.etch.interoptester.example.iot
+{
+	///<summary>Main implementation for IOTListener.</summary>
+	public class MainIOTListener : IOTHelper.IOTServerFactory
+	{
+ 		///<summary>Main for IOTListener.</summary>
+		///<param name="args">Command Line Arguments</param>
+		public static void Main(String[] args)
+        {
+            if (args.Length > 1)
+            {
+                Console.WriteLine("usage: MainIOTListener [uri]");
+                return;
+            }
+		
+            string uri = args.Length > 0 ? args[0] : "tcp://localhost:4001";
+			
+			ServerFactory listener = IOTHelper.NewListener( uri, null, new MainIOTListener());
+			
+			// Start the Listener
+			listener.TransportControl( TransportConsts.START_AND_WAIT_UP, 4000 );
+            Console.WriteLine( "listener started: "+listener );
+		}
+
+		///<summary>Return a new instance of IOTServer.</summary>
+		///<param name="client">Reference to remote service</param>
+		///<returns>Server Implementation</returns>
+		public IOTServer NewIOTServer( RemoteIOTClient client )
+		{
+			return new ImplIOTServer( client );
+		}
+	}
+}
\ No newline at end of file
diff --git a/interoptester/example/src/main/etch/IOT.etch b/interoptester/example/src/main/etch/IOT.etch
new file mode 100644
index 0000000..9947f5f
--- /dev/null
+++ b/interoptester/example/src/main/etch/IOT.etch
@@ -0,0 +1,13 @@
+module org.apache.etch.interoptester.example.iot
+
+/** Simple example for the interoptester. */
+service IOT
+{
+	/**
+	 * Adds two numbers.
+	 * @param x the first number to add.
+	 * @param y the second number to add.
+	 * @return the sum of x and y.
+	 */
+	int add( int x, int y )
+}
diff --git a/interoptester/example/src/main/java/org/apache/etch/interoptester/example/iot/ImplIOTClient.java b/interoptester/example/src/main/java/org/apache/etch/interoptester/example/iot/ImplIOTClient.java
new file mode 100644
index 0000000..2bef94a
--- /dev/null
+++ b/interoptester/example/src/main/java/org/apache/etch/interoptester/example/iot/ImplIOTClient.java
@@ -0,0 +1,52 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester.example.iot;
+
+import org.apache.etch.interoptester.example.iot.BaseIOTClient;
+import org.apache.etch.interoptester.example.iot.RemoteIOTServer;
+
+/**
+ * Your custom implementation of BaseIOTClient. Add methods here to provide
+ * implementations of messages from the server.
+ */
+public class ImplIOTClient extends BaseIOTClient
+{
+	/**
+	 * Constructs the ImplIOTClient.
+	 *
+	 * @param server a connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	public ImplIOTClient( RemoteIOTServer server )
+	{
+		this.server = server;
+	}
+	
+	/**
+	 * A connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	@SuppressWarnings( "unused" )
+	private final RemoteIOTServer server;
+
+	// TODO insert methods here to provide implementations of IOTClient
+	// messages from the server.
+}
\ No newline at end of file
diff --git a/interoptester/example/src/main/java/org/apache/etch/interoptester/example/iot/ImplIOTServer.java b/interoptester/example/src/main/java/org/apache/etch/interoptester/example/iot/ImplIOTServer.java
new file mode 100644
index 0000000..df3bd43
--- /dev/null
+++ b/interoptester/example/src/main/java/org/apache/etch/interoptester/example/iot/ImplIOTServer.java
@@ -0,0 +1,65 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester.example.iot;
+
+import org.apache.etch.interoptester.example.iot.BaseIOTServer;
+import org.apache.etch.interoptester.example.iot.RemoteIOTClient;
+
+/**
+ * Your custom implementation of BaseIOTServer. Add methods here to provide
+ * implementations of messages from the client.
+ */
+public class ImplIOTServer extends BaseIOTServer
+{
+	/**
+	 * Constructs the ImplIOTServer.
+	 *
+	 * @param client a connection to the client session. Use this to send a
+	 * message to the client.
+	 */
+	public ImplIOTServer( RemoteIOTClient client )
+	{
+		this.client = client;
+	}
+	
+	/**
+	 * A connection to the client session. Use this to send a
+	 * message to the client.
+	 */
+	@SuppressWarnings( "unused" )
+	private final RemoteIOTClient client;
+
+	@Override
+	public Integer add( Integer x, Integer y )
+	{
+		if (x == null)
+			throw new IllegalArgumentException( "x == null" );
+		if (y == null)
+			throw new IllegalArgumentException( "y == null" );
+		return x + y;
+	}
+	
+	@Override
+	public void _sessionNotify( Object event ) throws Exception
+	{
+		// ignore events.
+	}
+}
\ No newline at end of file
diff --git a/interoptester/example/src/main/java/org/apache/etch/interoptester/example/iot/MainIOTClient.java b/interoptester/example/src/main/java/org/apache/etch/interoptester/example/iot/MainIOTClient.java
new file mode 100644
index 0000000..98794d9
--- /dev/null
+++ b/interoptester/example/src/main/java/org/apache/etch/interoptester/example/iot/MainIOTClient.java
@@ -0,0 +1,187 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester.example.iot;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.etch.bindings.java.support._Etch_RuntimeException;
+import org.apache.etch.interoptester.example.iot.IOTClient;
+import org.apache.etch.interoptester.example.iot.IOTHelper;
+import org.apache.etch.interoptester.example.iot.RemoteIOTServer;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+
+/**
+ * Main program for IOTClient. This program makes a connection to the
+ * listener created by MainIOTListener.
+ */
+public class MainIOTClient implements IOTHelper.IOTClientFactory
+{
+	/**
+	 * Main program for IOTClient.
+	 * 
+	 * @param args command line arguments.
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		System.out.println( "MainIOTClient: starting" );
+		
+		if (args.length > 1)
+		{
+			System.err.println( "usage: MainIOTClient [uri]" );
+			System.exit( 1 );
+		}
+		
+		if (args.length > 0)
+			uri = args[0];
+		
+		dontStartListener = true;
+		
+		JUnitCore c = new org.junit.runner.JUnitCore();
+		
+		c.addListener( new RunListener()
+		{
+			@Override
+			public void testRunStarted( Description description )
+				throws Exception
+			{
+				System.out.println( "testRunStarted "+description );
+			}
+			
+			@Override
+			public void testStarted( Description description ) throws Exception
+			{
+				System.out.print( "test "+description );
+			}
+			
+			@Override
+			public void testFailure( Failure failure ) throws Exception
+			{
+				System.out.println( "[failed:  "+failure+"]" );
+			}
+			
+			@Override
+			public void testIgnored( Description description ) throws Exception
+			{
+				System.out.println( " [ignored]" );
+			}
+			
+			@Override
+			public void testFinished( Description description )
+				throws Exception
+			{
+				System.out.println( " [ok]" );
+			}
+			
+			@Override
+			public void testRunFinished( Result result ) throws Exception
+			{
+				System.out.println( "testRunFinished" );
+			}
+		} );
+		
+		Result r = c.run( MainIOTClient.class );
+		
+		if (!r.wasSuccessful())
+		{
+			System.err.printf( "MainIOTClient: tests failed (%d/%d/%d)",
+				r.getRunCount(), r.getIgnoreCount(), r.getFailureCount() );
+			System.err.println();
+			System.exit( 1 );
+		}
+		
+		System.out.printf( "MainIOTClient: tests succeeeded (%d/%d)",
+			r.getRunCount(), r.getIgnoreCount() );
+		System.out.println();
+		System.exit( 0 );
+	}
+	
+	private static boolean dontStartListener;
+	
+	private static String uri = "tcp://localhost:4001";
+	
+	/** @throws Exception */
+	@BeforeClass
+	public static void beforeClass() throws Exception
+	{
+		if (!dontStartListener)
+			MainIOTListener.main( new String[] {} );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Before
+	public void before() throws Exception
+	{
+		server = IOTHelper.newServer( uri, null, this );
+		server._startAndWaitUp( 4000 );
+	}
+	
+	private RemoteIOTServer server;
+	
+	/** @throws Exception */
+	@org.junit.After
+	public void after() throws Exception
+	{
+		server._stopAndWaitDown( 4000 );
+		server = null;
+	}
+
+	public IOTClient newIOTClient( RemoteIOTServer server )
+		throws Exception
+	{
+		return new ImplIOTClient( server );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = _Etch_RuntimeException.class )
+	public void add_null_null() throws Exception
+	{
+		server.add( null, null );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = _Etch_RuntimeException.class )
+	public void add_null_2() throws Exception
+	{
+		server.add( null, 2 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = _Etch_RuntimeException.class )
+	public void add_1_null() throws Exception
+	{
+		server.add( 1, null );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void add_1_2() throws Exception
+	{
+		assertEquals( 3, server.add( 1, 2 ) );
+	}
+}
diff --git a/interoptester/example/src/main/java/org/apache/etch/interoptester/example/iot/MainIOTListener.java b/interoptester/example/src/main/java/org/apache/etch/interoptester/example/iot/MainIOTListener.java
new file mode 100644
index 0000000..b441831
--- /dev/null
+++ b/interoptester/example/src/main/java/org/apache/etch/interoptester/example/iot/MainIOTListener.java
@@ -0,0 +1,66 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester.example.iot;
+
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.interoptester.example.iot.IOTHelper;
+import org.apache.etch.interoptester.example.iot.IOTServer;
+import org.apache.etch.interoptester.example.iot.RemoteIOTClient;
+import org.apache.etch.util.core.io.Transport;
+
+
+/**
+ * Main program for IOTServer. This program makes a listener to accept
+ * connections from MainIOTClient.
+ */
+public class MainIOTListener implements IOTHelper.IOTServerFactory
+{
+	/**
+	 * Main program for IOTServer.
+	 * 
+	 * @param args command line arguments.
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		if (args.length > 1)
+		{
+			System.err.println( "usage: MainIOTClient [uri]" );
+			System.exit( 1 );
+		}
+		
+		String uri = args.length > 0 ? args[0] : "tcp://localhost:4001";
+		
+		ServerFactory listener = IOTHelper.newListener( uri, null,
+			new MainIOTListener() );
+
+		// Start the Listener
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+		
+		System.out.println( "listener started: "+listener );
+	}
+
+	public IOTServer newIOTServer( RemoteIOTClient client )
+	{
+		return new ImplIOTServer( client );
+	}
+}
diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/Arg.java b/interoptester/src/main/java/org/apache/etch/interoptester/Arg.java
new file mode 100644
index 0000000..3029be6
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/Arg.java
@@ -0,0 +1,113 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.util.Assertion;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+
+
+/**
+ * Arg models an named value passed to a procedure (which is used to initialize
+ * a Param once received).
+ */
+public class Arg
+{
+	/**
+	 * @param r
+	 * @return the Arg that was parsed.
+	 */
+	public static Arg parse( TagElement r )
+	{
+		Assertion.check( r.matches( null, "arg" ), "tag is arg" );
+		
+		String name = r.getAttr( null, "name" );
+		if (name == null || name.length() == 0)
+			throw new IllegalArgumentException( "arg tag has no name" );
+		
+		String value = r.getAttr( null, "value" );
+		if (value == null && r.countChildren() > 0)
+			value = r.getCdataValue();
+		
+		if (value == null)
+			throw new IllegalArgumentException( "arg '"+name+"' has no value" );
+		
+		return new Arg( name, value );
+	}
+
+	private Arg( String name, String value )
+	{
+		this.name = name;
+		this.value = value;
+	}
+	
+	private final String name;
+	
+	private final String value;
+
+	/**
+	 * @return the name of this arg.
+	 */
+	public String name()
+	{
+		return name;
+	}
+	
+	/**
+	 * @param args named values which might be used as substitutions.
+	 * @return the value of this arg. This might involve substituting named
+	 * values from args.
+	 */
+	public String value( Map<String, String> args )
+	{
+		if (value == null)
+			return null;
+		
+		return Substitutor.subst( value, args );
+	}
+	
+	@Override
+	public String toString()
+	{
+		return String.format( "Arg( %s, %s )", name, value );
+	}
+
+	/**
+	 * @param who
+	 * @param args
+	 * @param substs
+	 * @return the map formed by processing substitutions from substs into each
+	 * value from args.
+	 */
+	public static Map<String, String> processSubst( String who,
+		Map<String, Arg> args, Map<String, String> substs )
+	{
+		Map<String, String> nargs = new HashMap<String, String>();
+		for (Arg a: args.values())
+		{
+			String v = a.value( substs );
+			nargs.put( a.name(), v );
+		}
+		return nargs;
+	}
+}
\ No newline at end of file
diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/ChildWalker.java b/interoptester/src/main/java/org/apache/etch/interoptester/ChildWalker.java
new file mode 100644
index 0000000..129fff5
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/ChildWalker.java
@@ -0,0 +1,79 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.Iterator;
+
+import org.apache.etch.util.core.xml.XmlParser.CdataElement;
+import org.apache.etch.util.core.xml.XmlParser.Element;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+
+
+/**
+ * ChildWalker calls a method with each child element under a given tag
+ * element.
+ */
+abstract public class ChildWalker
+{
+	/**
+	 * Iterates over the children of r and calls tag or cdata for each.
+	 * @param r
+	 */
+	public void walk( TagElement r )
+	{
+		for (Iterator<Element> i = r.getChildren(); i.hasNext();)
+		{
+			Element e = i.next();
+			if (!(e instanceof TagElement))
+			{
+				if (!cdata( (CdataElement) e ))
+					throw new IllegalArgumentException(
+						"tag "+r.getQName()+": cdata not allowed here: '"+e+"'" );
+				
+				continue;
+			}
+			
+			TagElement te = (TagElement) e;
+			if (!tag( te ))
+				throw new IllegalArgumentException(
+					"tag "+r.getQName()+": tag "+te.getQName()+" not allowed here" );
+		}
+	}
+
+	/**
+	 * @param te
+	 * @return if tag is allowed.
+	 */
+	public boolean tag( TagElement te )
+	{
+		return false;
+	}
+	
+	/**
+	 * @param e
+	 * @return true if cdata is allowed.
+	 */
+	public boolean cdata( CdataElement e )
+	{
+		String s = e.getCdata();
+		return s.trim().length() == 0;
+	}
+}
\ No newline at end of file
diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/DefaultRunningProg.java b/interoptester/src/main/java/org/apache/etch/interoptester/DefaultRunningProg.java
new file mode 100644
index 0000000..db47990
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/DefaultRunningProg.java
@@ -0,0 +1,165 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.etch.interoptester.Program.ProcessStreamReader;
+
+/**
+ * Default implementation of {@link RunningProg}.
+ */
+public class DefaultRunningProg implements RunningProg
+{
+	/**
+	 * @param tkns
+	 * @param nvs
+	 * @param stdoutTag
+	 * @param stderrTag
+	 */
+	public DefaultRunningProg( List<String> tkns, Map<String, String> nvs,
+		String stdoutTag, String stderrTag )
+	{
+		this.tkns = tkns;
+		this.nvs = nvs;
+		this.stdoutTag = stdoutTag;
+		this.stderrTag = stderrTag;
+	}
+
+	private final List<String> tkns;
+
+	private final Map<String, String> nvs;
+
+	private final String stdoutTag;
+
+	private final String stderrTag;
+
+	private ProcessBuilder pb;
+
+	private Process p;
+
+	private ProcessStreamReader outrdr;
+
+	private ProcessStreamReader errrdr;
+
+	private Integer sts;
+
+	@Override
+	public String toString()
+	{
+		return "DefaultRunningProg@" + Integer.toHexString( hashCode() );
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	public void start() throws Exception
+	{
+		pb = new ProcessBuilder( tkns );
+		pb.environment().putAll( nvs );
+		
+		h = new Thread( new Runnable()
+		{
+			public void run()
+			{
+				try
+				{
+					stop();
+				}
+				catch ( InterruptedException e )
+				{
+					// ignore
+				}
+			}
+		} );
+		
+		Runtime.getRuntime().addShutdownHook( h );
+
+		report( "start, tokens = " + tkns + ", nvs = " + nvs );
+
+		p = pb.start();
+
+		report( "started" );
+
+		p.getOutputStream().close();
+
+		outrdr = new ProcessStreamReader( p.getInputStream(), System.out,
+			stdoutTag );
+		outrdr.start();
+
+		errrdr = new ProcessStreamReader( p.getErrorStream(), System.out,
+			stderrTag );
+		errrdr.start();
+	}
+	
+	private Thread h;
+
+	public Integer join() throws InterruptedException
+	{
+		if (p != null)
+		{
+			report( "join" );
+
+			sts = p.waitFor();
+			p = null;
+			
+			try
+			{
+				Runtime.getRuntime().removeShutdownHook( h );
+			}
+			catch ( IllegalStateException e )
+			{
+				// ignore
+			}
+			h = null;
+
+			report( "join, sts = " + sts );
+
+			if (outrdr != null)
+				outrdr.join();
+
+			if (errrdr != null)
+				errrdr.join();
+
+			return sts;
+		}
+
+		report( "join: no program" );
+		return null;
+	}
+
+	public Integer stop() throws InterruptedException
+	{
+		report( "stop" );
+
+		if (p != null)
+			p.destroy();
+
+		return join();
+	}
+
+	private void report( String msg )
+	{
+		//System.out.println( this.toString() + ": " + msg );
+	}
+}
diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/Env.java b/interoptester/src/main/java/org/apache/etch/interoptester/Env.java
new file mode 100644
index 0000000..13ed45e
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/Env.java
@@ -0,0 +1,83 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.Map;
+
+import org.apache.etch.util.Assertion;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+
+
+/**
+ * Env models a contribution to the environment of a running program.
+ */
+public class Env
+{
+	/**
+	 * @param r
+	 * @return the Env that was parsed.
+	 */
+	public static Env parse( TagElement r )
+	{
+		Assertion.check( r.matches( null, "env" ), "tag is env" );
+		
+		String name = r.getAttr( null, "name" );
+		if (name == null || name.length() == 0)
+			throw new IllegalArgumentException( "env tag has no name" );
+		
+		String value = r.getAttr( null, "value" );
+		if (value == null && r.hasChildren())
+			value = r.getCdataValue();
+		
+		return new Env( name, value );
+	}
+	
+	private Env( String name, String value )
+	{
+		this.name = name;
+		this.value = value;
+	}
+	
+	private final String name;
+
+	/**
+	 * @return the name of this environment variable.
+	 */
+	public String name()
+	{
+		return name;
+	}
+	
+	private final String value;
+	
+	/**
+	 * @param args named values which might be used as substitutions.
+	 * @return the value of this env. This might involve substituting named
+	 * values from args.
+	 */
+	public String value( Map<String, String> args )
+	{
+		if (value == null)
+			return null;
+		
+		return Substitutor.subst( value, args );
+	}
+}
diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/InteropTest.java b/interoptester/src/main/java/org/apache/etch/interoptester/InteropTest.java
new file mode 100644
index 0000000..d36638c
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/InteropTest.java
@@ -0,0 +1,197 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+
+
+/** */
+public class InteropTest implements InteropTestIntf
+{
+	static InteropTestIntf parse( TagElement r )
+	{
+		if (!r.matches( null, "interoptest" ))
+			return null;
+		
+		InteropTest it = new InteropTest();
+		it.parseBody( r );
+		return it;
+	}
+	
+	/**
+	 * @param r
+	 */
+	public void parseBody( TagElement r )
+	{
+		new ChildWalker()
+		{
+			public boolean tag( TagElement te )
+			{
+				if (te.matches( null, "params" ))
+				{
+					parseParams( te );
+					return true;
+				}
+				
+				if (te.matches( null, "programs" ))
+				{
+					parsePrograms( te );
+					return true;
+				}
+				
+				if (te.matches( null, "tests" ))
+				{
+					parseTests( te );
+					return true;
+				}
+				
+				if (te.matches( null, "run" ))
+				{
+					parseRun( te );
+					return true;
+				}
+				
+				return false;
+			}
+		}.walk( r );
+	}
+	
+	private void parseParams( TagElement r )
+	{
+		new ChildWalker()
+		{
+			public boolean tag( TagElement te )
+			{
+				if (te.matches( null, "param" ))
+				{
+					parseParam( te );
+					return true;
+				}
+				
+				return false;
+			}
+		}.walk( r );
+	}
+	
+	private void parsePrograms( TagElement r )
+	{
+		new ChildWalker()
+		{
+			public boolean tag( TagElement te )
+			{
+				if (te.matches( null, "program" ))
+				{
+					parseProgram( te );
+					return true;
+				}
+				
+				return false;
+			}
+		}.walk( r );
+	}
+
+	private void parseTests( TagElement r )
+	{
+		new ChildWalker()
+		{
+			public boolean tag( TagElement te )
+			{
+				if (te.matches( null, "test" ))
+				{
+					parseTest( te );
+					return true;
+				}
+				
+				return false;
+			}
+		}.walk( r );
+	}
+	
+	private void parseParam( TagElement r )
+	{
+		Param p = Param.parse( r );
+		params.put( p.name(), p );
+	}
+	
+	private final Map<String, Param> params = new HashMap<String, Param>();
+
+	private void parseProgram( TagElement r )
+	{
+		Program p = Program.parse( this, r );
+		programs.put( p.name(), p );
+	}
+	
+	private final Map<String, Program> programs = new HashMap<String, Program>();
+
+	private void parseTest( TagElement r )
+	{
+		Test t = Test.parse( this, r );
+		tests.put( t.name(), t );
+	}
+	
+	final Map<String, Test> tests = new HashMap<String, Test>();
+
+	private void parseRun( TagElement r )
+	{
+		runs.add( Run.parse( this, r ) );
+	}
+	
+	private final List<Run> runs = new ArrayList<Run>();
+
+	public void run( Map<String, String> overrides ) throws Exception
+	{
+		//System.out.println( "InteropTest.run: overrides = "+overrides );
+		
+		// construct substs out of params + overrides
+		
+		Map<String, String> substs = Param.processOverrides( "interoptest",
+			params, overrides );
+		
+		//System.out.println( "InteropTest.run: substs = "+substs );
+		
+		// run each "run" defined in interoptest
+		
+		for (Run r: runs)
+			r.run( substs );
+	}
+
+	public TestIntf getTest( String test )
+	{
+		return tests.get( test );
+	}
+
+	public Program getProgram( String name )
+	{
+		return programs.get( name );
+	}
+
+	public int nextRunId()
+	{
+		return ++runId;
+	}
+	
+	private int runId;
+}
\ No newline at end of file
diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/InteropTestIntf.java b/interoptester/src/main/java/org/apache/etch/interoptester/InteropTestIntf.java
new file mode 100644
index 0000000..38c3644
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/InteropTestIntf.java
@@ -0,0 +1,55 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.Map;
+
+/**
+ * Interface to a suite of tests to be run.
+ */
+public interface InteropTestIntf
+{
+	/**
+	 * @param test the name of the test to get.
+	 * @return the interface to the test.
+	 */
+	public TestIntf getTest( String test );
+
+	/**
+	 * @param name
+	 * @return the named Program.
+	 */
+	public Program getProgram( String name );
+	
+	/**
+	 * Runs all the tests in the suite.
+	 * 
+	 * @param overrides replacement values for interoptest params. any params
+	 * which have no default must be specified.
+	 * @throws Exception 
+	 */
+	public void run( Map<String, String> overrides ) throws Exception;
+
+	/**
+	 * @return the next id of a run in this interoptest.
+	 */
+	public int nextRunId();
+}
diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/MainInteropTester.java b/interoptester/src/main/java/org/apache/etch/interoptester/MainInteropTester.java
new file mode 100644
index 0000000..63dd677
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/MainInteropTester.java
@@ -0,0 +1,94 @@
+/* $Id: InteropTester.java 2575 2009-01-29 16:53:50Z sccomer $

+ *

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements. See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership. The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License. You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied. See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+

+package org.apache.etch.interoptester;

+

+import java.io.File;

+import java.io.IOException;

+import java.util.HashMap;

+import java.util.Map;

+

+import org.apache.etch.util.ArrayIterator;

+import org.apache.etch.util.StringUtil;

+import org.apache.etch.util.cmd.StringArrayIterator;

+import org.apache.etch.util.core.xml.XmlParser;

+import org.apache.etch.util.core.xml.XmlParser.TagElement;

+

+

+/** */

+@SuppressWarnings( "all" )

+public class MainInteropTester

+{

+	/**

+	 * @param args

+	 * @throws Exception

+	 */

+	public static void main( String[] args ) throws Exception

+	{

+		if (args.length < 1)

+		{

+			System.err.println( "usage: InteropTester file [name=value ...]" );

+			System.exit( 1 );

+		}

+

+		StringArrayIterator i = new StringArrayIterator( args );

+

+		TagElement te = new XmlParser().parseOne( new File( i.next() ), null,

+			"interoptest" );

+		// System.out.println( te );

+		InteropTestIntf itest = InteropTest.parse( te );

+		te = null;

+

+		Map<String, String> overrides = new HashMap<String, String>();

+		while (i.hasNext())

+		{

+			String s = i.next();

+			String[] x = StringUtil.leftSplit( s, '=' );

+			if (x == null)

+				throw new IllegalArgumentException(

+					"malformed 'name=value' token on command line" );

+			overrides.put( x[0], x[1] );

+		}

+

+		//System.out.println( "main: overrides = " + overrides );

+

+		new Thread( new Runnable()

+		{

+			public void run()

+			{

+				try

+				{

+					int c = System.in.read();

+					if (c == 'q')

+						System.exit( 1 );

+				}

+				catch ( IOException e )

+				{

+					// ignore

+				}

+			}

+		} ).start();

+

+		itest.run( overrides );

+

+		System.out.println( "main: done" );

+		System.exit( 0 );

+	}

+}

diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/Param.java b/interoptester/src/main/java/org/apache/etch/interoptester/Param.java
new file mode 100644
index 0000000..770c16e
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/Param.java
@@ -0,0 +1,127 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.util.Assertion;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+
+
+/**
+ * Param models a named value initialized from args supplied to a function and
+ * perhaps given a default value. A Param may be used when calling another
+ * function by substitution into an Arg or Token.
+ */
+public class Param
+{
+	/**
+	 * @param r
+	 * @return the parsed Param.
+	 */
+	public static Param parse( TagElement r )
+	{
+		Assertion.check( r.matches( null, "param" ), "tag is param" );
+		
+		String name = r.getAttr( null, "name" );
+		if (name == null || name.length() == 0)
+			throw new IllegalArgumentException( "param tag has no name attribute" );
+		
+		Param p = new Param( name );
+		p.parseBody( r );
+		return p;
+	}
+
+	private Param( String name )
+	{
+		this.name = name;
+	}
+
+	private final String name;
+
+	/**
+	 * @return the name of this param.
+	 */
+	public String name()
+	{
+		return name;
+	}
+
+	private void parseBody( TagElement r )
+	{
+		deflt = r.getAttr( null, "default" );
+		if (deflt == null && r.countChildren() > 0)
+			deflt = r.getCdataValue();
+	}
+	
+	private String deflt;
+
+	/**
+	 * @param args
+	 * @return the value of the named param in args, or the default value if not
+	 * in args.
+	 */
+	public String value( Map<String, String> args )
+	{
+		String v = args.get( name );
+		if (v != null)
+			return v;
+		return deflt;
+	}
+	
+	@Override
+	public String toString()
+	{
+		return String.format( "Param( %s, %s )", name, deflt );
+	}
+
+	/**
+	 * @param who the tag name of the owner of params.
+	 * @param params a map of params (from param tags).
+	 * @param overrides name / value pairs which override default param values.
+	 * @return a map of name / value pairs which are the param values after
+	 * overrides have been applied.
+	 */
+	public static Map<String, String> processOverrides( String who,
+		Map<String, Param> params, Map<String, String> overrides )
+	{
+		// ensure names in overrides appear in params
+		
+		for (String name: overrides.keySet())
+			if (!params.containsKey( name ))
+				throw new IllegalArgumentException(
+					who+" param '"+name+"' is not defined, cannot override" );
+		
+		// construct args out of params + overrides
+		
+		Map<String, String> args = new HashMap<String, String>();
+		for (Param p : params.values())
+		{
+			String v = p.value( overrides );
+			if (v == null)
+				throw new IllegalArgumentException(
+					who+" param '"+p.name()+"' has no value, must override" );
+			args.put( p.name(), v );
+		}
+		return args;
+	}
+}
\ No newline at end of file
diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/Prog.java b/interoptester/src/main/java/org/apache/etch/interoptester/Prog.java
new file mode 100644
index 0000000..d0cb50a
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/Prog.java
@@ -0,0 +1,150 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.util.Assertion;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+
+
+/**
+ * Prog models a reference to a Program in a Test.
+ */
+public class Prog
+	{
+		/**
+		 * @param test
+		 * @param r
+		 * @return the parsed Prog.
+		 */
+		public static Prog parse( TestIntf test, TagElement r )
+		{
+			Assertion.check( r.matches( null, "prog" ), "tag is prog" );
+			
+			String name = r.getAttr( null, "name" );
+			if (name == null || name.length() == 0)
+				throw new IllegalArgumentException( "prog tag has no name attribute" );
+			
+			Prog p = new Prog( test, name );
+			p.parseBody( r );
+			return p;
+		}
+		
+		private Prog( TestIntf test, String name )
+		{
+			this.test = test;
+			this.name = name;
+		}
+
+		private final TestIntf test;
+		
+		private final String name;
+
+		/**
+		 * @return the enclosing Test
+		 */
+		public TestIntf test()
+		{
+			return test;
+		}
+
+		/**
+		 * @return the name of the Program to run.
+		 */
+		public String name()
+		{
+			return name;
+		}
+		
+		private void parseBody( TagElement r )
+		{
+			new ChildWalker()
+			{
+				public boolean tag( TagElement te )
+				{
+					if (te.matches( null, "arg" ))
+					{
+						Arg a = Arg.parse( te );
+						if (args.containsKey( a.name() ))
+							throw new IllegalArgumentException( "duplicate name arg "+a.name() );
+						args.put( a.name(), a );
+						return true;
+					}
+					
+					return false;
+				}
+			}.walk( r );
+		}
+		
+		private final Map<String, Arg> args = new HashMap<String, Arg>();
+
+		/**
+		 * @return the args to be passed to this prog.
+		 */
+		public Map<String, Arg> args()
+		{
+			return args;
+		}
+
+		/**
+		 * @param substs
+		 * @return a running instance of Prog.
+		 * @throws Exception 
+		 */
+		public RunningProg start( Map<String, String> substs ) throws Exception
+		{
+			Map<String, String> overrides = processSubst( "start", substs );
+			return getProgram().start( overrides );
+		}
+
+		/**
+		 * @param substs
+		 * @throws Exception 
+		 */
+		public void run( Map<String, String> substs ) throws Exception
+		{
+			Map<String, String> overrides = processSubst( "run", substs );
+			getProgram().run( overrides );
+		}
+
+		private Map<String, String> processSubst( String who,
+			Map<String, String> substs )
+		{
+			//System.out.println( "Prog."+who+": name "+name+", substs = "+substs );
+			
+			Map<String, String> overrides = Arg.processSubst( "prog", args,
+				substs );
+			
+			//System.out.println( "Prog."+who+": name "+name+", overrides = "+overrides );
+			
+			return overrides;
+		}
+
+		private Program getProgram()
+		{
+			Program p = test.getProgram( name );
+			if (p == null)
+				throw new IllegalArgumentException( "no such program "+name );
+			return p;
+		}
+	}
\ No newline at end of file
diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/Program.java b/interoptester/src/main/java/org/apache/etch/interoptester/Program.java
new file mode 100644
index 0000000..4721494
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/Program.java
@@ -0,0 +1,430 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.etch.util.Assertion;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+
+
+/**
+ * Program models a program to be run as part of a test. The program has
+ * positional parameters, environment, stdin, stdout, stderr, and timeout.
+ */
+public class Program
+{
+	/**
+	 * @param itest
+	 * @param r
+	 * @return the parsed Program.
+	 */
+	public static Program parse( InteropTestIntf itest, TagElement r )
+	{
+		Assertion.check( r.matches( null, "program" ), "tag is program" );
+		
+		String name = r.getAttr( null, "name" );
+		if (name == null || name.length() == 0)
+			throw new IllegalArgumentException( "program tag has no name" );
+		
+		Program p = new Program( itest, name );
+		p.parseBody( r );
+		return p;
+	}
+	
+	/**
+	 * @param itest
+	 * @param name
+	 */
+	private Program( InteropTestIntf itest, String name )
+	{
+		this.itest = itest;
+		this.name = name;
+	}
+
+	private final InteropTestIntf itest;
+
+	private final String name;
+	
+	/**
+	 * @return the containing InteropTestIntf.
+	 */
+	public InteropTestIntf itest()
+	{
+		return itest;
+	}
+	
+	/**
+	 * @return the name of this Program.
+	 */
+	public String name()
+	{
+		return name;
+	}
+	
+	/**
+	 * @param r
+	 */
+	public void parseBody( TagElement r )
+	{
+		new ChildWalker()
+		{
+			public boolean tag( TagElement te )
+			{
+				if (te.matches( null, "params" ))
+				{
+					parseParams( te );
+					return true;
+				}
+				
+				if (te.matches( null, "tokens" ))
+				{
+					parseTokens( te );
+					return true;
+				}
+				
+				if (te.matches( null, "environment" ))
+				{
+					parseEnvironment( te );
+					return true;
+				}
+				
+				if (te.matches( null, "stdin" ))
+				{
+					parseStdin( te );
+					return true;
+				}
+				
+				if (te.matches( null, "stdout" ))
+				{
+					parseStdout( te );
+					return true;
+				}
+				
+				if (te.matches( null, "stderr" ))
+				{
+					parseStderr( te );
+					return true;
+				}
+				
+				if (te.matches( null, "stdouttag" ))
+				{
+					parseStdoutTag( te );
+					return true;
+				}
+				
+				if (te.matches( null, "stderrtag" ))
+				{
+					parseStderrTag( te );
+					return true;
+				}
+				
+				if (te.matches( null, "timeout" ))
+				{
+					parseTimeout( te );
+					return true;
+				}
+				
+				return false;
+			}
+		}.walk( r );
+	}
+
+	private void parseParams( TagElement r )
+	{
+		new ChildWalker()
+		{
+			public boolean tag( TagElement te )
+			{
+				if (te.matches( null, "param" ))
+				{
+					parseParam( te );
+					return true;
+				}
+
+				return false;
+			}
+		}.walk( r );
+	}
+
+	private void parseParam( TagElement te )
+	{
+		Param p = Param.parse( te );
+		params.put( p.name(), p );
+	}
+	
+	private final Map<String, Param> params = new HashMap<String, Param>();
+
+	private void parseTokens( TagElement r )
+	{
+		new ChildWalker()
+		{
+			public boolean tag( TagElement te )
+			{
+				if (te.matches( null, "token" ))
+				{
+					parseToken( te );
+					return true;
+				}
+
+				return false;
+			}
+		}.walk( r );
+	}
+
+	private void parseToken( TagElement r )
+	{
+		tokens.add( Token.parse( r ) );
+	}
+	
+	private final List<Token> tokens = new ArrayList<Token>();
+
+	private void parseEnvironment( TagElement r )
+	{
+		new ChildWalker()
+		{
+			public boolean tag( TagElement te )
+			{
+				if (te.matches( null, "env" ))
+				{
+					parseEnv( te );
+					return true;
+				}
+
+				return false;
+			}
+		}.walk( r );
+	}
+
+	private void parseEnv( TagElement r )
+	{
+		Env e = Env.parse( r );
+		envs.put( e.name(), e );
+	}
+	
+	private final Map<String, Env> envs = new HashMap<String, Env>();
+
+	private void parseStdin( TagElement r )
+	{
+		// TODO Auto-generated method stub
+		throw new UnsupportedOperationException( "parseStdin" );
+	}
+
+	private void parseStdout( TagElement r )
+	{
+		// TODO Auto-generated method stub
+		throw new UnsupportedOperationException( "parseStdout" );
+	}
+
+	private void parseStderr( TagElement r )
+	{
+		// TODO Auto-generated method stub
+		throw new UnsupportedOperationException( "parseStderr" );
+	}
+	
+	private void parseStdoutTag( TagElement r )
+	{
+		stdoutTag = r.getCdataValue();
+	}
+	
+	private String stdoutTag = "out";
+	
+	private void parseStderrTag( TagElement r )
+	{
+		stderrTag = r.getCdataValue();
+	}
+	
+	private String stderrTag = "err";
+
+	private void parseTimeout( TagElement r )
+	{
+		// TODO Auto-generated method stub
+		throw new UnsupportedOperationException( "parseTimeout" );
+	}
+
+	/**
+	 * @param overrides
+	 * @return a RunningProg which allows the running program to be controlled.
+	 * @throws Exception 
+	 */
+	public RunningProg start( Map<String, String> overrides ) throws Exception
+	{
+		Map<String, String> substs = processOverrides( "start", overrides );
+		List<String> tkns = processTokens( substs );
+		Map<String, String> nvs = processEnvs( substs );
+		//System.out.printf( "Program.start: tokens %s envs %s\n", tkns, nvs );
+		DefaultRunningProg rp = new DefaultRunningProg( tkns, nvs, stdoutTag, stderrTag );
+		try
+		{
+			rp.start();
+			return rp;
+		}
+		catch ( Exception e )
+		{
+			e.printStackTrace();
+			try
+			{
+				rp.stop();
+			}
+			catch ( InterruptedException e1 )
+			{
+				e1.printStackTrace();
+			}
+			throw new Exception( "process did not start" );
+		}
+	}
+
+	/**
+	 * @param overrides
+	 * @throws Exception 
+	 */
+	public void run( Map<String, String> overrides ) throws Exception
+	{
+		Map<String, String> substs = processOverrides( "run", overrides );
+		List<String> tkns = processTokens( substs );
+		Map<String, String> nvs = processEnvs( substs );
+		//System.out.printf( "Program.run: tokens %s envs %s\n", tkns, nvs );
+		
+		DefaultRunningProg rp = new DefaultRunningProg( tkns, nvs, stdoutTag, stderrTag );
+		try
+		{
+			rp.start();
+		}
+		catch ( Exception e )
+		{
+			e.printStackTrace();
+			try
+			{
+				rp.stop();
+			}
+			catch ( InterruptedException e1 )
+			{
+				e1.printStackTrace();
+			}
+			throw new Exception( "process did not start" );
+		}
+		
+		try
+		{
+			Integer sts = rp.join();
+			if (sts == null || sts != 0)
+				throw new Exception( "process died with bad status: "+sts );
+		}
+		catch ( InterruptedException e )
+		{
+			e.printStackTrace();
+		}
+	}
+
+	private Map<String, String> processOverrides( String who,
+		Map<String, String> overrides )
+	{
+		//System.out.println( "Program."+who+": name "+name+", overrides = "+overrides );
+		
+		Map<String, String> substs = Param.processOverrides( "program", params,
+			overrides );
+		
+		//System.out.println( "Program."+who+": name "+name+", substs = "+substs );
+		
+		return substs;
+	}
+
+	private List<String> processTokens( Map<String, String> substs )
+	{
+		List<String> ntokens = new ArrayList<String>();
+		for (Token t: tokens)
+			ntokens.add( t.value( substs ) );
+		return ntokens;
+	}
+
+	private Map<String, String> processEnvs( Map<String, String> substs )
+	{
+		Map<String, String> nenvs = new HashMap<String, String>();
+		for (Env e: envs.values())
+			nenvs.put( e.name(), e.value( substs ) );
+		return nenvs;
+	}
+	
+	/**
+	 * @author wert
+	 *
+	 */
+	public static class ProcessStreamReader extends Thread
+	{
+		/**
+		 * @param is input stream to read until eof.
+		 * @param tag 
+		 * @param ps 
+		 * @throws Exception 
+		 */
+		public ProcessStreamReader( InputStream is, PrintStream ps, String tag ) throws Exception
+		{
+			rdr = new BufferedReader( new InputStreamReader( is ) );
+			this.ps = ps;
+			this.tag = tag;
+		}
+		
+		private final BufferedReader rdr;
+		
+		private final PrintStream ps;
+		
+		private final String tag;
+		
+		@Override
+		public void run()
+		{
+			try
+			{
+				String s;
+				while ((s = rdr.readLine()) != null)
+				{
+					synchronized (ps)
+					{
+						ps.printf( "[%s] %s\n", tag, s );
+					}
+				}
+			}
+			catch ( Exception e )
+			{
+				e.printStackTrace();
+			}
+			finally
+			{
+				try
+				{
+					rdr.close();
+				}
+				catch ( IOException e )
+				{
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/Run.java b/interoptester/src/main/java/org/apache/etch/interoptester/Run.java
new file mode 100644
index 0000000..25185f9
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/Run.java
@@ -0,0 +1,185 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.util.Assertion;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+
+
+/**
+ * Model of a test run. Run identifies the Test to be run and the arguments
+ * (name / value pairs) which will be supplied to the Test when it is run.
+ */
+public class Run
+{
+	/**
+	 * @param itest 
+	 * @param r the xml tag which defines this Run.
+	 * @return the parsed Run object.
+	 */
+	public static Run parse( InteropTestIntf itest, TagElement r )
+	{
+		Assertion.check( r.matches( null, "run" ), "tag is run" );
+		
+		String name = r.getAttr( null, "name" );
+		if (name == null || name.length() == 0)
+			name = "run-"+itest.nextRunId();
+		
+		String test = r.getAttr( null, "test" );
+		if (test == null || test.length() == 0)
+			throw new IllegalArgumentException( "run tag has no test attribute" );
+		
+		Run t = new Run( itest, name, test );
+		t.parseBody( r );
+		return t;
+	}
+
+	/**
+	 * @param itest
+	 * @param test
+	 */
+	private Run( InteropTestIntf itest, String name, String test )
+	{
+		this.itest = itest;
+		this.name = name;
+		this.test = test;
+	}
+
+	private final InteropTestIntf itest;
+	
+	private final String name;
+	
+	private final String test;
+	
+	/**
+	 * @return the containing InteropTestIntf.
+	 */
+	public InteropTestIntf itest()
+	{
+		return itest;
+	}
+	
+	/**
+	 * @return the name of this run.
+	 */
+	public String name()
+	{
+		return name;
+	}
+
+	/**
+	 * @return the test name.
+	 */
+	public String test()
+	{
+		return test;
+	}
+	
+	@Override
+	public String toString()
+	{
+		return "Run ("+name+")";
+	}
+	
+	private void parseBody( TagElement r )
+	{
+		new ChildWalker()
+		{
+			public boolean tag( TagElement te )
+			{
+				if (te.matches( null, "arg" ))
+				{
+					Arg a = Arg.parse( te );
+					if (args.containsKey( a.name() ))
+						throw new IllegalArgumentException( "duplicate name arg "+a.name() );
+					args.put( a.name(), a );
+					return true;
+				}
+				
+				if (te.matches( null, "disable" ))
+				{
+					if (te.countChildren() > 0)
+						disable = Boolean.valueOf( te.getCdataValue() );
+					else
+						disable = true;
+					//System.out.println( "run "+name+" test "+test+", disable = "+disable );
+					return true;
+				}
+				
+				return false;
+			}
+		}.walk( r );
+	}
+	
+	private boolean disable;
+	
+	private final Map<String, Arg> args = new HashMap<String, Arg>();
+
+	/**
+	 * Runs the test specified by this Run.
+	 * @param substs params from interoptest to use for substitutions into this
+	 * Run's args. The args are then used to override the params of the Run's
+	 * test.
+	 * @throws Exception 
+	 */
+	public void run( Map<String, String> substs ) throws Exception
+	{
+		try
+		{
+			TestIntf t = itest.getTest( test );
+			if (t == null)
+				throw new IllegalArgumentException( "test "+test+" not found" );
+			
+			System.out.println( "---------------------------------------------------" );
+			
+			if (disable)
+			{
+				System.out.println( "Run.run: name "+name+" test "+test+", disabled" );
+				return;
+			}
+			
+			System.out.println( "Run.run: name "+name+" test "+test+", substs = "+substs );
+			
+			Map<String, String> overrides = Arg.processSubst( "run", args, substs );
+			
+			System.out.println( "Run.run: name "+name+" test "+test+", overrides = "+overrides );
+			
+			t.run( overrides );
+			
+			System.out.println( "Run.run: name "+name+" test "+test+", done" );
+		}
+		catch ( RuntimeException e )
+		{
+			throw new RuntimeException( "Run.run: name "+name+" test "+test+", caught exception", e );
+		}
+	}
+
+	/**
+	 * @return the map of args for this test run.
+	 */
+	public Map<String, Arg> args()
+	{
+		return args;
+	}
+}
\ No newline at end of file
diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/RunningProg.java b/interoptester/src/main/java/org/apache/etch/interoptester/RunningProg.java
new file mode 100644
index 0000000..b1aceb3
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/RunningProg.java
@@ -0,0 +1,41 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+/**
+ * RunningProg models a running program.
+ */
+public interface RunningProg
+{
+	/**
+	 * Stops the running program.
+	 * @return the status of the program. 0 means it exited normally.
+	 * @throws InterruptedException 
+	 */
+	public Integer stop() throws InterruptedException;
+	
+	/**
+	 * Waits for the running program to terminate.
+	 * @return the status of the program. 0 means it exited normally.
+	 * @throws InterruptedException 
+	 */
+	public Integer join() throws InterruptedException;
+}
\ No newline at end of file
diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/Substitutor.java b/interoptester/src/main/java/org/apache/etch/interoptester/Substitutor.java
new file mode 100644
index 0000000..70e99e1
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/Substitutor.java
@@ -0,0 +1,158 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.Map;
+
+import org.apache.etch.util.Assertion;
+import org.apache.etch.util.CharIterator;
+
+
+/**
+ * A class to perform substitutions into a string from a map,
+ * so that with input value="abc{foo}def" and map has key "foo"
+ * with value "123", the result is "abc123def".
+ */
+public class Substitutor
+{
+	private Substitutor()
+	{
+		// don't instantiate
+	}
+	
+	/**
+	 * @param value
+	 * @param map
+	 * @return value with substitutions from map
+	 */
+	public static String subst( String value, Map<String, String> map )
+	{
+		StringBuffer sb = new StringBuffer();
+		StringBuffer save = new StringBuffer();
+		CharIterator i = new CharIterator( value );
+		int state = 0;
+		while (state != 4)
+		{
+			char c;
+			int cc;
+			if (i.hasNext())
+			{
+				c = i.next();
+				cc = charClass( c );
+			}
+			else
+			{
+				c = 0;
+				cc = EOF;
+			}
+			
+			int nstate = nstates[state][cc];
+			int action = actions[state][cc];
+			
+			switch (action)
+			{
+				case 1:
+					sb.append( c );
+					break;
+				case 2:
+					// ignore
+					break;
+				case 3:
+					save.append( c );
+					break;
+				case 4:
+					sb.append( save );
+					save.setLength( 0 );
+					sb.append( c );
+					break;
+				case 5:
+					save.append( c );
+					sb.append( subst0( save.toString(), map ) );
+					save.setLength( 0 );
+					break;
+				case 6:
+					throw new IllegalArgumentException( "malformed escape" );
+				case 7:
+					sb.append( save );
+					save.setLength( 0 );
+					break;
+				default:
+					throw new IllegalArgumentException( "action "+action+" unknown" );
+			}
+			
+			state = nstate;
+		}
+		return sb.toString();
+	}
+	
+	private static Object subst0( String s, Map<String, String> map )
+	{
+		Assertion.check( s.startsWith( "{" ), "starts with {" );
+		Assertion.check( s.endsWith( "}" ), "ends with }" );
+		String n = s.substring( 1 ).substring( 0, s.length()-2 );
+		if (map.containsKey( n ))
+			return map.get( n );
+		return s;
+	}
+
+	private static int charClass( char c )
+	{
+		if (c == '\\') return BSL;
+		if (c == '{') return LBR;
+		if (c == '}') return RBR;
+		if (c >= 'a' && c <= 'z') return ALN;
+		if (c >= 'A' && c <= 'Z') return ALN;
+		if (c >= '0' && c <= '9') return ALN;
+		return OTH;
+	}
+	
+	private final static int BSL = 0;
+	
+	private final static int LBR = 1;
+	
+	private final static int RBR = 2;
+	
+	private final static int ALN = 3;
+	
+	private final static int OTH = 4;
+	
+	private final static int EOF = 5;
+	
+	private static final byte[][] nstates =
+	{
+		// first index is current state
+		// second index is char class: BSL, LBR, RBR, ALN, OTH, EOF
+		{ 1, 2, 0, 0, 0, 4 },
+		{ 0, 0, 0, 0, 0, 4 },
+		{ 0, 2, 0, 3, 0, 4 },
+		{ 0, 0, 0, 3, 0, 4 }
+	};
+	
+	private static final byte[][] actions =
+	{
+		// first index is current state
+		// second index is char class: BSL, LBR, RBR, ALN, OTH, EOF
+		{ 2, 3, 1, 1, 1, 2 },
+		{ 1, 1, 1, 1, 1, 6 },
+		{ 4, 1, 4, 3, 4, 7 },
+		{ 4, 4, 5, 3, 4, 7 }
+	};
+}
diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/Test.java b/interoptester/src/main/java/org/apache/etch/interoptester/Test.java
new file mode 100644
index 0000000..523a489
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/Test.java
@@ -0,0 +1,297 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.etch.util.Assertion;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+
+
+/**
+ * Test models a test that can be run. A Test has a name (used by a Run to
+ * specify the test), includes some parameter values and some programs to be
+ * run for setup, support, the test jig itself, and then cleanup.
+ */
+public class Test implements TestIntf
+{
+	/**
+	 * @param itest
+	 * @param r
+	 * @return the parsed Test.
+	 */
+	public static Test parse( InteropTestIntf itest, TagElement r )
+	{
+		Assertion.check( r.matches( null, "test" ), "tag is test" );
+		
+		String name = r.getAttr( null, "name" );
+		if (name == null || name.length() == 0)
+			throw new IllegalArgumentException( "test tag has no name attribute" );
+		
+		Test t = new Test( itest, name );
+		t.parseBody( r );
+		return t;
+	}
+
+	/**
+	 * @param itest
+	 * @param name
+	 */
+	private Test( InteropTestIntf itest, String name )
+	{
+		this.itest = itest;
+		this.name = name;
+	}
+	
+	private final InteropTestIntf itest;
+	
+	private final String name;
+	
+	public InteropTestIntf itest()
+	{
+		return itest;
+	}
+	
+	public String name()
+	{
+		return name;
+	}
+	
+	private void parseBody( TagElement r )
+	{
+		new ChildWalker()
+		{
+			public boolean tag( TagElement te )
+			{
+				if (te.matches( null, "params" ))
+				{
+					parseParams( te );
+					return true;
+				}
+				
+				if (te.matches( null, "setup" ))
+				{
+					parseSetup( te );
+					return true;
+				}
+				
+				if (te.matches( null, "support" ))
+				{
+					parseSupport( te );
+					return true;
+				}
+				
+				if (te.matches( null, "jig" ))
+				{
+					parseJig( te );
+					return true;
+				}
+				
+				if (te.matches( null, "cleanup" ))
+				{
+					parseCleanup( te );
+					return true;
+				}
+				
+				return false;
+			}
+		}.walk( r );
+		
+		if (jig == null)
+			throw new IllegalArgumentException( "no jig defined for test: "+name );
+	}
+	
+	private void parseParams( TagElement r )
+	{
+		new ChildWalker()
+		{
+			public boolean tag( TagElement te )
+			{
+				if (te.matches( null, "param" ))
+				{
+					parseParam( te );
+					return true;
+				}
+				
+				return false;
+			}
+		}.walk( r );
+	}
+
+	private void parseParam( TagElement r )
+	{
+		Param p = Param.parse( r );
+		params.put( p.name(), p );
+	}
+	
+	private final Map<String, Param> params = new HashMap<String, Param>();
+
+	private void parseSetup( TagElement r )
+	{
+		parseProgList( setup, r );
+	}
+	
+	private final List<Prog> setup = new ArrayList<Prog>();
+
+	private void parseSupport( TagElement r )
+	{
+		parseProgList( support, r );
+	}
+	
+	private final List<Prog> support = new ArrayList<Prog>();
+
+	private void parseJig( TagElement r )
+	{
+		List<Prog> jigs = new ArrayList<Prog>();
+		parseProgList( jigs, r );
+		if (jigs.size() != 1)
+			throw new IllegalArgumentException( "only one test jig per test" );
+		jig = jigs.get( 0 );
+	}
+	
+	private Prog jig;
+
+	private void parseCleanup( TagElement r )
+	{
+		parseProgList( cleanup, r );
+	}
+
+	private final List<Prog> cleanup = new ArrayList<Prog>();
+	
+	private void parseProgList( final List<Prog> list, TagElement r )
+	{
+		new ChildWalker()
+		{
+			public boolean tag( TagElement te )
+			{
+				if (te.matches( null, "prog" ))
+				{
+					parseProg( list, te );
+					return true;
+				}
+				
+				return false;
+			}
+		}.walk( r );
+	}
+
+	private void parseProg( List<Prog> list, TagElement r )
+	{
+		list.add( Prog.parse( this, r ) );
+	}
+
+	public void run( Map<String, String> overrides ) throws Exception
+	{
+		//System.out.println( "Test.run: "+name+", overrides = "+overrides );
+		
+		Map<String, String> substs = Param.processOverrides( "test", params,
+			overrides );
+		
+		//System.out.println( "Test.run: "+name+", substs = "+substs );
+		
+		runProgs( setup, substs );
+		try
+		{
+			List<RunningProg> runningProgs = startProgs( support, substs );
+			try
+			{
+				runProg( jig, substs );
+			}
+			finally
+			{
+				stopProgs( runningProgs );
+			}
+		}
+		finally
+		{
+			runProgs( cleanup, substs );
+		}
+	}
+
+	private void runProgs( List<Prog> progs, Map<String, String> substs ) throws Exception
+	{
+		for (Prog prog: progs)
+			runProg( prog, substs );
+	}
+
+	private List<RunningProg> startProgs( List<Prog> progs,
+		Map<String, String> substs ) throws Exception
+	{
+		List<RunningProg> runningProgs = new ArrayList<RunningProg>();
+		for (Prog prog: progs)
+			runningProgs.add( startProg( prog, substs ) );
+		return runningProgs;
+	}
+
+	private void stopProgs( List<RunningProg> runningProgs ) throws Exception
+	{
+		for (RunningProg rp: runningProgs)
+			stopProg( rp );
+	}
+
+	private void runProg( Prog prog, Map<String, String> substs ) throws Exception
+	{
+		prog.run( substs );
+	}
+
+	private RunningProg startProg( Prog prog, Map<String, String> substs ) throws Exception
+	{
+		return prog.start( substs );
+	}
+
+	private void stopProg( RunningProg rp ) throws Exception
+	{
+		rp.stop();
+	}
+
+	public Prog jig()
+	{
+		return jig;
+	}
+
+	public List<Prog> cleanup()
+	{
+		return cleanup;
+	}
+
+	public List<Prog> setup()
+	{
+		return setup;
+	}
+
+	public List<Prog> support()
+	{
+		return support;
+	}
+
+	public Map<String, Param> params()
+	{
+		return params;
+	}
+
+	public Program getProgram( String name )
+	{
+		return itest.getProgram( name );
+	}
+}
\ No newline at end of file
diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/TestIntf.java b/interoptester/src/main/java/org/apache/etch/interoptester/TestIntf.java
new file mode 100644
index 0000000..e6499aa
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/TestIntf.java
@@ -0,0 +1,81 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Interface to a test. A test consists of setup, support, jig, and cleanup
+ * programs.
+ */
+public interface TestIntf
+{
+	/**
+	 * @return the containing InteropTestIntf.
+	 */
+	public InteropTestIntf itest();
+	
+	/**
+	 * @return the name of the test.
+	 */
+	public String name();
+	
+	/**
+	 * @return the params of this test.
+	 */
+	public Map<String, Param> params();
+	
+	/**
+	 * @return the setup programs of this test.
+	 */
+	public List<Prog> setup();
+	
+	/**
+	 * @return the support programs of this test.
+	 */
+	public List<Prog> support();
+	
+	/**
+	 * @return the test jig of this test. This is the program that performs the
+	 * test.
+	 */
+	public Prog jig();
+	
+	/**
+	 * @return the cleanup programs of this test.
+	 */
+	public List<Prog> cleanup();
+
+	/**
+	 * Runs the test with the specified arguments.
+	 * @param overrides name / value pairs which must correspond to defined
+	 * test parameters and override their values.
+	 * @throws Exception 
+	 */
+	public void run( Map<String, String> overrides ) throws Exception;
+
+	/**
+	 * @param name
+	 * @return the named Program
+	 */
+	public Program getProgram( String name );
+}
diff --git a/interoptester/src/main/java/org/apache/etch/interoptester/Token.java b/interoptester/src/main/java/org/apache/etch/interoptester/Token.java
new file mode 100644
index 0000000..924351e
--- /dev/null
+++ b/interoptester/src/main/java/org/apache/etch/interoptester/Token.java
@@ -0,0 +1,68 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.Map;
+
+import org.apache.etch.util.Assertion;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+
+
+/**
+ * Token models an unnamed positional parameter to a program.
+ */
+public class Token
+{
+	/**
+	 * @param r
+	 * @return the parsed Token.
+	 */
+	public static Token parse( TagElement r )
+	{
+		Assertion.check( r.matches( null, "token" ), "tag is token" );
+		
+		String value = r.getAttr( null, "value" );
+		if (value == null && r.hasChildren())
+			value = r.getCdataValue();
+		
+		return new Token( value );
+	}
+	
+	private Token( String value )
+	{
+		this.value = value;
+	}
+	
+	private final String value;
+	
+	/**
+	 * @param args named values which might be used as substitutions.
+	 * @return the value of this arg. This might involve substituting named
+	 * values from args.
+	 */
+	public String value( Map<String, String> args )
+	{
+		if (value == null)
+			return null;
+		
+		return Substitutor.subst( value, args );
+	}
+}
diff --git a/interoptester/src/test/java/org/apache/etch/interoptester/TestArg.java b/interoptester/src/test/java/org/apache/etch/interoptester/TestArg.java
new file mode 100644
index 0000000..4dcdbd0
--- /dev/null
+++ b/interoptester/src/test/java/org/apache/etch/interoptester/TestArg.java
@@ -0,0 +1,178 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.interoptester.Arg;
+import org.apache.etch.util.AssertionException;
+import org.apache.etch.util.core.xml.XmlParser;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+/**
+ * Test of Arg.
+ */
+public class TestArg
+{
+	private final Map<String, String> args = new HashMap<String, String>();
+	{
+		args.put( "bar", "123" );
+		args.put( "baz", "456" );
+	}
+	
+	private TagElement parseXml( String s ) throws Exception
+	{
+		return new XmlParser().parseOne( s );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = AssertionException.class )
+	public void parse1() throws Exception
+	{
+		// tag is arg
+		Arg.parse( parseXml( "<foo/>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void parse2() throws Exception
+	{
+		// arg tag has no name
+		Arg.parse( parseXml( "<arg/>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void parse3() throws Exception
+	{
+		// arg tag has no name
+		Arg.parse( parseXml( "<arg name=\"\"/>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void parse4() throws Exception
+	{
+		// arg 'foo' has no value
+		Arg.parse( parseXml( "<arg name=\"foo\"/>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void parse5() throws Exception
+	{
+		// arg 'foo' has no value
+		Arg.parse( parseXml( "<arg name=\"foo\"></arg>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse6() throws Exception
+	{
+		Arg a = Arg.parse( parseXml( "<arg name=\"foo\">abc</arg>" ) );
+		assertEquals( "foo", a.name() );
+		assertEquals( "abc", a.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse7() throws Exception
+	{
+		Arg a = Arg.parse( parseXml( "<arg name=\"foo\" value=\"\"/>" ) );
+		assertEquals( "foo", a.name() );
+		assertEquals( "", a.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse8() throws Exception
+	{
+		Arg a = Arg.parse( parseXml( "<arg name=\"foo\" value=\"abc\"/>" ) );
+		assertEquals( "foo", a.name() );
+		assertEquals( "abc", a.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse9() throws Exception
+	{
+		Arg a = Arg.parse( parseXml( "<arg name=\"fu\">{bar}</arg>" ) );
+		assertEquals( "fu", a.name() );
+		assertEquals( "123", a.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse10() throws Exception
+	{
+		Arg a = Arg.parse( parseXml( "<arg name=\"fu\" value=\"{bar}\"/>" ) );
+		assertEquals( "fu", a.name() );
+		assertEquals( "123", a.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse11() throws Exception
+	{
+		Arg a = Arg.parse( parseXml( "<arg name=\"tofu\">x{baz}y</arg>" ) );
+		assertEquals( "tofu", a.name() );
+		assertEquals( "x456y", a.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse12() throws Exception
+	{
+		Arg a = Arg.parse( parseXml( "<arg name=\"tofu\" value=\"x{baz}y\"/>" ) );
+		assertEquals( "tofu", a.name() );
+		assertEquals( "x456y", a.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse13() throws Exception
+	{
+		Arg a = Arg.parse( parseXml( "<arg name=\"snafu\">x{barf}y</arg>" ) );
+		assertEquals( "snafu", a.name() );
+		assertEquals( "x{barf}y", a.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse14() throws Exception
+	{
+		Arg a = Arg.parse( parseXml( "<arg name=\"snafu\" value=\"x{barf}y\"/>" ) );
+		assertEquals( "snafu", a.name() );
+		assertEquals( "x{barf}y", a.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void toString1() throws Exception
+	{
+		Arg a = Arg.parse( parseXml( "<arg name=\"tofu\" value=\"x{baz}y\"/>" ) );
+		assertEquals( "Arg( tofu, x{baz}y )", a.toString() );
+	}
+}
diff --git a/interoptester/src/test/java/org/apache/etch/interoptester/TestEnv.java b/interoptester/src/test/java/org/apache/etch/interoptester/TestEnv.java
new file mode 100644
index 0000000..9689fca
--- /dev/null
+++ b/interoptester/src/test/java/org/apache/etch/interoptester/TestEnv.java
@@ -0,0 +1,190 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.interoptester.Env;
+import org.apache.etch.util.AssertionException;
+import org.apache.etch.util.core.xml.XmlParser;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/** Test of Env */
+public class TestEnv
+{
+	private final Map<String, String> args = new HashMap<String, String>();
+	{
+		args.put( "bar", "123" );
+		args.put( "baz", "456" );
+	}
+	
+	private TagElement parseXml( String s ) throws Exception
+	{
+		return new XmlParser().parseOne( s );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = AssertionException.class )
+	public void parse1() throws Exception
+	{
+		// tag is env
+		Env.parse( parseXml( "<blah/>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void parse2() throws Exception
+	{
+		// env tag has no name
+		Env.parse( parseXml( "<env/>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void parse3() throws Exception
+	{
+		// env tag has no name
+		Env.parse( parseXml( "<env name=\"\"/>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse4() throws Exception
+	{
+		Env e = Env.parse( parseXml( "<env name=\"foo\"/>" ) );
+		assertEquals( "foo", e.name() );
+		assertNull( e.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse5() throws Exception
+	{
+		Env e = Env.parse( parseXml( "<env name=\"foo\"></env>" ) );
+		assertEquals( "foo", e.name() );
+		assertNull( e.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse6() throws Exception
+	{
+		Env e = Env.parse( parseXml( "<env name=\"bar\">abc</env>" ) );
+		assertEquals( "bar", e.name() );
+		assertEquals( "abc", e.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse7() throws Exception
+	{
+		Env e = Env.parse( parseXml( "<env name=\"foo\" value=\"\"/>" ) );
+		assertEquals( "foo", e.name() );
+		assertEquals( "", e.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse8() throws Exception
+	{
+		Env e = Env.parse( parseXml( "<env name=\"foo\" value=\"abc\"/>" ) );
+		assertEquals( "foo", e.name() );
+		assertEquals( "abc", e.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse9() throws Exception
+	{
+		Env e = Env.parse( parseXml( "<env name=\"bar\">{blah}</env>" ) );
+		assertEquals( "bar", e.name() );
+		assertEquals( "{blah}", e.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse10() throws Exception
+	{
+		Env e = Env.parse( parseXml( "<env name=\"foo\" value=\"{blah}\"/>" ) );
+		assertEquals( "foo", e.name() );
+		assertEquals( "{blah}", e.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse11() throws Exception
+	{
+		Env e = Env.parse( parseXml( "<env name=\"bar\">s{blag}t</env>" ) );
+		assertEquals( "bar", e.name() );
+		assertEquals( "s{blag}t", e.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse12() throws Exception
+	{
+		Env e = Env.parse( parseXml( "<env name=\"foo\" value=\"s{blag}t\"/>" ) );
+		assertEquals( "foo", e.name() );
+		assertEquals( "s{blag}t", e.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse13() throws Exception
+	{
+		Env e = Env.parse( parseXml( "<env name=\"bar\">{bar}</env>" ) );
+		assertEquals( "bar", e.name() );
+		assertEquals( "123", e.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse14() throws Exception
+	{
+		Env e = Env.parse( parseXml( "<env name=\"foo\" value=\"{bar}\"/>" ) );
+		assertEquals( "foo", e.name() );
+		assertEquals( "123", e.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse15() throws Exception
+	{
+		Env e = Env.parse( parseXml( "<env name=\"bar\">x{baz}y</env>" ) );
+		assertEquals( "bar", e.name() );
+		assertEquals( "x456y", e.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse16() throws Exception
+	{
+		Env e = Env.parse( parseXml( "<env name=\"foo\" value=\"x{baz}y\"/>" ) );
+		assertEquals( "foo", e.name() );
+		assertEquals( "x456y", e.value( args ) );
+	}
+}
diff --git a/interoptester/src/test/java/org/apache/etch/interoptester/TestParam.java b/interoptester/src/test/java/org/apache/etch/interoptester/TestParam.java
new file mode 100644
index 0000000..9be6481
--- /dev/null
+++ b/interoptester/src/test/java/org/apache/etch/interoptester/TestParam.java
@@ -0,0 +1,136 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+import org.apache.etch.interoptester.Param;
+import org.apache.etch.util.AssertionException;
+import org.apache.etch.util.core.xml.XmlParser;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/** */
+public class TestParam
+{
+	private final Map<String, String> args = new HashMap<String, String>();
+	{
+		args.put( "bar", "123" );
+		args.put( "baz", "456" );
+	}
+	
+	private TagElement parseXml( String s ) throws Exception
+	{
+		return new XmlParser().parseOne( s );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = AssertionException.class )
+	public void parse1() throws Exception
+	{
+		// tag is param
+		Param.parse( parseXml( "<foo/>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void parse2() throws Exception
+	{
+		// param tag has no name attribute
+		Param.parse( parseXml( "<param/>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse3() throws Exception
+	{
+		Param p = Param.parse( parseXml( "<param name=\"foo\"/>" ) );
+		assertEquals( "foo", p.name() );
+		assertNull( p.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse4() throws Exception
+	{
+		Param p = Param.parse( parseXml( "<param name=\"foo\"></param>" ) );
+		assertEquals( "foo", p.name() );
+		assertNull( p.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse5() throws Exception
+	{
+		Param p = Param.parse( parseXml( "<param name=\"foo\">789</param>" ) );
+		assertEquals( "foo", p.name() );
+		assertEquals( "789", p.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse6() throws Exception
+	{
+		Param p = Param.parse( parseXml( "<param name=\"foo\" default=\"\"/>" ) );
+		assertEquals( "foo", p.name() );
+		assertEquals( "", p.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse7() throws Exception
+	{
+		Param p = Param.parse( parseXml( "<param name=\"foo\" default=\"789\"/>" ) );
+		assertEquals( "foo", p.name() );
+		assertEquals( "789", p.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse8() throws Exception
+	{
+		Param p = Param.parse( parseXml( "<param name=\"bar\"/>" ) );
+		assertEquals( "bar", p.name() );
+		assertEquals( "123", p.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse9() throws Exception
+	{
+		Param p = Param.parse( parseXml( "<param name=\"baz\" default=\"234\"/>" ) );
+		assertEquals( "baz", p.name() );
+		assertEquals( "456", p.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void toString1() throws Exception
+	{
+		Param p = Param.parse( parseXml( "<param name=\"baz\" default=\"234\"/>" ) );
+		assertEquals( "Param( baz, 234 )", p.toString() );
+	}
+}
diff --git a/interoptester/src/test/java/org/apache/etch/interoptester/TestProg.java b/interoptester/src/test/java/org/apache/etch/interoptester/TestProg.java
new file mode 100644
index 0000000..d3ea120
--- /dev/null
+++ b/interoptester/src/test/java/org/apache/etch/interoptester/TestProg.java
@@ -0,0 +1,159 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.etch.interoptester.InteropTestIntf;
+import org.apache.etch.interoptester.Param;
+import org.apache.etch.interoptester.Prog;
+import org.apache.etch.interoptester.Program;
+import org.apache.etch.interoptester.TestIntf;
+import org.apache.etch.util.AssertionException;
+import org.apache.etch.util.core.xml.XmlParser;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+
+import static org.junit.Assert.*;
+
+
+/** Test of Prog */
+public class TestProg
+{
+	private final TestIntf test = new MyTest();
+	
+	private TagElement parseXml( String s ) throws Exception
+	{
+		return new XmlParser().parseOne( s );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test( expected = AssertionException.class )
+	public void parse1() throws Exception
+	{
+		// tag is prog
+		Prog.parse( test, parseXml( "<blah/>" ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test( expected = IllegalArgumentException.class )
+	public void parse2() throws Exception
+	{
+		// prog tag has no name attribute
+		Prog.parse( test, parseXml( "<prog/>" ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test( expected = IllegalArgumentException.class )
+	public void parse3() throws Exception
+	{
+		// prog tag has no name attribute
+		Prog.parse( test, parseXml( "<prog name=\"\"/>" ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void parse4() throws Exception
+	{
+		Prog p = Prog.parse( test, parseXml( "<prog name=\"foo\"/>" ) );
+		assertSame( test, p.test() );
+		assertEquals( "foo", p.name() );
+		assertEquals( 0, p.args().size() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test( expected = IllegalArgumentException.class )
+	public void parse5() throws Exception
+	{
+		Prog.parse( test, parseXml( "<prog name=\"foo\"><arg name=\"bar\"/></prog>" ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test( expected = IllegalArgumentException.class )
+	public void parse6() throws Exception
+	{
+		// duplicate name arg bar
+		Prog.parse( test, parseXml( "<prog name=\"foo\"><arg name=\"bar\"/><arg name=\"bar\"/></prog>" ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test( expected = IllegalArgumentException.class )
+	public void parse7() throws Exception
+	{
+		Prog.parse( test, parseXml( "<prog name=\"foo\"><arg name=\"bar\"/><arg name=\"baz\"/></prog>" ) );
+	}
+	
+	private static class MyTest implements TestIntf
+	{
+		public List<Prog> cleanup()
+		{
+			// ignore
+			return null;
+		}
+
+		public InteropTestIntf itest()
+		{
+			// ignore
+			return null;
+		}
+
+		public Prog jig()
+		{
+			// ignore
+			return null;
+		}
+
+		public String name()
+		{
+			// ignore
+			return null;
+		}
+
+		public Map<String, Param> params()
+		{
+			// ignore
+			return null;
+		}
+
+		public void run( Map<String, String> args )
+		{
+			// ignore
+		}
+
+		public List<Prog> setup()
+		{
+			// ignore
+			return null;
+		}
+
+		public List<Prog> support()
+		{
+			// ignore
+			return null;
+		}
+
+		public Program getProgram( String name )
+		{
+			// ignore
+			return null;
+		}
+	}
+}
diff --git a/interoptester/src/test/java/org/apache/etch/interoptester/TestRun.java b/interoptester/src/test/java/org/apache/etch/interoptester/TestRun.java
new file mode 100644
index 0000000..71b6872
--- /dev/null
+++ b/interoptester/src/test/java/org/apache/etch/interoptester/TestRun.java
@@ -0,0 +1,374 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.etch.interoptester.InteropTestIntf;
+import org.apache.etch.interoptester.Param;
+import org.apache.etch.interoptester.Prog;
+import org.apache.etch.interoptester.Program;
+import org.apache.etch.interoptester.Run;
+import org.apache.etch.interoptester.TestIntf;
+import org.apache.etch.util.AssertionException;
+import org.apache.etch.util.core.xml.XmlParser;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+import org.junit.Test;
+
+
+/** */
+public class TestRun
+{
+	private InteropTestIntf itest = new MyInteropTestIntf();
+	
+	private TagElement parseXml( String s ) throws Exception
+	{
+		return new XmlParser().parseOne( s );
+	}
+	
+	/** @throws Exception */
+	@Test( expected=AssertionException.class )
+	public void parse1() throws Exception
+	{
+		Run.parse( itest, parseXml( "<blah/>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected=IllegalArgumentException.class )
+	public void parse2() throws Exception
+	{
+		Run.parse( itest, parseXml( "<run/>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected=IllegalArgumentException.class )
+	public void parse3() throws Exception
+	{
+		Run.parse( itest, parseXml( "<run test=\"\"/>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse4() throws Exception
+	{
+		Run r = Run.parse( itest, parseXml( "<run test=\"foo\"/>" ) );
+		assertSame( itest, r.itest() );
+		assertEquals( "foo", r.test() );
+		assertEquals( 0, r.args().size() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse5() throws Exception
+	{
+		Run r = Run.parse( itest, parseXml( "<run test=\"bar\"></run>" ) );
+		assertSame( itest, r.itest() );
+		assertEquals( "bar", r.test() );
+		assertEquals( 0, r.args().size() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected=IllegalArgumentException.class )
+	public void parse6() throws Exception
+	{
+		// unknown tag blah in run.
+		Run.parse( itest, parseXml( "<run test=\"foo\"><blah/></run>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected=IllegalArgumentException.class )
+	public void parse7() throws Exception
+	{
+		// arg tag has no name.
+		Run.parse( itest, parseXml( "<run test=\"foo\"><arg/></run>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected=IllegalArgumentException.class )
+	public void parse8() throws Exception
+	{
+		// arg tag has no name.
+		Run.parse( itest, parseXml( "<run test=\"foo\"><arg name=\"\"/></run>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void parse9() throws Exception
+	{
+		// arg a1 has no value
+		Run.parse( itest, parseXml( "<run test=\"foo\"><arg name=\"a1\"/></run>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected=IllegalArgumentException.class )
+	public void parse10() throws Exception
+	{
+		// duplicate name arg a1
+		Run.parse( itest, parseXml( "<run test=\"foo\"><arg name=\"a1\"/><arg name=\"a1\"/></run>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void parse11() throws Exception
+	{
+		// arg a1 has no value
+		Run.parse( itest, parseXml( "<run test=\"foo\"><arg name=\"a1\"/><arg name=\"a2\"/></run>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected=RuntimeException.class )
+	public void run1() throws Exception
+	{
+		// test bad not found
+		Run r = Run.parse( itest, parseXml( "<run test=\"bad\"/>" ) );
+		r.run( new HashMap<String, String>() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void run2() throws Exception
+	{
+		Run r = Run.parse( itest, parseXml( "<run test=\"foo\"/>" ) );
+		assertNull( test );
+		r.run( new HashMap<String, String>() );
+		assertEquals( "foo", test.name() );
+		assertEquals( 0, test.args.size() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void run3() throws Exception
+	{
+		// arg 'abc' has no value
+		Run.parse( itest, parseXml( "<run test=\"foo\"><arg name=\"abc\"/></run>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void run4() throws Exception
+	{
+		Run r = Run.parse( itest, parseXml( "<run test=\"foo\"><arg name=\"abc\" value=\"234\"/></run>" ) );
+		assertNull( test );
+		r.run( new HashMap<String, String>() );
+		assertEquals( "foo", test.name() );
+		assertEquals( 1, test.args.size() );
+		assertEquals( "234", test.args.get( "abc" ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void run5() throws Exception
+	{
+		Run r = Run.parse( itest, parseXml( "<run test=\"foo\"><arg name=\"abc\">345</arg></run>" ) );
+		assertNull( test );
+		r.run( new HashMap<String, String>() );
+		assertEquals( "foo", test.name() );
+		assertEquals( 1, test.args.size() );
+		assertEquals( "345", test.args.get( "abc" ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void run6() throws Exception
+	{
+		Run r = Run.parse( itest, parseXml( "<run test=\"bar\"/>" ) );
+		assertNull( test );
+		Map<String, String> args = new HashMap<String, String>();
+		args.put( "abc", "123" );
+		r.run( args );
+		assertEquals( "bar", test.name() );
+		assertEquals( 0, test.args.size() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void run7() throws Exception
+	{
+		Run r = Run.parse( itest, parseXml( "<run test=\"bar\"><arg name=\"abc\" value=\"xy\"/></run>" ) );
+		assertNull( test );
+		Map<String, String> args = new HashMap<String, String>();
+		args.put( "p1", "123" );
+		r.run( args );
+		assertEquals( "bar", test.name() );
+		assertEquals( 1, test.args.size() );
+		assertEquals( "xy", test.args.get( "abc" ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void run8() throws Exception
+	{
+		Run r = Run.parse( itest, parseXml( "<run test=\"bar\"><arg name=\"abc\" value=\"x{p2}y\"/></run>" ) );
+		assertNull( test );
+		Map<String, String> args = new HashMap<String, String>();
+		args.put( "p1", "123" );
+		r.run( args );
+		assertEquals( "bar", test.name() );
+		assertEquals( 1, test.args.size() );
+		assertEquals( "x{p2}y", test.args.get( "abc" ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void run9() throws Exception
+	{
+		Run r = Run.parse( itest, parseXml( "<run test=\"bar\"><arg name=\"abc\" value=\"x{p1}y\"/></run>" ) );
+		assertNull( test );
+		Map<String, String> args = new HashMap<String, String>();
+		args.put( "p1", "123" );
+		r.run( args );
+		assertEquals( "bar", test.name() );
+		assertEquals( 1, test.args.size() );
+		assertEquals( "x123y", test.args.get( "abc" ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void run10() throws Exception
+	{
+		Run r = Run.parse( itest, parseXml( "<run test=\"bar\"><arg name=\"abc\" value=\"x\\{p1}y\"/></run>" ) );
+		assertNull( test );
+		Map<String, String> args = new HashMap<String, String>();
+		args.put( "p1", "123" );
+		r.run( args );
+		assertEquals( "bar", test.name() );
+		assertEquals( 1, test.args.size() );
+		assertEquals( "x{p1}y", test.args.get( "abc" ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void run11() throws Exception
+	{
+		Run r = Run.parse( itest, parseXml( "<run test=\"bar\"><arg name=\"abc\" value=\"x\\\\y\"/></run>" ) );
+		assertNull( test );
+		Map<String, String> args = new HashMap<String, String>();
+		args.put( "p1", "123" );
+		r.run( args );
+		assertEquals( "bar", test.name() );
+		assertEquals( 1, test.args.size() );
+		assertEquals( "x\\y", test.args.get( "abc" ) );
+	}
+	
+	private class MyInteropTestIntf implements InteropTestIntf
+	{
+		public TestIntf getTest( String test )
+		{
+			if (test.equals( "bad" ))
+				return null;
+			
+			return new MyTest( this, test );
+		}
+
+		public void run( Map<String, String> args )
+		{
+			// ignore.
+		}
+
+		public Program getProgram( String name )
+		{
+			// ignore.
+			return null;
+		}
+
+		public int nextRunId()
+		{
+			return ++runId;
+		}
+		
+		private int runId;
+	}
+	
+	private class MyTest implements TestIntf
+	{
+		public MyTest( InteropTestIntf itest, String name )
+		{
+			this.itest = itest;
+			this.name = name;
+		}
+		
+		private final InteropTestIntf itest;
+		
+		private final String name;
+		
+		public InteropTestIntf itest()
+		{
+			return itest;
+		}
+		
+		public String name()
+		{
+			return name;
+		}
+
+		public void run( Map<String, String> args )
+		{
+			TestRun.this.test = this;
+			this.args = args;
+		}
+		
+		private Map<String, String> args;
+
+		public List<Prog> cleanup()
+		{
+			// ignore
+			return null;
+		}
+
+		public Prog jig()
+		{
+			// ignore
+			return null;
+		}
+
+		public Map<String, Param> params()
+		{
+			// ignore
+			return null;
+		}
+
+		public List<Prog> setup()
+		{
+			// ignore
+			return null;
+		}
+
+		public List<Prog> support()
+		{
+			// ignore
+			return null;
+		}
+
+		public Program getProgram( String name )
+		{
+			// ignore
+			return null;
+		}
+	}
+	
+	private MyTest test;
+}
diff --git a/interoptester/src/test/java/org/apache/etch/interoptester/TestSubstitutor.java b/interoptester/src/test/java/org/apache/etch/interoptester/TestSubstitutor.java
new file mode 100644
index 0000000..ef28e20
--- /dev/null
+++ b/interoptester/src/test/java/org/apache/etch/interoptester/TestSubstitutor.java
@@ -0,0 +1,124 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+import org.apache.etch.interoptester.Substitutor;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/** */
+public class TestSubstitutor
+{
+	private final Map<String, String> map = new HashMap<String, String>();
+	{
+		map.put( "a", "1" );
+		map.put( "b", "2" );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subst1() throws Exception
+	{
+		assertEquals( "", Substitutor.subst( "", map ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subst2() throws Exception
+	{
+		assertEquals( "a", Substitutor.subst( "a", map ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subst3() throws Exception
+	{
+		assertEquals( "1", Substitutor.subst( "{a}", map ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subst4() throws Exception
+	{
+		assertEquals( "x2y", Substitutor.subst( "x{b}y", map ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subst5() throws Exception
+	{
+		assertEquals( "{c}", Substitutor.subst( "{c}", map ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subst5a() throws Exception
+	{
+		assertEquals( "{{c}}", Substitutor.subst( "{{c}}", map ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subst6() throws Exception
+	{
+		assertEquals( "{1}", Substitutor.subst( "{{a}}", map ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subst7() throws Exception
+	{
+		assertEquals( "{a", Substitutor.subst( "{a", map ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subst7a() throws Exception
+	{
+		assertEquals( "a}", Substitutor.subst( "a}", map ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subst8() throws Exception
+	{
+		assertEquals( "{a}", Substitutor.subst( "\\{a}", map ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subst9() throws Exception
+	{
+		assertEquals( "a", Substitutor.subst( "\\a", map ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subst10() throws Exception
+	{
+		assertEquals( "\\", Substitutor.subst( "\\\\", map ) );
+	}
+}
diff --git a/interoptester/src/test/java/org/apache/etch/interoptester/TestTest.java b/interoptester/src/test/java/org/apache/etch/interoptester/TestTest.java
new file mode 100644
index 0000000..d5e8c0d
--- /dev/null
+++ b/interoptester/src/test/java/org/apache/etch/interoptester/TestTest.java
@@ -0,0 +1,159 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+import static org.junit.Assert.*;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.interoptester.InteropTestIntf;
+import org.apache.etch.interoptester.Program;
+import org.apache.etch.interoptester.Test;
+import org.apache.etch.interoptester.TestIntf;
+import org.apache.etch.util.AssertionException;
+import org.apache.etch.util.core.xml.XmlParser;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+
+
+/** Test of Test */
+public class TestTest
+{
+	private final InteropTestIntf itest = new MyInteropTest();
+	
+	private final Map<String, String> args = new HashMap<String, String>();
+	{
+		args.put( "bar", "123" );
+		args.put( "baz", "456" );
+	}
+	
+	private TagElement parseXml( String s ) throws Exception
+	{
+		return new XmlParser().parseOne( s );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test( expected = AssertionException.class )
+	public void parse1() throws Exception
+	{
+		// tag is test
+		Test.parse( itest, parseXml( "<blah/>" ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test( expected = IllegalArgumentException.class )
+	public void parse2() throws Exception
+	{
+		// test tag has not name attribute
+		Test.parse( itest, parseXml( "<test/>" ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test( expected = IllegalArgumentException.class )
+	public void parse3() throws Exception
+	{
+		// no jig defined for test: foo
+		Test.parse( itest, parseXml( "<test name=\"foo\"/>" ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test( expected = IllegalArgumentException.class )
+	public void parse4() throws Exception
+	{
+		// no jig defined for test: foo
+		Test.parse( itest, parseXml( "<test name=\"foo\"><jig></jig></test>" ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test( expected = IllegalArgumentException.class )
+	public void parse5() throws Exception
+	{
+		// only one test jig per test
+		Test.parse( itest, parseXml(
+			"<test name=\"foo\"><jig><prog name=\"bar\"/><prog name=\"baz\"/></jig></test>" ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void parse6() throws Exception
+	{
+		Test t = Test.parse( itest, parseXml(
+			"<test name=\"foo\"><jig><prog name=\"bar\"/></jig></test>" ) );
+		assertSame( itest, t.itest() );
+		assertEquals( "foo", t.name() );
+		assertEquals( 0, t.params().size() );
+		assertEquals( 0, t.setup().size() );
+		assertEquals( 0, t.support().size() );
+		assertEquals( "bar", t.jig().name() );
+		assertEquals( 0, t.cleanup().size() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void parse7() throws Exception
+	{
+		Test t = Test.parse( itest, parseXml(
+			"<test name=\"bar\"><params><param name=\"param1\"/><param name=\"param2\"/></params><setup><prog name=\"setup1\"/><prog name=\"setup2\"/></setup><support><prog name=\"support1\"/><prog name=\"support2\"/></support><jig><prog name=\"jig1\"/></jig><cleanup><prog name=\"cleanup1\"/><prog name=\"cleanup2\"/></cleanup></test>" ) );
+		assertSame( itest, t.itest() );
+		assertEquals( "bar", t.name() );
+		assertEquals( 2, t.params().size() );
+		assertTrue( t.params().containsKey( "param1" ) );
+		assertTrue( t.params().containsKey( "param2" ) );
+		assertEquals( 2, t.setup().size() );
+		assertEquals( "setup1", t.setup().get( 0 ).name() );
+		assertEquals( "setup2", t.setup().get( 1 ).name() );
+		assertEquals( 2, t.support().size() );
+		assertEquals( "support1", t.support().get( 0 ).name() );
+		assertEquals( "support2", t.support().get( 1 ).name() );
+		assertEquals( "jig1", t.jig().name() );
+		assertEquals( 2, t.cleanup().size() );
+		assertEquals( "cleanup1", t.cleanup().get( 0 ).name() );
+		assertEquals( "cleanup2", t.cleanup().get( 1 ).name() );
+	}
+	
+	private static class MyInteropTest implements InteropTestIntf
+	{
+		public TestIntf getTest( String test )
+		{
+			// ignore
+			return null;
+		}
+
+		public void run( Map<String, String> args )
+		{
+			// ignore
+		}
+
+		public Program getProgram( String name )
+		{
+			// ignore
+			return null;
+		}
+
+		public int nextRunId()
+		{
+			return ++runId;
+		}
+		
+		private int runId;
+	}
+}
diff --git a/interoptester/src/test/java/org/apache/etch/interoptester/TestToken.java b/interoptester/src/test/java/org/apache/etch/interoptester/TestToken.java
new file mode 100644
index 0000000..0c5ffcd
--- /dev/null
+++ b/interoptester/src/test/java/org/apache/etch/interoptester/TestToken.java
@@ -0,0 +1,112 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.interoptester;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.etch.interoptester.Token;
+import org.apache.etch.util.AssertionException;
+import org.apache.etch.util.core.xml.XmlParser;
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+/** Test of Token */
+public class TestToken
+{
+	private final Map<String, String> args = new HashMap<String, String>();
+	{
+		args.put( "bar", "123" );
+		args.put( "baz", "456" );
+	}
+	
+	private TagElement parseXml( String s ) throws Exception
+	{
+		return new XmlParser().parseOne( s );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = AssertionException.class )
+	public void parse1() throws Exception
+	{
+		// tag is token
+		Token.parse( parseXml( "<blah/>" ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse2() throws Exception
+	{
+		Token t = Token.parse( parseXml( "<token/>" ) );
+		assertNull( t.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse3() throws Exception
+	{
+		Token t = Token.parse( parseXml( "<token></token>" ) );
+		assertNull( t.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse4() throws Exception
+	{
+		Token t = Token.parse( parseXml( "<token>abc</token>" ) );
+		assertEquals( "abc", t.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse5() throws Exception
+	{
+		Token t = Token.parse( parseXml( "<token value=\"\"/>" ) );
+		assertEquals( "", t.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse6() throws Exception
+	{
+		Token t = Token.parse( parseXml( "<token value=\"abc\"/>" ) );
+		assertEquals( "abc", t.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse7() throws Exception
+	{
+		Token t = Token.parse( parseXml( "<token>{bar}</token>" ) );
+		assertEquals( "123", t.value( args ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void parse8() throws Exception
+	{
+		Token t = Token.parse( parseXml( "<token value=\"{bar}\"/>" ) );
+		assertEquals( "123", t.value( args ) );
+	}
+}
diff --git a/plugins/README.txt b/plugins/README.txt
new file mode 100644
index 0000000..d754b0a
--- /dev/null
+++ b/plugins/README.txt
@@ -0,0 +1,4 @@
+visualstudioplugin
+vim
+ant
+
diff --git a/plugins/ant/build.xml b/plugins/ant/build.xml
new file mode 100644
index 0000000..9695f77
--- /dev/null
+++ b/plugins/ant/build.xml
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-ant-task" basedir="." default="help">
+    <description>Etch-Ant-Task implementation</description>
+    <property name="Etch.basedir" location="${basedir}/../.." />
+    <import file="${Etch.basedir}/build-support/etch.includes.xml" />
+
+    <!-- Static properties of the sub-project -->
+    <property name="proj"                 location="${Etch.basedir}/plugins/ant" />
+    <property name="target"               location="${proj}/target" />
+    <property name="src"                  location="${proj}/src" />        
+    <property name="generatedSrc"         location="${target}/generated-sources" />
+    <property name="classesDirectory"     location="${target}/classes" />
+    <property name="testResultsDirectory" location="${target}/test-results" />
+
+    <!-- MACRO: init-target -->
+    <macrodef name="init-target" >
+        <sequential>
+            <delete dir="${classesDirectory}"   failonerror="false" quiet="true" />
+            <mkdir dir="${classesDirectory}" />
+            <mkdir dir="${classesDirectory}/main" />
+            <mkdir dir="${classesDirectory}/test" />
+        </sequential>
+    </macrodef>
+
+    <!-- MACRO: compile-sources -->
+    <macrodef name="compile-sources" >
+        <sequential>            
+            <!-- compile ant plugin -->
+            <javac  debug="${Etch.javac.debug}"
+                    target="1.5"
+                    optimize="${Etch.javac.optimize}"
+                    destdir="${classesDirectory}/main" >
+                <src path="${src}/main/java" />
+                <exclude name="**/.svn/**" />
+                <classpath refid="Etch.dependencies.jar.paths" />
+                <classpath>
+                    <pathelement location="${Etch.HOME}/lib/${etch-compiler.jar}" />
+                    <pathelement location="${Etch.HOME}/lib/${etch-util.jar}" />
+                </classpath>
+            </javac>
+
+            <!-- compiler plugin resources -->
+            <copy todir="${classesDirectory}/main" >
+                <fileset dir="${src}/main/resources" excludes="**/.svn/**" />
+            </copy>
+
+            <!-- Compile Tests -->
+            <!--
+            <javac  debug="${Etch.javac.debug}"
+                    target="1.5"
+                    optimize="${Etch.javac.optimize}"
+                    destdir="${classesDirectory}/test" >
+                <src path="${src}/test/java" />
+                <exclude name="**/.svn/**" />
+                <classpath refid="Etch.dependencies.jar.paths" />
+                <classpath>
+                    <pathelement location="${classesDirectory}/main" />
+                    <pathelement location="${Etch.HOME}/lib/${etch-compiler.jar}" />
+                </classpath>
+            </javac>
+            -->
+
+            <!-- compiler plugin resources -->
+            <!--
+            <copy todir="${classesDirectory}/test" >
+                <fileset dir="${src}/test/resources" excludes="**/.svn/**" />
+            </copy>
+            -->
+        </sequential>
+    </macrodef>
+    
+    <!-- MACRO: bundle-jars -->
+    <macrodef name="bundle-jars" >
+        <attribute name="dist" default="${Etch.dist}" />
+        <sequential>
+            <mkdir dir="@{dist}/lib" />
+            
+            <!-- CREATE jars -->
+
+            <!-- Package up etch-ant-task jar -->
+            <jar jarfile="@{dist}/lib/${etch-ant-task.jar}" >
+                <manifest>
+                    <attribute name="Copyright"    value="${Etch.copyrightNotice}" />
+                    <attribute name="Version"      value="${Etch.version}" />
+                    <attribute name="LongVersion"  value="${Etch.longversion}" />
+                    <attribute name="Build-Tag"    value="${Etch.buildTag}" />
+                    <attribute name="SVN-Revision" value="${Etch.runtime.revisionNumber}" />
+                    <attribute name="Class-Path"   value="${etch-compiler.jar}" />
+                </manifest>
+                <metainf dir="${Etch.basedir}">
+                    <include name="NOTICE.txt" />
+                    <include name="LICENSE.txt" />
+                </metainf>
+                <fileset dir="${classesDirectory}/main"/>
+            </jar>
+
+            <!-- CREATE source archives -->
+            
+            <!-- package up etch-ant-task src -->
+            <zip destfile="@{dist}/lib/${etch-ant-task-src.zip}" >
+                <fileset dir="${src}/main/java" excludes="**/.svn/**" />
+                <fileset dir="${src}/main/resources" excludes="**/.svn/**" />
+            </zip>
+
+        </sequential>
+    </macrodef>
+    
+    <!-- INIT TARGET -->
+    <!-- Modify this target to define project specific properties that can only be set at runtime -->
+    <target name="do-init">
+        <delete dir="${target}" failonerror="false" quiet="true" />
+
+        <mkdir dir="${target}" />
+        <mkdir dir="${generatedSrc}" />
+        <mkdir dir="${classesDirectory}" />
+        <mkdir dir="${testResultsDirectory}" />
+    </target>
+
+    <!-- CLEAN TARGET -->
+    <target name="do-clean">
+        <delete dir="${target}" />
+    </target>
+
+    <!-- BUILD TARGET -->
+    
+    <target name="generate-sources" >
+        <!-- Generate version info -->
+    </target>
+
+    <target name="compile-for-dist" >
+        <!-- Initialize target directories -->
+        <init-target />
+
+        <!-- Compile Source -->
+        <compile-sources />
+
+        <!-- Bundle Jars -->
+        <bundle-jars dist="${Etch.dist}" />
+    </target>
+    
+    <target name="compile-for-clover" if="Clover.enabled" >
+
+        <echo message="Rebuilding with clover" />
+
+        <!-- initialize-clover -->
+        <initialize-clover suffix="etchanttask" >
+            <fileset dir="${src}/main/java">
+                <include name="**/*.java" />
+            </fileset>
+            <!--
+            <testsources dir="${src}/test/java">
+                <include name="**/*.java" />
+            </testsources>
+            -->
+        </initialize-clover>
+        
+        <!-- Initialize target directories -->
+        <init-target />
+        
+        <!-- Compile Source -->
+        <compile-sources />
+        
+        <!-- Bundle Jars -->
+        <bundle-jars dist="${Etch.clover-dist}" />
+
+    </target>
+    
+    <target name="do-build" depends="generate-sources,compile-for-dist,compile-for-clover" />
+
+    <!-- TEST TARGET -->
+    <target name="do-test">
+        
+        <!-- Run Unit Tests -->
+        <!--
+        <junit printsummary="yes" haltonfailure="no" dir="${classesDirectory}"
+            errorProperty="build.tests.fail" failureProperty="build.tests.fail">
+            <classpath>
+                <pathelement location="${classesDirectory}/main" />
+                <pathelement location="${classesDirectory}/test" />
+                <pathelement location="${Etch.dependency.junit.jar}" />
+                <pathelement location="${Etch.HOME}/lib/${etch-compiler.jar}" />
+                <pathelement location="${Etch.dependency.clover.jar}"/>
+            </classpath>
+            <formatter type="xml"/>
+            <batchtest fork="true" todir="${testResultsDirectory}">
+                <fileset dir="${src}/test/java">
+                    <include name="**/*.java" />
+                </fileset>
+            </batchtest>
+        </junit>
+        -->
+    </target>
+
+    <!-- POSTBUILD TARGET -->
+    <target name="do-postbuild">
+    </target>
+
+    <target name="do-publish" if="build.tests.fail">
+        <!-- Set flag file if any tests failed -->
+        <touch file="${Etch.runtime.tests.fail}"/>
+    </target>
+
+</project>
diff --git a/plugins/ant/src/main/java/org/apache/etch/tools/ant/EtchCompileTask.java b/plugins/ant/src/main/java/org/apache/etch/tools/ant/EtchCompileTask.java
new file mode 100644
index 0000000..8235330
--- /dev/null
+++ b/plugins/ant/src/main/java/org/apache/etch/tools/ant/EtchCompileTask.java
@@ -0,0 +1,283 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tools.ant;
+
+import java.io.File;
+import java.util.StringTokenizer;
+
+import org.apache.etch.compiler.CmdLineOptions;
+import org.apache.etch.compiler.EtchCompiler;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.DirSet;
+
+
+/**
+ * Ant task for compiling Etch sources files.
+ * 
+ */
+public class EtchCompileTask extends Task
+{
+	/**
+	 * Creates a new ant task for running the Etch compiler.
+	 */
+	public EtchCompileTask()
+	{
+		// nothing to do.
+	}
+
+	private CmdLineOptions clo = new CmdLineOptions();
+
+	/////////
+
+	/**
+	 * The list of paths to search for included or mixed in files (-I option).
+	 *
+	 * @param value
+	 */
+	public void addIncludes( DirSet value )
+	{
+		DirectoryScanner ds = value.getDirectoryScanner( getProject() );
+		for (String dir : ds.getIncludedDirectories())
+			clo.includePath.add( new File( ds.getBasedir(), dir ) );
+	}
+
+	/**
+	 * The source file to compile.
+	 *
+	 * @param value
+	 */
+	public void setFile( File value )
+	{
+		if (clo.sourceFile != null)
+			throw new BuildException( "only one source file at a time, please" );
+		clo.sourceFile = value;
+	}
+
+	/**
+	 * The destination directory of the generated files (-d option). If not
+	 * specified, the same directory of the source file.
+	 *
+	 * @param value
+	 */
+	public void setOutputDir( File value )
+	{
+		clo.outputDir = value;
+	}
+
+	/**
+	 * The binding name. Example values are java, csharp, python, ruby, c, and
+	 * xml (-b option).
+	 *
+	 * @param value
+	 */
+	public void setBinding( String value )
+	{
+		clo.binding = value;
+	}
+
+	/**
+	 * This specifies the file(s) we need to generate (-w option). Valid values
+	 * depend upon the binding, but examples include BOTH, SERVER, CLIENT, ALL,
+	 * INTF, IMPL, MAIN, NONE, and FORCE. HELP might give you some. Separate
+	 * values using one or more characters from ",;: " (e.g., "BOTH, INTF",
+	 * which is also the default for many bindings).
+	 *
+	 * @param value
+	 */
+	public void setWhat( String value )
+	{
+		StringTokenizer st = new StringTokenizer( value,
+			CmdLineOptions.WHAT_DELIMETER );
+		while (st.hasMoreElements())
+			clo.what.add( st.nextToken().toUpperCase() );
+	}
+
+	/**
+	 * Flag indicates whether to ignore the globally reserved word list (-g
+	 * option).
+	 *
+	 * @param value
+	 */
+	public void setIgnoreGlobalWordsList( boolean value )
+	{
+		clo.ignoreGlobalWordsList = value;
+	}
+
+	/**
+	 * Flag indicates whether to ignore the locally reserved word list (-l
+	 * option).
+	 *
+	 * @param value
+	 */
+	public void setIgnoreLocalWordsList( boolean value )
+	{
+		clo.ignoreLocalWordsList = value;
+	}
+
+	/**
+	 * The path of the user-defined reserved words list (-W option).
+	 *
+	 * @param value
+	 */
+	public void setUserWordsList( File value )
+	{
+		clo.userWordsList = value;
+	}
+
+	/**
+	 * Ignore the ETCH_INCLUDE_PATH environment variable (-i option).
+	 *
+	 * @param value
+	 */
+	public void setIgnoreIncludePath( boolean value )
+	{
+		clo.ignoreIncludePath = value;
+	}
+
+	/**
+	 * Flag indicates that mixin artifacts should not be generated (-n option).
+	 * If false, mixin artifacts are generated into mixinOutputDir.
+	 *
+	 * @param value
+	 */
+	public void setNoMixinArtifacts( boolean value )
+	{
+		clo.noMixinArtifacts = value;
+	}
+
+	/**
+	 * The destination directory of the generated mixin files (-m option). If
+	 * not specified, and if noMixinArtifacts allows, mixin artifacts are
+	 * generated into outputDir.
+	 *
+	 * @param value
+	 */
+	public void setMixinOutputDir( File value )
+	{
+		clo.mixinOutputDir = value;
+	}
+
+	/**
+	 * Flag indicates whether the module name should should be flattened to
+	 * produce a single directory or a directory tree (e.g., for csharp) (-f
+	 * option).
+	 *
+	 * @param value
+	 */
+	public void setNoFlattenPackages( boolean value )
+	{
+		clo.noFlattenPackages = value;
+	}
+
+	/**
+	 * Destination directory of the user editable template files (-t option).
+	 * If not specified, same as outputDir.
+	 *
+	 * @param value
+	 */
+	public void setTemplateOutputDir( File value )
+	{
+		clo.templateOutputDir = value;
+	}
+
+	/**
+	 * Flag indicates that the compiler should not report progress (-q option).
+	 * 
+	 * @param value
+	 */
+	public void setQuiet( boolean value )
+	{
+		clo.quiet = value;
+	}
+
+	/**
+	 * We're just testing the compiler, don't write any files (--testing option).
+	 * 
+	 * @param value 
+	 */
+	public void setTesting( boolean value )
+	{
+		clo.testing = value;
+	}
+
+	/** 
+	 * Sets the location of the etch installation (this is the directory which
+	 * contains bin and lib) (no corresponding command line option).
+	 *
+	 * @param value
+	 */
+	public void setHome( File value )
+	{
+		home = value;
+	}
+
+	private File home;
+
+	/** EXECUTION **/
+
+	@Override
+	/**
+	 * execute
+	 */
+	public void execute() throws BuildException
+	{
+		ClassLoader cl;
+
+		try
+		{
+			cl = EtchCompiler.setupClassLoader( home );
+		}
+		catch ( Exception e )
+		{
+			e.printStackTrace();
+			throw new BuildException(
+				"problem setting up etch compiler class loader", e );
+		}
+
+		EtchCompiler etchCompiler;
+
+		try
+		{
+			// Instantiate a new compiler instance
+			etchCompiler = new EtchCompiler( cl );
+		}
+		catch ( Exception e )
+		{
+			e.printStackTrace();
+			throw new BuildException( "problem setting up etch compiler", e );
+		}
+
+		try
+		{
+			etchCompiler.run( clo );
+		}
+		catch ( Exception e )
+		{
+			e.printStackTrace();
+			throw new BuildException( "problem running etch compiler", e );
+		}
+		
+		if (clo.lh.hasError())
+			throw new BuildException( "problem running etch compiler" );
+	}
+}
diff --git a/plugins/ant/src/main/resources/org/apache/etch/tools/ant/etch.xml b/plugins/ant/src/main/resources/org/apache/etch/tools/ant/etch.xml
new file mode 100644
index 0000000..735d963
--- /dev/null
+++ b/plugins/ant/src/main/resources/org/apache/etch/tools/ant/etch.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<antlib>
+	<taskdef name="etch" classname="org.apache.etch.tools.ant.EtchCompileTask"/>
+</antlib>
diff --git a/plugins/vim/README.txt b/plugins/vim/README.txt
new file mode 100644
index 0000000..cb17e43
--- /dev/null
+++ b/plugins/vim/README.txt
@@ -0,0 +1,16 @@
+About
+-----
+
+etch.vim is a syntax definition for .etch files. It is based on the java.vim syntax file that ships w/ vim70.
+
+
+To Install
+----------
+
+1. Copy etch.vim to VIM_HOME/syntax
+2. Add the following line your .vimrc to recogize .etch files:
+
+   au BufNewFile,BufRead *.etch setf etch
+
+3. Enjoy!
+
diff --git a/plugins/vim/etch.vim b/plugins/vim/etch.vim
new file mode 100644
index 0000000..230f889
--- /dev/null
+++ b/plugins/vim/etch.vim
@@ -0,0 +1,295 @@
+" Vim syntax file
+" Language:     Etch 
+" Maintainer:   James Dixson <dixson@apache.org>
+" URL:		http://incubator.apache.org/projects/etch.html
+" Last Change:  13 Nov 2007
+"
+" Licensed to the Apache Software Foundation (ASF) under one   *
+" or more contributor license agreements.  See the NOTICE file *
+" distributed with this work for additional information        *
+" regarding copyright ownership.  The ASF licenses this file   *
+" to you under the Apache License, Version 2.0 (the            *
+" \"License\"); you may not use this file except in compliance   *
+" with the License.  You may obtain a copy of the License at   *
+"                                                              *
+"   http://www.apache.org/licenses/LICENSE-2.0                 *
+"                                                              *
+" Unless required by applicable law or agreed to in writing,   *
+" software distributed under the License is distributed on an  *
+" \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+" KIND, either express or implied.  See the License for the    *
+" specific language governing permissions and limitations      *
+" under the License.                                           *
+"
+"
+"  Based on java.vim by Claudio Fleiner <claudio@fleiner.com>
+"
+" Please check :help etch.vim for comments on some of the options available.
+
+" Quit when a syntax file was already loaded
+if !exists("main_syntax")
+  if version < 600
+    syntax clear
+  elseif exists("b:current_syntax")
+    finish
+  endif
+  " we define it here so that included files can test for it
+  let main_syntax='etch'
+endif
+
+" don't use standard HiLink, it will not work with included syntax files
+if version < 508
+  command! -nargs=+ EtchHiLink hi link <args>
+else
+  command! -nargs=+ EtchHiLink hi def link <args>
+endif
+
+" some characters that cannot be in a etch idl (outside a string)
+syn match etchError "[\\@`]"
+syn match etchError "<<<\|\.\.\|=>\|<>\|||=\|&&=\|[^-]->\|\*\/"
+syn match etchOK "\.\.\."
+
+" use separate name so that it can be deleted in etchcc.vim
+syn match   etchError2 "#\|=<"
+EtchHiLink etchError2 etchError
+
+" keyword definitions
+syn keyword etchOptionAsyncReceiver pool queued none free
+syn keyword etchOptionAuthorize true false 
+"syn keyword etchOptionAuthorize true false <id> <integer>
+syn keyword etchOptionDirection client server both
+"syn keyword etchOptionExtern <id>[]
+syn keyword etchOptionOneway true false
+"syn keyword etchOptionTimeout <integer>
+"syn keyword etchOptionToString <string>
+syn keyword etchOptionUnchecked true false
+
+syn keyword etchExternal module
+syn match etchExternal "\<import\>\(\s\+static\>\)\?"
+syn keyword etchConstant null
+syn keyword etchType boolean byte const double enum exception extern float int long mixin object service short string struct void
+syn keyword etchBoolean true false
+syn keyword etchMethodDecl throws
+syn match   etchAnnotation      "@[_$a-zA-Z][_$a-zA-Z0-9_]*\>"
+
+if exists("etch_space_errors")
+  if !exists("etch_no_trail_space_error")
+    syn match   etchSpaceError  "\s\+$"
+  endif
+  if !exists("etch_no_tab_space_error")
+    syn match   etchSpaceError  " \+\t"me=e-1
+  endif
+endif
+
+syn region  etchLabelRegion     transparent matchgroup=etchLabel start="\<case\>" matchgroup=NONE end=":" contains=etchNumber,etchCharacter
+syn match   etchUserLabel       "^\s*[_$a-zA-Z][_$a-zA-Z0-9_]*\s*:"he=e-1 contains=etchLabel
+syn keyword etchLabel		default
+
+" The following cluster contains all etch groups except the contained ones
+syn cluster etchTop add=etchError,etchError2,etchOptionAsyncReceiver,etchOptionDirection,etchExternal,etchConstant,etchType,etchBoolean,etchMethodDecl,etchAnnotation
+
+" Comments
+syn keyword etchTodo		 contained TODO FIXME XXX
+if exists("etch_comment_strings")
+  syn region  etchCommentString    contained start=+"+ end=+"+ end=+$+ end=+\*/+me=s-1,he=s-1 contains=etchSpecial,etchCommentStar,etchSpecialChar,@Spell
+  syn region  etchComment2String   contained start=+"+  end=+$\|"+  contains=etchSpecial,etchSpecialChar,@Spell
+  syn match   etchCommentCharacter contained "'\\[^']\{1,6\}'" contains=etchSpecialChar
+  syn match   etchCommentCharacter contained "'\\''" contains=etchSpecialChar
+  syn match   etchCommentCharacter contained "'[^\\]'"
+  syn cluster etchCommentSpecial add=etchCommentString,etchCommentCharacter,etchNumber
+  syn cluster etchCommentSpecial2 add=etchComment2String,etchCommentCharacter,etchNumber
+endif
+syn region  etchComment		 start="/\*"  end="\*/" contains=@etchCommentSpecial,etchTodo,@Spell
+syn match   etchCommentStar      contained "^\s*\*[^/]"me=e-1
+syn match   etchCommentStar      contained "^\s*\*$"
+syn match   etchLineComment      "//.*" contains=@etchCommentSpecial2,etchTodo,@Spell
+EtchHiLink etchCommentString etchString
+EtchHiLink etchComment2String etchString
+EtchHiLink etchCommentCharacter etchCharacter
+
+syn cluster etchTop add=etchComment,etchLineComment
+
+if !exists("etch_ignore_javadoc") 
+  syntax case ignore
+  " syntax coloring for javadoc comments (HTML)
+  syntax include @etchHtml <sfile>:p:h/html.vim
+  unlet b:current_syntax
+  syn region  etchDocComment    start="/\*\*"  end="\*/" keepend contains=etchCommentTitle,@etchHtml,etchDocTags,etchDocSeeTag,etchTodo,@Spell
+  syn region  etchCommentTitle  contained matchgroup=etchDocComment start="/\*\*"   matchgroup=etchCommentTitle keepend end="\.$" end="\.[ \t\r<&]"me=e-1 end="[^{]@"me=s-2,he=s-1 end="\*/"me=s-1,he=s-1 contains=@etchHtml,etchCommentStar,etchTodo,@Spell,etchDocTags,etchDocSeeTag
+
+  syn region etchDocTags         contained start="{@\(link\|linkplain\|inherit[Dd]oc\|doc[rR]oot\|value\)" end="}"
+  syn match  etchDocTags         contained "@\(param\|exception\|throws\|since\)\s\+\S\+" contains=etchDocParam
+  syn match  etchDocParam        contained "\s\S\+"
+  syn match  etchDocTags         contained "@\(version\|author\|return\|deprecated\|serial\|serialField\|serialData\)\>"
+  syn region etchDocSeeTag       contained matchgroup=etchDocTags start="@see\s\+" matchgroup=NONE end="\_."re=e-1 contains=etchDocSeeTagParam
+  syn match  etchDocSeeTagParam  contained @"\_[^"]\+"\|<a\s\+\_.\{-}</a>\|\(\k\|\.\)*\(#\k\+\((\_[^)]\+)\)\=\)\=@ extend
+  syntax case match
+endif
+
+" match the special comment /**/
+syn match   etchComment		 "/\*\*/"
+
+" Strings and constants
+syn match   etchSpecialError     contained "\\."
+syn match   etchSpecialCharError contained "[^']"
+syn match   etchSpecialChar      contained "\\\([4-9]\d\|[0-3]\d\d\|[\"\\'ntbrf]\|u\x\{4\}\)"
+syn region  etchString		start=+"+ end=+"+ end=+$+ contains=etchSpecialChar,etchSpecialError,@Spell
+" next line disabled, it can cause a crash for a long line
+"syn match   etchStringError	  +"\([^"\\]\|\\.\)*$+
+syn match   etchCharacter	 "'[^']*'" contains=etchSpecialChar,etchSpecialCharError
+syn match   etchCharacter	 "'\\''" contains=etchSpecialChar
+syn match   etchCharacter	 "'[^\\]'"
+syn match   etchNumber		 "\<\(0[0-7]*\|0[xX]\x\+\|\d\+\)[lL]\=\>"
+syn match   etchNumber		 "\(\<\d\+\.\d*\|\.\d\+\)\([eE][-+]\=\d\+\)\=[fFdD]\="
+syn match   etchNumber		 "\<\d\+[eE][-+]\=\d\+[fFdD]\=\>"
+syn match   etchNumber		 "\<\d\+\([eE][-+]\=\d\+\)\=[fFdD]\>"
+
+" unicode characters
+syn match   etchSpecial "\\u\d\{4\}"
+
+syn cluster etchTop add=etchString,etchCharacter,etchNumber,etchSpecial,etchStringError
+
+if exists("etch_highlight_functions")
+  if etch_highlight_functions == "indent"
+    syn match  etchFuncDef "^\(\t\| \{8\}\)[_$a-zA-Z][_$a-zA-Z0-9_. \[\]]*([^-+*/()]*)" contains=etchScopeDecl,etchType,etchStorageClass,@etchClasses
+    syn region etchFuncDef start=+^\(\t\| \{8\}\)[$_a-zA-Z][$_a-zA-Z0-9_. \[\]]*([^-+*/()]*,\s*+ end=+)+ contains=etchScopeDecl,etchType,etchStorageClass,@etchClasses
+    syn match  etchFuncDef "^  [$_a-zA-Z][$_a-zA-Z0-9_. \[\]]*([^-+*/()]*)" contains=etchScopeDecl,etchType,etchStorageClass,@etchClasses
+    syn region etchFuncDef start=+^  [$_a-zA-Z][$_a-zA-Z0-9_. \[\]]*([^-+*/()]*,\s*+ end=+)+ contains=etchScopeDecl,etchType,etchStorageClass,@etchClasses
+  else
+    " This line catches method declarations at any indentation>0, but it assumes
+    " two things:
+    "   1. class names are always capitalized (ie: Button)
+    "   2. method names are never capitalized (except constructors, of course)
+    syn region etchFuncDef start=+^\s\+\(\(void\|boolean\|enum\|object\|string\|byte\|short\|int\|long\|float\|double\|\([A-Za-z_][A-Za-z0-9_$]*\.\)*[A-Z][A-Za-z0-9_$]*\)\(<[^>]*>\)\=\(\[\]\)*\s\+[a-z][A-Za-z0-9_$]*\|[A-Z][A-Za-z0-9_$]*\)\s*([^0-9]+ end=+)+ contains=etchType,etchComment,etchLineComment,@etchClasses
+  endif
+  syn match  etchBraces  "[{}]"
+  syn cluster etchTop add=etchFuncDef,etchBraces
+endif
+
+if exists("etch_highlight_debug")
+
+  " Strings and constants
+  syn match   etchDebugSpecial		contained "\\\d\d\d\|\\."
+  syn region  etchDebugString		contained start=+"+  end=+"+  contains=etchDebugSpecial
+  syn match   etchDebugStringError      +"\([^"\\]\|\\.\)*$+
+  syn match   etchDebugCharacter	contained "'[^\\]'"
+  syn match   etchDebugSpecialCharacter contained "'\\.'"
+  syn match   etchDebugSpecialCharacter contained "'\\''"
+  syn match   etchDebugNumber		contained "\<\(0[0-7]*\|0[xX]\x\+\|\d\+\)[lL]\=\>"
+  syn match   etchDebugNumber		contained "\(\<\d\+\.\d*\|\.\d\+\)\([eE][-+]\=\d\+\)\=[fFdD]\="
+  syn match   etchDebugNumber		contained "\<\d\+[eE][-+]\=\d\+[fFdD]\=\>"
+  syn match   etchDebugNumber		contained "\<\d\+\([eE][-+]\=\d\+\)\=[fFdD]\>"
+  syn keyword etchDebugBoolean		contained true false
+  syn keyword etchDebugType		contained null this super
+  syn region etchDebugParen  start=+(+ end=+)+ contained contains=etchDebug.*,etchDebugParen
+
+  " to make this work you must define the highlighting for these groups
+  syn match etchDebug "\<System\.\(out\|err\)\.print\(ln\)*\s*("me=e-1 contains=etchDebug.* nextgroup=etchDebugParen
+  syn match etchDebug "\<p\s*("me=e-1 contains=etchDebug.* nextgroup=etchDebugParen
+  syn match etchDebug "[A-Za-z][a-zA-Z0-9_]*\.printStackTrace\s*("me=e-1 contains=etchDebug.* nextgroup=etchDebugParen
+  syn match etchDebug "\<trace[SL]\=\s*("me=e-1 contains=etchDebug.* nextgroup=etchDebugParen
+
+  syn cluster etchTop add=etchDebug
+
+  if version >= 508 || !exists("did_c_syn_inits")
+    EtchHiLink etchDebug		 Debug
+    EtchHiLink etchDebugString		 DebugString
+    EtchHiLink etchDebugStringError	 etchError
+    EtchHiLink etchDebugType		 DebugType
+    EtchHiLink etchDebugBoolean		 DebugBoolean
+    EtchHiLink etchDebugNumber		 Debug
+    EtchHiLink etchDebugSpecial		 DebugSpecial
+    EtchHiLink etchDebugSpecialCharacter DebugSpecial
+    EtchHiLink etchDebugCharacter	 DebugString
+    EtchHiLink etchDebugParen		 Debug
+
+    EtchHiLink DebugString		 String
+    EtchHiLink DebugSpecial		 Special
+    EtchHiLink DebugBoolean		 Boolean
+    EtchHiLink DebugType		 Type
+  endif
+endif
+
+if exists("etch_mark_braces_in_parens_as_errors")
+  syn match etchInParen		 contained "[{}]"
+  EtchHiLink etchInParen	etchError
+  syn cluster etchTop add=etchInParen
+endif
+
+" catch errors caused by wrong parenthesis
+syn region  etchParenT  transparent matchgroup=etchParen  start="("  end=")" contains=@etchTop,etchParenT1
+syn region  etchParenT1 transparent matchgroup=etchParen1 start="(" end=")" contains=@etchTop,etchParenT2 contained
+syn region  etchParenT2 transparent matchgroup=etchParen2 start="(" end=")" contains=@etchTop,etchParenT  contained
+syn match   etchParenError       ")"
+" catch errors caused by wrong square parenthesis
+syn region  etchParenT  transparent matchgroup=etchParen  start="\["  end="\]" contains=@etchTop,etchParenT1
+syn region  etchParenT1 transparent matchgroup=etchParen1 start="\[" end="\]" contains=@etchTop,etchParenT2 contained
+syn region  etchParenT2 transparent matchgroup=etchParen2 start="\[" end="\]" contains=@etchTop,etchParenT  contained
+syn match   etchParenError       "\]"
+
+EtchHiLink etchParenError       etchError
+
+if !exists("etch_minlines")
+  let etch_minlines = 10
+endif
+exec "syn sync ccomment etchComment minlines=" . etch_minlines
+
+" The default highlighting.
+if version >= 508 || !exists("did_etch_syn_inits")
+  if version < 508
+    let did_etch_syn_inits = 1
+  endif
+  EtchHiLink etchFuncDef		Function
+  EtchHiLink etchVarArg                 Function
+  EtchHiLink etchBraces			Function
+  EtchHiLink etchBranch			Conditional
+  EtchHiLink etchUserLabelRef		etchUserLabel
+  EtchHiLink etchLabel			Label
+  EtchHiLink etchUserLabel		Label
+  EtchHiLink etchExceptions		Exception
+  EtchHiLink etchMethodDecl		etchStorageClass
+  EtchHiLink etchBoolean		Boolean
+  EtchHiLink etchSpecial		Special
+  EtchHiLink etchSpecialError		Error
+  EtchHiLink etchSpecialCharError	Error
+  EtchHiLink etchString			String
+  EtchHiLink etchCharacter		Character
+  EtchHiLink etchSpecialChar		SpecialChar
+  EtchHiLink etchNumber			Number
+  EtchHiLink etchError			Error
+  EtchHiLink etchStringError		Error
+  EtchHiLink etchStatement		Statement
+  EtchHiLink etchOperator		Operator
+  EtchHiLink etchComment		Comment
+  EtchHiLink etchDocComment		Comment
+  EtchHiLink etchLineComment		Comment
+  EtchHiLink etchConstant		Constant
+  EtchHiLink etchTypedef		Typedef
+  EtchHiLink etchTodo			Todo
+  EtchHiLink etchAnnotation             PreProc
+
+  EtchHiLink etchCommentTitle		SpecialComment
+  EtchHiLink etchDocTags		Special
+  EtchHiLink etchDocParam		Function
+  EtchHiLink etchDocSeeTagParam		Function
+  EtchHiLink etchCommentStar		etchComment
+
+  EtchHiLink etchType			Type
+  EtchHiLink etchExternal		Include
+
+  EtchHiLink htmlComment		Special
+  EtchHiLink htmlCommentPart		Special
+  EtchHiLink etchSpaceError		Error
+endif
+
+delcommand EtchHiLink
+
+let b:current_syntax = "etch"
+
+if main_syntax == 'etch'
+  unlet main_syntax
+endif
+
+let b:spell_options="contained"
+
+" vim: ts=8
diff --git a/plugins/visualstudio-addin/etch-addin/AssemblyInfo.cs b/plugins/visualstudio-addin/etch-addin/AssemblyInfo.cs
new file mode 100644
index 0000000..7d4c379
--- /dev/null
+++ b/plugins/visualstudio-addin/etch-addin/AssemblyInfo.cs
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *

+// or more contributor license agreements.  See the NOTICE file *

+// distributed with this work for additional information        *

+// regarding copyright ownership.  The ASF licenses this file   *

+// to you under the Apache License, Version 2.0 (the            *

+// "License"); you may not use this file except in compliance   *

+// with the License.  You may obtain a copy of the License at   *

+//                                                              *

+//   http://www.apache.org/licenses/LICENSE-2.0                 *

+//                                                              *

+// Unless required by applicable law or agreed to in writing,   *

+// software distributed under the License is distributed on an  *

+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+// KIND, either express or implied.  See the License for the    *

+// specific language governing permissions and limitations      *

+// under the License.                                           *

+using System.Reflection;

+using System.Runtime.CompilerServices;

+

+//

+// General Information about an assembly is controlled through the following 

+// set of attributes. Change these attribute values to modify the information

+// associated with an assembly.

+//

+[assembly: AssemblyTitle("Visual Studio Plugin For Etch")]

+[assembly: AssemblyDescription("Visual Studio Plugin For Etch")]

+[assembly: AssemblyConfiguration("")]

+[assembly: AssemblyCompany("Cisco Systems, Inc")]

+[assembly: AssemblyProduct("Etch")]

+[assembly: AssemblyCopyright("Copyright © Cisco Systems 2008")]

+[assembly: AssemblyTrademark("")]

+[assembly: AssemblyCulture("")]

+

+//

+// Version information for an assembly consists of the following four values:

+//

+//      Major Version

+//      Minor Version 

+//      Revision

+//      Build Number

+//

+// You can specify all the value or you can default the Revision and Build Numbers 

+// by using the '*' as shown below:

+

+[assembly: AssemblyVersion("1.0.*")]

+

+//

+// In order to sign your assembly you must specify a key to use. Refer to the 

+// Microsoft .NET Framework documentation for more information on assembly signing.

+//

+// Use the attributes below to control which key is used for signing. 

+//

+// Notes: 

+//   (*) If no key is specified - the assembly cannot be signed.

+//   (*) KeyName refers to a key that has been installed in the Crypto Service

+//       Provider (CSP) on your machine. 

+//   (*) If the key file and a key name attributes are both specified, the 

+//       following processing occurs:

+//       (1) If the KeyName can be found in the CSP - that key is used.

+//       (2) If the KeyName does not exist and the KeyFile does exist, the key 

+//           in the file is installed into the CSP and used.

+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework

+//       documentation for more information on this.

+//

+[assembly: AssemblyDelaySign(false)]

+[assembly: AssemblyKeyFile("")]

+[assembly: AssemblyKeyName("")]

diff --git a/plugins/visualstudio-addin/etch-addin/CommandBar.resx b/plugins/visualstudio-addin/etch-addin/CommandBar.resx
new file mode 100644
index 0000000..e4f12a7
--- /dev/null
+++ b/plugins/visualstudio-addin/etch-addin/CommandBar.resx
@@ -0,0 +1,1032 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+ <root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="enAction" xml:space="preserve">
+    <value>Action</value>
+  </data>
+  <data name="enAddins" xml:space="preserve">
+    <value>Addins</value>
+  </data>
+  <data name="enBuild" xml:space="preserve">
+    <value>Build</value>
+  </data>
+  <data name="enClass Diagram" xml:space="preserve">
+    <value>Class Diagram</value>
+  </data>
+  <data name="enCommunity" xml:space="preserve">
+    <value>Community</value>
+  </data>
+  <data name="enData" xml:space="preserve">
+    <value>Data</value>
+  </data>
+  <data name="enDatabase" xml:space="preserve">
+    <value>Database</value>
+  </data>
+  <data name="enDatabase Diagram" xml:space="preserve">
+    <value>Database Diagram</value>
+  </data>
+  <data name="enDebug" xml:space="preserve">
+    <value>Debug</value>
+  </data>
+  <data name="enDiagram" xml:space="preserve">
+    <value>Diagram</value>
+  </data>
+  <data name="enEdit" xml:space="preserve">
+    <value>Edit</value>
+  </data>
+  <data name="enFile" xml:space="preserve">
+    <value>File</value>
+  </data>
+  <data name="enFormat" xml:space="preserve">
+    <value>Format</value>
+  </data>
+  <data name="enFrames" xml:space="preserve">
+    <value>Frames</value>
+  </data>
+  <data name="enHelp" xml:space="preserve">
+    <value>Help</value>
+  </data>
+  <data name="enImage" xml:space="preserve">
+    <value>Image</value>
+  </data>
+  <data name="enLayout" xml:space="preserve">
+    <value>Layout</value>
+  </data>
+  <data name="enMacros" xml:space="preserve">
+    <value>Macros</value>
+  </data>
+  <data name="enProject" xml:space="preserve">
+    <value>Project</value>
+  </data>
+  <data name="enQuery" xml:space="preserve">
+    <value>Query</value>
+  </data>
+  <data name="enQuery Designer" xml:space="preserve">
+    <value>Query Designer</value>
+  </data>
+  <data name="enRefactor" xml:space="preserve">
+    <value>Refactor</value>
+  </data>
+  <data name="enResources" xml:space="preserve">
+    <value>Resources</value>
+  </data>
+  <data name="enSchema" xml:space="preserve">
+    <value>Schema</value>
+  </data>
+  <data name="enStyles" xml:space="preserve">
+    <value>Styles</value>
+  </data>
+  <data name="enTeam" xml:space="preserve">
+    <value>Team</value>
+  </data>
+  <data name="enTable" xml:space="preserve">
+    <value>Table</value>
+  </data>
+  <data name="enTable Designer" xml:space="preserve">
+    <value>Table Designer</value>
+  </data>
+  <data name="enTest" xml:space="preserve">
+    <value>Test</value>
+  </data>
+  <data name="enTools" xml:space="preserve">
+    <value>Tools</value>
+  </data>
+  <data name="enView" xml:space="preserve">
+    <value>View</value>
+  </data>
+  <data name="enWindow" xml:space="preserve">
+    <value>Window</value>
+  </data>
+  <data name="enXML" xml:space="preserve">
+    <value>XML</value>
+  </data>
+  <data name="jaAction" xml:space="preserve">
+    <value>操作</value>
+  </data>
+  <data name="jaAddins" xml:space="preserve">
+    <value>アドイン</value>
+  </data>
+  <data name="jaBuild" xml:space="preserve">
+    <value>ビルド</value>
+  </data>
+  <data name="jaClass Diagram" xml:space="preserve">
+    <value>クラス ダイアグラム</value>
+  </data>
+  <data name="jaCommunity" xml:space="preserve">
+    <value>コミュニティ</value>
+  </data>
+  <data name="jaData" xml:space="preserve">
+    <value>データ</value>
+  </data>
+  <data name="jaDatabase" xml:space="preserve">
+    <value>データベース</value>
+  </data>
+  <data name="jaDatabase Diagram" xml:space="preserve">
+    <value>データベース ダイアグラム</value>
+  </data>
+  <data name="jaDebug" xml:space="preserve">
+    <value>デバッグ</value>
+  </data>
+  <data name="jaDiagram" xml:space="preserve">
+    <value>ダイアグラム</value>
+  </data>
+  <data name="jaEdit" xml:space="preserve">
+    <value>編集</value>
+  </data>
+  <data name="jaFile" xml:space="preserve">
+    <value>ファイル</value>
+  </data>
+  <data name="jaFormat" xml:space="preserve">
+    <value>書式</value>
+  </data>
+  <data name="jaFrames" xml:space="preserve">
+    <value>フレーム</value>
+  </data>
+  <data name="jaHelp" xml:space="preserve">
+    <value>ヘルプ</value>
+  </data>
+  <data name="jaImage" xml:space="preserve">
+    <value>イメージ</value>
+  </data>
+  <data name="jaLayout" xml:space="preserve">
+    <value>レイアウト</value>
+  </data>
+  <data name="jaMacros" xml:space="preserve">
+    <value>マクロ</value>
+  </data>
+  <data name="jaProject" xml:space="preserve">
+    <value>プロジェクト</value>
+  </data>
+  <data name="jaQuery" xml:space="preserve">
+    <value>クエリ</value>
+  </data>
+  <data name="jaQuery Designer" xml:space="preserve">
+    <value>クエリ デザイナ</value>
+  </data>
+  <data name="jaRefactor" xml:space="preserve">
+    <value>リファクタ</value>
+  </data>
+  <data name="jaResources" xml:space="preserve">
+    <value>リソース</value>
+  </data>
+  <data name="jaSchema" xml:space="preserve">
+    <value>スキーマ</value>
+  </data>
+  <data name="jaStyles" xml:space="preserve">
+    <value>スタイル</value>
+  </data>
+  <data name="jaTeam" xml:space="preserve">
+    <value>チーム</value>
+  </data>
+  <data name="jaTable" xml:space="preserve">
+    <value>テーブル</value>
+  </data>
+  <data name="jaTable Designer" xml:space="preserve">
+    <value>テーブル デザイナ</value>
+  </data>
+  <data name="jaTest" xml:space="preserve">
+    <value>テスト</value>
+  </data>
+  <data name="jaTools" xml:space="preserve">
+    <value>ツール</value>
+  </data>
+  <data name="jaView" xml:space="preserve">
+    <value>表示</value>
+  </data>
+  <data name="jaWindow" xml:space="preserve">
+    <value>ウィンドウ</value>
+  </data>
+  <data name="jaXML" xml:space="preserve">
+    <value>XML</value>
+  </data>
+  <data name="deAction" xml:space="preserve">
+    <value>Aktion</value>
+  </data>
+  <data name="deAddins" xml:space="preserve">
+    <value>Add-Ins</value>
+  </data>
+  <data name="deBuild" xml:space="preserve">
+    <value>Erstellen</value>
+  </data>
+  <data name="deClass Diagram" xml:space="preserve">
+    <value>Klassendiagramm</value>
+  </data>
+  <data name="deCommunity" xml:space="preserve">
+    <value>Community</value>
+  </data>
+  <data name="deData" xml:space="preserve">
+    <value>Daten</value>
+  </data>
+  <data name="deDatabase" xml:space="preserve">
+    <value>Datenbank</value>
+  </data>
+  <data name="deDatabase Diagram" xml:space="preserve">
+    <value>Datenbankdiagramm</value>
+  </data>
+  <data name="deDebug" xml:space="preserve">
+    <value>Debuggen</value>
+  </data>
+  <data name="deDiagram" xml:space="preserve">
+    <value>Diagramm</value>
+  </data>
+  <data name="deEdit" xml:space="preserve">
+    <value>Bearbeiten</value>
+  </data>
+  <data name="deFile" xml:space="preserve">
+    <value>Datei</value>
+  </data>
+  <data name="deFormat" xml:space="preserve">
+    <value>Format</value>
+  </data>
+  <data name="deFrames" xml:space="preserve">
+    <value>Rahmen</value>
+  </data>
+  <data name="deHelp" xml:space="preserve">
+    <value>Hilfe</value>
+  </data>
+  <data name="deImage" xml:space="preserve">
+    <value>Bild</value>
+  </data>
+  <data name="deLayout" xml:space="preserve">
+    <value>Layout</value>
+  </data>
+  <data name="deMacros" xml:space="preserve">
+    <value>Makros</value>
+  </data>
+  <data name="deProject" xml:space="preserve">
+    <value>Projekt</value>
+  </data>
+  <data name="deQuery" xml:space="preserve">
+    <value>Query</value>
+  </data>
+  <data name="deQuery Designer" xml:space="preserve">
+    <value>Abfrage-Designer</value>
+  </data>
+  <data name="deRefactor" xml:space="preserve">
+    <value>Umgestalten</value>
+  </data>
+  <data name="deResources" xml:space="preserve">
+    <value>Ressourcen</value>
+  </data>
+  <data name="deSchema" xml:space="preserve">
+    <value>Schema</value>
+  </data>
+  <data name="deStyles" xml:space="preserve">
+    <value>Formate</value>
+  </data>
+  <data name="deTeam" xml:space="preserve">
+    <value>Team</value>
+  </data>
+  <data name="deTable" xml:space="preserve">
+    <value>Tabelle</value>
+  </data>
+  <data name="deTable Designer" xml:space="preserve">
+    <value>Tabellen-Designer</value>
+  </data>
+  <data name="deTest" xml:space="preserve">
+    <value>Testen</value>
+  </data>
+  <data name="deTools" xml:space="preserve">
+    <value>Extras</value>
+  </data>
+  <data name="deView" xml:space="preserve">
+    <value>Ansicht</value>
+  </data>
+  <data name="deWindow" xml:space="preserve">
+    <value>Fenster</value>
+  </data>
+  <data name="deXML" xml:space="preserve">
+    <value>XML</value>
+  </data>
+  <data name="esAction" xml:space="preserve">
+    <value>Acción</value>
+  </data>
+  <data name="esAddins" xml:space="preserve">
+    <value>Complementos</value>
+  </data>
+  <data name="esBuild" xml:space="preserve">
+    <value>Generar</value>
+  </data>
+  <data name="esClass Diagram" xml:space="preserve">
+    <value>Diagrama de clase</value>
+  </data>
+  <data name="esCommunity" xml:space="preserve">
+    <value>Comunidad</value>
+  </data>
+  <data name="esData" xml:space="preserve">
+    <value>Datos</value>
+  </data>
+  <data name="esDatabase" xml:space="preserve">
+    <value>Base de datos</value>
+  </data>
+  <data name="esDatabase Diagram" xml:space="preserve">
+    <value>Diagrama de base de datos</value>
+  </data>
+  <data name="esDebug" xml:space="preserve">
+    <value>Depurar</value>
+  </data>
+  <data name="esDiagram" xml:space="preserve">
+    <value>Diagrama</value>
+  </data>
+  <data name="esEdit" xml:space="preserve">
+    <value>Editar</value>
+  </data>
+  <data name="esFile" xml:space="preserve">
+    <value>Archivo</value>
+  </data>
+  <data name="esFormat" xml:space="preserve">
+    <value>Formato</value>
+  </data>
+  <data name="esFrames" xml:space="preserve">
+    <value>Marcos</value>
+  </data>
+  <data name="esHelp" xml:space="preserve">
+    <value>Ayuda</value>
+  </data>
+  <data name="esImage" xml:space="preserve">
+    <value>Imagen</value>
+  </data>
+  <data name="esLayout" xml:space="preserve">
+    <value>Diseño</value>
+  </data>
+  <data name="esMacros" xml:space="preserve">
+    <value>Macros</value>
+  </data>
+  <data name="esProject" xml:space="preserve">
+    <value>Proyecto</value>
+  </data>
+  <data name="esQuery" xml:space="preserve">
+    <value>Consulta</value>
+  </data>
+  <data name="esQuery Designer" xml:space="preserve">
+    <value>Diseñador de consultas</value>
+  </data>
+  <data name="esRefactor" xml:space="preserve">
+    <value>Refactorizar</value>
+  </data>
+  <data name="esResources" xml:space="preserve">
+    <value>Recursos</value>
+  </data>
+  <data name="esSchema" xml:space="preserve">
+    <value>Esquema</value>
+  </data>
+  <data name="esStyles" xml:space="preserve">
+    <value>Estilos</value>
+  </data>
+  <data name="esTeam" xml:space="preserve">
+    <value>Equipo</value>
+  </data>
+  <data name="esTable" xml:space="preserve">
+    <value>Tabla</value>
+  </data>
+  <data name="esTable Designer" xml:space="preserve">
+    <value>Diseñador de tablas</value>
+  </data>
+  <data name="esTest" xml:space="preserve">
+    <value>Prueba</value>
+  </data>
+  <data name="esTools" xml:space="preserve">
+    <value>Herramientas</value>
+  </data>
+  <data name="esView" xml:space="preserve">
+    <value>Ver</value>
+  </data>
+  <data name="esWindow" xml:space="preserve">
+    <value>Ventana</value>
+  </data>
+  <data name="esXML" xml:space="preserve">
+    <value>XML</value>
+  </data>
+  <data name="frAction" xml:space="preserve">
+    <value>Action</value>
+  </data>
+  <data name="frAddins" xml:space="preserve">
+    <value>Compléments</value>
+  </data>
+  <data name="frBuild" xml:space="preserve">
+    <value>Générer</value>
+  </data>
+  <data name="frClass Diagram" xml:space="preserve">
+    <value>Diagramme de classes</value>
+  </data>
+  <data name="frCommunity" xml:space="preserve">
+    <value>Communauté</value>
+  </data>
+  <data name="frData" xml:space="preserve">
+    <value>Données</value>
+  </data>
+  <data name="frDatabase" xml:space="preserve">
+    <value>Base de données</value>
+  </data>
+  <data name="frDatabase Diagram" xml:space="preserve">
+    <value>Schéma de base de données</value>
+  </data>
+  <data name="frDebug" xml:space="preserve">
+    <value>Déboguer</value>
+  </data>
+  <data name="frDiagram" xml:space="preserve">
+    <value>Schéma</value>
+  </data>
+  <data name="frEdit" xml:space="preserve">
+    <value>Modifier</value>
+  </data>
+  <data name="frFile" xml:space="preserve">
+    <value>Fichier</value>
+  </data>
+  <data name="frFormat" xml:space="preserve">
+    <value>Format</value>
+  </data>
+  <data name="frFrames" xml:space="preserve">
+    <value>Frames</value>
+  </data>
+  <data name="frHelp" xml:space="preserve">
+    <value>?</value>
+  </data>
+  <data name="frImage" xml:space="preserve">
+    <value>Image</value>
+  </data>
+  <data name="frLayout" xml:space="preserve">
+    <value>Disposition</value>
+  </data>
+  <data name="frMacros" xml:space="preserve">
+    <value>Macros</value>
+  </data>
+  <data name="frProject" xml:space="preserve">
+    <value>Projet</value>
+  </data>
+  <data name="frQuery" xml:space="preserve">
+    <value>Requête</value>
+  </data>
+  <data name="frQuery Designer" xml:space="preserve">
+    <value>Concepteur de requêtes</value>
+  </data>
+  <data name="frRefactor" xml:space="preserve">
+    <value>Refactoriser</value>
+  </data>
+  <data name="frResources" xml:space="preserve">
+    <value>Ressources</value>
+  </data>
+  <data name="frSchema" xml:space="preserve">
+    <value>Schéma</value>
+  </data>
+  <data name="frStyles" xml:space="preserve">
+    <value>Styles</value>
+  </data>
+  <data name="frTeam" xml:space="preserve">
+    <value>équipe</value>
+  </data>
+  <data name="frTable" xml:space="preserve">
+    <value>Tableau</value>
+  </data>
+  <data name="frTable Designer" xml:space="preserve">
+    <value>Concepteur de tables</value>
+  </data>
+  <data name="frTest" xml:space="preserve">
+    <value>Test</value>
+  </data>
+  <data name="frTools" xml:space="preserve">
+    <value>Outils</value>
+  </data>
+  <data name="frView" xml:space="preserve">
+    <value>Affichage</value>
+  </data>
+  <data name="frWindow" xml:space="preserve">
+    <value>Fenêtre</value>
+  </data>
+  <data name="frXML" xml:space="preserve">
+    <value>XML</value>
+  </data>
+  <data name="itAction" xml:space="preserve">
+    <value>Azione</value>
+  </data>
+  <data name="itAddins" xml:space="preserve">
+    <value>Componenti aggiuntivi</value>
+  </data>
+  <data name="itBuild" xml:space="preserve">
+    <value>Genera</value>
+  </data>
+  <data name="itClass Diagram" xml:space="preserve">
+    <value>Diagramma classi</value>
+  </data>
+  <data name="itCommunity" xml:space="preserve">
+    <value>Comunità</value>
+  </data>
+  <data name="itData" xml:space="preserve">
+    <value>Dati</value>
+  </data>
+  <data name="itDatabase" xml:space="preserve">
+    <value>Database</value>
+  </data>
+  <data name="itDatabase Diagram" xml:space="preserve">
+    <value>Diagramma database</value>
+  </data>
+  <data name="itDebug" xml:space="preserve">
+    <value>Debug</value>
+  </data>
+  <data name="itDiagram" xml:space="preserve">
+    <value>Diagramma</value>
+  </data>
+  <data name="itEdit" xml:space="preserve">
+    <value>Modifica</value>
+  </data>
+  <data name="itFile" xml:space="preserve">
+    <value>File</value>
+  </data>
+  <data name="itFormat" xml:space="preserve">
+    <value>Formato</value>
+  </data>
+  <data name="itFrames" xml:space="preserve">
+    <value>Frame</value>
+  </data>
+  <data name="itHelp" xml:space="preserve">
+    <value>?</value>
+  </data>
+  <data name="itImage" xml:space="preserve">
+    <value>Immagine</value>
+  </data>
+  <data name="itLayout" xml:space="preserve">
+    <value>Layout</value>
+  </data>
+  <data name="itMacros" xml:space="preserve">
+    <value>Macro</value>
+  </data>
+  <data name="itProject" xml:space="preserve">
+    <value>Progetto</value>
+  </data>
+  <data name="itQuery" xml:space="preserve">
+    <value>Query</value>
+  </data>
+  <data name="itQuery Designer" xml:space="preserve">
+    <value>Progettazione query</value>
+  </data>
+  <data name="itRefactor" xml:space="preserve">
+    <value>Effettua refactoring</value>
+  </data>
+  <data name="itResources" xml:space="preserve">
+    <value>Risorse</value>
+  </data>
+  <data name="itSchema" xml:space="preserve">
+    <value>Schema</value>
+  </data>
+  <data name="itStyles" xml:space="preserve">
+    <value>Stili</value>
+  </data>
+  <data name="itTeam" xml:space="preserve">
+    <value>Team</value>
+  </data>
+  <data name="itTable" xml:space="preserve">
+    <value>Tabella</value>
+  </data>
+  <data name="itTable Designer" xml:space="preserve">
+    <value>Progettazione tabelle</value>
+  </data>
+  <data name="itTest" xml:space="preserve">
+    <value>Prova</value>
+  </data>
+  <data name="itTools" xml:space="preserve">
+    <value>Strumenti</value>
+  </data>
+  <data name="itView" xml:space="preserve">
+    <value>Visualizza</value>
+  </data>
+  <data name="itWindow" xml:space="preserve">
+    <value>Finestra</value>
+  </data>
+  <data name="itXML" xml:space="preserve">
+    <value>XML</value>
+  </data>
+  <data name="koAction" xml:space="preserve">
+    <value>작업</value>
+  </data>
+  <data name="koAddins" xml:space="preserve">
+    <value>추가 기능</value>
+  </data>
+  <data name="koBuild" xml:space="preserve">
+    <value>빌드</value>
+  </data>
+  <data name="koClass Diagram" xml:space="preserve">
+    <value>클래스 다이어그램</value>
+  </data>
+  <data name="koCommunity" xml:space="preserve">
+    <value>커뮤니티</value>
+  </data>
+  <data name="koData" xml:space="preserve">
+    <value>데이터</value>
+  </data>
+  <data name="koDatabase" xml:space="preserve">
+    <value>데이터베이스</value>
+  </data>
+  <data name="koDatabase Diagram" xml:space="preserve">
+    <value>데이터베이스 다이어그램</value>
+  </data>
+  <data name="koDebug" xml:space="preserve">
+    <value>디버그</value>
+  </data>
+  <data name="koDiagram" xml:space="preserve">
+    <value>다이어그램</value>
+  </data>
+  <data name="koEdit" xml:space="preserve">
+    <value>편집</value>
+  </data>
+  <data name="koFile" xml:space="preserve">
+    <value>파일</value>
+  </data>
+  <data name="koFormat" xml:space="preserve">
+    <value>서식</value>
+  </data>
+  <data name="koFrames" xml:space="preserve">
+    <value>프레임</value>
+  </data>
+  <data name="koHelp" xml:space="preserve">
+    <value>도움말</value>
+  </data>
+  <data name="koImage" xml:space="preserve">
+    <value>이미지</value>
+  </data>
+  <data name="koLayout" xml:space="preserve">
+    <value>레이아웃</value>
+  </data>
+  <data name="koMacros" xml:space="preserve">
+    <value>매크로</value>
+  </data>
+  <data name="koProject" xml:space="preserve">
+    <value>프로젝트</value>
+  </data>
+  <data name="koQuery" xml:space="preserve">
+    <value>쿼리</value>
+  </data>
+  <data name="koQuery Designer" xml:space="preserve">
+    <value>쿼리 디자이너</value>
+  </data>
+  <data name="koRefactor" xml:space="preserve">
+    <value>리팩터링</value>
+  </data>
+  <data name="koResources" xml:space="preserve">
+    <value>리소스</value>
+  </data>
+  <data name="koSchema" xml:space="preserve">
+    <value>스키마</value>
+  </data>
+  <data name="koStyles" xml:space="preserve">
+    <value>스타일</value>
+  </data>
+  <data name="koTeam" xml:space="preserve">
+    <value>팀</value>
+  </data>
+  <data name="koTable" xml:space="preserve">
+    <value>테이블</value>
+  </data>
+  <data name="koTable Designer" xml:space="preserve">
+    <value>테이블 디자이너</value>
+  </data>
+  <data name="koTest" xml:space="preserve">
+    <value>테스트</value>
+  </data>
+  <data name="koTools" xml:space="preserve">
+    <value>도구</value>
+  </data>
+  <data name="koView" xml:space="preserve">
+    <value>뷰</value>
+  </data>
+  <data name="koWindow" xml:space="preserve">
+    <value>창</value>
+  </data>
+  <data name="koXML" xml:space="preserve">
+    <value>XML</value>
+  </data>
+  <data name="zh-CHSAction" xml:space="preserve">
+    <value>操作</value>
+  </data>
+  <data name="zh-CHSAddins" xml:space="preserve">
+    <value>外接程序</value>
+  </data>
+  <data name="zh-CHSBuild" xml:space="preserve">
+    <value>生成</value>
+  </data>
+  <data name="zh-CHSClass Diagram" xml:space="preserve">
+    <value>类关系图</value>
+  </data>
+  <data name="zh-CHSCommunity" xml:space="preserve">
+    <value>社区</value>
+  </data>
+  <data name="zh-CHSData" xml:space="preserve">
+    <value>数据</value>
+  </data>
+  <data name="zh-CHSDatabase" xml:space="preserve">
+    <value>数据库</value>
+  </data>
+  <data name="zh-CHSDatabase Diagram" xml:space="preserve">
+    <value>数据库关系图</value>
+  </data>
+  <data name="zh-CHSDebug" xml:space="preserve">
+    <value>调试</value>
+  </data>
+  <data name="zh-CHSDiagram" xml:space="preserve">
+    <value>关系图</value>
+  </data>
+  <data name="zh-CHSEdit" xml:space="preserve">
+    <value>编辑</value>
+  </data>
+  <data name="zh-CHSFile" xml:space="preserve">
+    <value>文件</value>
+  </data>
+  <data name="zh-CHSFormat" xml:space="preserve">
+    <value>格式</value>
+  </data>
+  <data name="zh-CHSFrames" xml:space="preserve">
+    <value>框架</value>
+  </data>
+  <data name="zh-CHSHelp" xml:space="preserve">
+    <value>帮助</value>
+  </data>
+  <data name="zh-CHSImage" xml:space="preserve">
+    <value>图像</value>
+  </data>
+  <data name="zh-CHSLayout" xml:space="preserve">
+    <value>布局</value>
+  </data>
+  <data name="zh-CHSMacros" xml:space="preserve">
+    <value>宏</value>
+  </data>
+  <data name="zh-CHSProject" xml:space="preserve">
+    <value>项目</value>
+  </data>
+  <data name="zh-CHSQuery" xml:space="preserve">
+    <value>查询</value>
+  </data>
+  <data name="zh-CHSQuery Designer" xml:space="preserve">
+    <value>查询设计器</value>
+  </data>
+  <data name="zh-CHSRefactor" xml:space="preserve">
+    <value>重构</value>
+  </data>
+  <data name="zh-CHSResources" xml:space="preserve">
+    <value>资源</value>
+  </data>
+  <data name="zh-CHSSchema" xml:space="preserve">
+    <value>架构</value>
+  </data>
+  <data name="zh-CHSStyles" xml:space="preserve">
+    <value>样式</value>
+  </data>
+  <data name="zh-CHSTeam" xml:space="preserve">
+    <value>工作组</value>
+  </data>
+  <data name="zh-CHSTable" xml:space="preserve">
+    <value>表</value>
+  </data>
+  <data name="zh-CHSTable Designer" xml:space="preserve">
+    <value>表设计器</value>
+  </data>
+  <data name="zh-CHSTest" xml:space="preserve">
+    <value>测试</value>
+  </data>
+  <data name="zh-CHSTools" xml:space="preserve">
+    <value>工具</value>
+  </data>
+  <data name="zh-CHSView" xml:space="preserve">
+    <value>视图</value>
+  </data>
+  <data name="zh-CHSWindow" xml:space="preserve">
+    <value>窗口</value>
+  </data>
+  <data name="zh-CHSXML" xml:space="preserve">
+    <value>XML</value>
+  </data>
+  <data name="zh-CHTAction" xml:space="preserve">
+    <value>動作</value>
+  </data>
+  <data name="zh-CHTAddins" xml:space="preserve">
+    <value>增益集</value>
+  </data>
+  <data name="zh-CHTBuild" xml:space="preserve">
+    <value>建置</value>
+  </data>
+  <data name="zh-CHTClass Diagram" xml:space="preserve">
+    <value>類別圖表</value>
+  </data>
+  <data name="zh-CHTCommunity" xml:space="preserve">
+    <value>社群</value>
+  </data>
+  <data name="zh-CHTData" xml:space="preserve">
+    <value>資料</value>
+  </data>
+  <data name="zh-CHTDatabase" xml:space="preserve">
+    <value>資料庫</value>
+  </data>
+  <data name="zh-CHTDatabase Diagram" xml:space="preserve">
+    <value>資料庫圖表</value>
+  </data>
+  <data name="zh-CHTDebug" xml:space="preserve">
+    <value>偵錯</value>
+  </data>
+  <data name="zh-CHTDiagram" xml:space="preserve">
+    <value>圖表</value>
+  </data>
+  <data name="zh-CHTEdit" xml:space="preserve">
+    <value>編輯</value>
+  </data>
+  <data name="zh-CHTFile" xml:space="preserve">
+    <value>檔案</value>
+  </data>
+  <data name="zh-CHTFormat" xml:space="preserve">
+    <value>格式</value>
+  </data>
+  <data name="zh-CHTFrames" xml:space="preserve">
+    <value>框架</value>
+  </data>
+  <data name="zh-CHTHelp" xml:space="preserve">
+    <value>說明</value>
+  </data>
+  <data name="zh-CHTImage" xml:space="preserve">
+    <value>影像</value>
+  </data>
+  <data name="zh-CHTLayout" xml:space="preserve">
+    <value>配置</value>
+  </data>
+  <data name="zh-CHTMacros" xml:space="preserve">
+    <value>巨集</value>
+  </data>
+  <data name="zh-CHTProject" xml:space="preserve">
+    <value>專案</value>
+  </data>
+  <data name="zh-CHTQuery" xml:space="preserve">
+    <value>查詢</value>
+  </data>
+  <data name="zh-CHTQuery Designer" xml:space="preserve">
+    <value>查詢設計工具</value>
+  </data>
+  <data name="zh-CHTRefactor" xml:space="preserve">
+    <value>重整</value>
+  </data>
+  <data name="zh-CHTResources" xml:space="preserve">
+    <value>資源</value>
+  </data>
+  <data name="zh-CHTSchema" xml:space="preserve">
+    <value>結構描述</value>
+  </data>
+  <data name="zh-CHTStyles" xml:space="preserve">
+    <value>樣式</value>
+  </data>
+  <data name="zh-CHTTeam" xml:space="preserve">
+    <value>小組</value>
+  </data>
+  <data name="zh-CHTTable" xml:space="preserve">
+    <value>資料表</value>
+  </data>
+  <data name="zh-CHTTable Designer" xml:space="preserve">
+    <value>資料表設計工具</value>
+  </data>
+  <data name="zh-CHTTest" xml:space="preserve">
+    <value>測試</value>
+  </data>
+  <data name="zh-CHTTools" xml:space="preserve">
+    <value>工具</value>
+  </data>
+  <data name="zh-CHTView" xml:space="preserve">
+    <value>檢視</value>
+  </data>
+  <data name="zh-CHTWindow" xml:space="preserve">
+    <value>視窗</value>
+  </data>
+  <data name="zh-CHTXML" xml:space="preserve">
+    <value>XML</value>
+  </data>
+  <data name="String1" xml:space="preserve">
+    <value>Hello</value>
+  </data>
+</root>
diff --git a/plugins/visualstudio-addin/etch-addin/Connect.cs b/plugins/visualstudio-addin/etch-addin/Connect.cs
new file mode 100644
index 0000000..de2b6b4
--- /dev/null
+++ b/plugins/visualstudio-addin/etch-addin/Connect.cs
@@ -0,0 +1,253 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Diagnostics;
+using Extensibility;
+using EnvDTE;
+using EnvDTE80;
+using Microsoft.VisualStudio.CommandBars;
+
+namespace Etch
+{
+	/// <summary>The object for implementing an Add-in.</summary>
+	/// <seealso class='IDTExtensibility2' />
+    public class Connect : IDTExtensibility2, IDTCommandTarget
+	{
+		/// <summary>Implements the constructor for the Add-in object. Place your initialization code within this method.</summary>
+		public Connect()
+		{
+		}
+
+        /// <summary>
+        /// FindNamedCommand
+        /// </summary>
+        /// <param name="commandName">command name of the addin</param>
+        /// <param name="command">the command to find</param>
+        /// <returns></returns>
+        public bool FindNamedCommand(string commandName, out Command command)
+        {
+            try
+            {
+                Commands commands = _applicationObject.Commands;
+                command = commands.Item(commandName, -1);
+                return true;
+            }
+            catch (System.Exception)
+            {
+            }
+            command = null;
+            return false;
+        }
+
+		/// <summary>Implements the OnConnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being loaded.</summary>
+		/// <param term='application'>Root object of the host application.</param>
+		/// <param term='connectMode'>Describes how the Add-in is being loaded.</param>
+		/// <param term='addInInst'>Object representing this Add-in.</param>
+		/// <seealso class='IDTExtensibility2' />
+		public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
+		{
+			_applicationObject = (DTE2)application;
+			_addInInstance = (AddIn)addInInst;
+
+            if (connectMode == Extensibility.ext_ConnectMode.ext_cm_Startup)
+            {
+                Command command, commandS, commandC, commandX;
+                CommandBar itemCmdBar;
+                object[] contextGUIDS = new object[] { };
+
+                try
+                {
+                    itemCmdBar = ((CommandBars)_applicationObject.CommandBars)["Item"];
+                    if (itemCmdBar == null)
+                    {
+                        System.Windows.Forms.MessageBox.Show("Cannot get Solution Explorer Item menubar", "Error",
+                            System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
+                    }
+                    else
+                    {
+                        // Create a Command with name Etch and then add it to the "Item" menubar for the SolutionExplorer
+                        if (!FindNamedCommand("Etch.Connect.Etch", out command))
+                        {
+                            command = _applicationObject.Commands.AddNamedCommand(_addInInstance, "Etch", "Etch (Both)", "Generate Etch bindings", true, 6, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled);
+                            CommandBarControl cb = command.AddControl(itemCmdBar, 4) as CommandBarControl;
+                            cb.BeginGroup = true;
+                        }
+                        if (!FindNamedCommand("Etch.Connect.EtchS", out commandS))
+                        {
+                            commandS = _applicationObject.Commands.AddNamedCommand(_addInInstance, "EtchS", "Etch (Server)", "Executes Etch server binding", true, 39, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled);
+                            commandS.AddControl(itemCmdBar, 5);
+                        }
+                        if (!FindNamedCommand("Etch.Connect.EtchC", out commandC))
+                        {
+                            commandC = _applicationObject.Commands.AddNamedCommand(_addInInstance, "EtchC", "Etch (Client)", "Executes Etch client binding", true, 41, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled);
+                            commandC.AddControl(itemCmdBar, 6);
+                        }
+                        /*
+                        if(!FindNamedCommand("Etch.Connect.EtchM", out commandM))
+                        {
+                            commandM = _applicationObject.Commands.AddNamedCommand(_addInInstance, "EtchM", "Etch Mixin (Both)", "Executes Etch Mixin bindings", true, 6, ref contextGUIDS, (int) vsCommandStatus.vsCommandStatusSupported + (int) vsCommandStatus.vsCommandStatusEnabled);
+                            commandM.AddControl(itemCmdBar, 7);
+                        }
+                        if(!FindNamedCommand("Etch.Connect.EtchMS", out commandMS))
+                        {
+                            commandMS = _applicationObject.Commands.AddNamedCommand(_addInInstance, "EtchMS", "Etch Mixin (Server)", "Executes Etch Mixin server binding", true, 39, ref contextGUIDS, (int) vsCommandStatus.vsCommandStatusSupported + (int) vsCommandStatus.vsCommandStatusEnabled);
+                            commandMS.AddControl(itemCmdBar, 8);
+                        }
+                        if(!FindNamedCommand("Etch.Connect.EtchMC", out commandMS))
+                        {
+                            commandMC = _applicationObject.Commands.AddNamedCommand(_addInInstance, "EtchMC", "Etch Mixin (Client)", "Executes Etch Mixin client binding", true, 41, ref contextGUIDS, (int) vsCommandStatus.vsCommandStatusSupported + (int) vsCommandStatus.vsCommandStatusEnabled);
+                            commandMC.AddControl(itemCmdBar, 9);
+                        }
+                        */ 
+                        if(!FindNamedCommand("Etch.Connect.EtchX", out commandX))
+                        {
+                            commandX = _applicationObject.Commands.AddNamedCommand(_addInInstance, "EtchX", "Etch (XML)", "Executes Etch XML binding", true, 6, ref contextGUIDS, (int) vsCommandStatus.vsCommandStatusSupported + (int) vsCommandStatus.vsCommandStatusEnabled);
+                            commandX.AddControl(itemCmdBar, 10);
+                        }
+                    }
+                }
+                catch (Exception ex)
+                {
+                    System.Windows.Forms.MessageBox.Show(ex.ToString(), "Error",
+                        System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
+                }
+            }			
+		}
+
+		/// <summary>Implements the OnDisconnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being unloaded.</summary>
+		/// <param term='disconnectMode'>Describes how the Add-in is being unloaded.</param>
+		/// <param term='custom'>Array of parameters that are host application specific.</param>
+		/// <seealso class='IDTExtensibility2' />
+		public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom)
+		{
+		}
+
+		/// <summary>Implements the OnAddInsUpdate method of the IDTExtensibility2 interface. Receives notification when the collection of Add-ins has changed.</summary>
+		/// <param term='custom'>Array of parameters that are host application specific.</param>
+		/// <seealso class='IDTExtensibility2' />		
+		public void OnAddInsUpdate(ref Array custom)
+		{
+		}
+
+		/// <summary>Implements the OnStartupComplete method of the IDTExtensibility2 interface. Receives notification that the host application has completed loading.</summary>
+		/// <param term='custom'>Array of parameters that are host application specific.</param>
+		/// <seealso class='IDTExtensibility2' />
+		public void OnStartupComplete(ref Array custom)
+		{
+		}
+
+		/// <summary>Implements the OnBeginShutdown method of the IDTExtensibility2 interface. Receives notification that the host application is being unloaded.</summary>
+		/// <param term='custom'>Array of parameters that are host application specific.</param>
+		/// <seealso class='IDTExtensibility2' />
+		public void OnBeginShutdown(ref Array custom)
+		{
+		}
+		
+		private DTE2 _applicationObject;
+		private AddIn _addInInstance;
+
+        #region IDTCommandTarget Members
+
+        public void Exec(string CmdName, vsCommandExecOption ExecuteOption, ref object VariantIn, ref object VariantOut, ref bool Handled)
+        {
+            Handled = false;
+            if (ExecuteOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
+            {
+                if (CmdName == "Etch.Connect.Etch" || CmdName == "Etch.Connect.EtchS" || CmdName == "Etch.Connect.EtchC" ||
+                    CmdName == "Etch.Connect.EtchM" || CmdName == "Etch.Connect.EtchMS" || CmdName == "Etch.Connect.EtchMC" ||
+                    CmdName == "Etch.Connect.EtchX")
+                {
+                    try
+                    {
+                        UIHierarchy uih = _applicationObject.ToolWindows.SolutionExplorer;
+                        UIHierarchyItem item = (uih.SelectedItems as System.Array).GetValue(0) as UIHierarchyItem;
+                        ProjectItem prjItem = item.Object as ProjectItem;
+                        string path = prjItem.Properties.Item("FullPath").Value.ToString();
+                        string dir = System.IO.Path.GetDirectoryName(path);
+
+                        ProcessStartInfo psi = new ProcessStartInfo();
+                        psi.UseShellExecute = true;
+                        psi.WorkingDirectory = dir;
+                        psi.FileName = "etch.bat";
+
+                        if(CmdName == "Etch.Connect.EtchX")
+                        {
+                            psi.Arguments = "-b xml -w all ";
+                        }
+                        else
+                        {
+                            psi.Arguments = "-b csharp ";
+
+                            if(CmdName == "Etch.Connect.EtchC")
+                                psi.Arguments += "-w client,main,impl,helper ";
+                            else if(CmdName == "Etch.Connect.EtchS")
+                                psi.Arguments += "-w server,main,impl,helper ";
+                            else if(CmdName == "Etch.Connect.Etch")
+                                psi.Arguments += "-w all ";
+                        }
+
+                        psi.Arguments += "\"" + path + "\"";
+
+                        System.Diagnostics.Process p = System.Diagnostics.Process.Start(psi);
+                        p.WaitForExit(60000);                        
+                    }
+                    catch (Exception ex)
+                    {
+                        System.Windows.Forms.MessageBox.Show(ex.ToString(), "Error",
+                            System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
+                    }
+
+                    Handled = true;
+                    return;
+                }
+            }
+        }
+
+        public void QueryStatus(string CmdName, vsCommandStatusTextWanted NeededText, ref vsCommandStatus StatusOption, ref object CommandText)
+        {
+            if (NeededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone)
+            {
+                if (CmdName == "Etch.Connect.Etch" || CmdName == "Etch.Connect.EtchS" || CmdName == "Etch.Connect.EtchC" ||
+                    CmdName == "Etch.Connect.EtchM" || CmdName == "Etch.Connect.EtchMS" || CmdName == "Etch.Connect.EtchMC" || CmdName == "Etch.Connect.EtchX")
+                {
+                    //Dynamically enable & disable the command. If the selected file name is *.etch, then make the command visible.
+                    UIHierarchy uih = _applicationObject.ToolWindows.SolutionExplorer;
+                    UIHierarchyItem item = (uih.SelectedItems as System.Array).GetValue(0) as UIHierarchyItem;
+                    StatusOption = vsCommandStatus.vsCommandStatusSupported;
+                    string name = item.Name.ToLower();
+                    if (!name.EndsWith(".etch"))
+                    {
+                        StatusOption |= vsCommandStatus.vsCommandStatusInvisible;
+                    }
+                    else
+                    {
+                        StatusOption |= vsCommandStatus.vsCommandStatusEnabled;
+                    }
+                }
+                else
+                {
+                    StatusOption = vsCommandStatus.vsCommandStatusUnsupported;
+                }
+            }
+        }
+
+        #endregion
+    }
+}
\ No newline at end of file
diff --git a/plugins/visualstudio-addin/etch-addin/Etch-AddIn.csproj b/plugins/visualstudio-addin/etch-addin/Etch-AddIn.csproj
new file mode 100644
index 0000000..32b6450
--- /dev/null
+++ b/plugins/visualstudio-addin/etch-addin/Etch-AddIn.csproj
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{77EBC514-6834-486D-B5E2-CE17B26BF202}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <StartupObject>
+    </StartupObject>
+    <NoStandardLibraries>false</NoStandardLibraries>
+    <AssemblyName>EtchAddIn</AssemblyName>
+    <RootNamespace>EtchAddIn</RootNamespace>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\</OutputPath>
+    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <WarningLevel>4</WarningLevel>
+    <IncrementalBuild>false</IncrementalBuild>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugSymbols>false</DebugSymbols>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\</OutputPath>
+    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
+    <DefineConstants>TRACE</DefineConstants>
+    <WarningLevel>4</WarningLevel>
+    <IncrementalBuild>false</IncrementalBuild>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Extensibility, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AssemblyInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Connect.cs">
+      <SubType>Code</SubType>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="CommandBar.resx">
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <COMReference Include="EnvDTE">
+      <Guid>{80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2}</Guid>
+      <VersionMajor>8</VersionMajor>
+      <VersionMinor>0</VersionMinor>
+      <Lcid>0</Lcid>
+      <WrapperTool>primary</WrapperTool>
+      <Isolated>False</Isolated>
+    </COMReference>
+    <COMReference Include="EnvDTE80">
+      <Guid>{1A31287A-4D7D-413E-8E32-3B374931BD89}</Guid>
+      <VersionMajor>8</VersionMajor>
+      <VersionMinor>0</VersionMinor>
+      <Lcid>0</Lcid>
+      <WrapperTool>primary</WrapperTool>
+      <Isolated>False</Isolated>
+    </COMReference>
+    <COMReference Include="Microsoft.VisualStudio.CommandBars">
+      <Guid>{1CBA492E-7263-47BB-87FE-639000619B15}</Guid>
+      <VersionMajor>8</VersionMajor>
+      <VersionMinor>0</VersionMinor>
+      <Lcid>0</Lcid>
+      <WrapperTool>primary</WrapperTool>
+      <Isolated>False</Isolated>
+    </COMReference>
+    <COMReference Include="stdole">
+      <Guid>{00020430-0000-0000-C000-000000000046}</Guid>
+      <VersionMajor>2</VersionMajor>
+      <VersionMinor>0</VersionMinor>
+      <Lcid>0</Lcid>
+      <WrapperTool>primary</WrapperTool>
+      <Isolated>False</Isolated>
+    </COMReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="Etch.AddIn" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
+  <PropertyGroup>
+    <PreBuildEvent>
+    </PreBuildEvent>
+    <PostBuildEvent>
+    </PostBuildEvent>
+  </PropertyGroup>
+  <ProjectExtensions>
+    <VisualStudio>
+    </VisualStudio>
+  </ProjectExtensions>
+</Project>
diff --git a/plugins/visualstudio-addin/etch-addin/Etch.AddIn b/plugins/visualstudio-addin/etch-addin/Etch.AddIn
new file mode 100644
index 0000000..5c1e302
--- /dev/null
+++ b/plugins/visualstudio-addin/etch-addin/Etch.AddIn
Binary files differ
diff --git a/plugins/visualstudio-addin/installer/VS2005_AddIn_User_Guide.rtf b/plugins/visualstudio-addin/installer/VS2005_AddIn_User_Guide.rtf
new file mode 100644
index 0000000..b61dbc3
--- /dev/null
+++ b/plugins/visualstudio-addin/installer/VS2005_AddIn_User_Guide.rtf
@@ -0,0 +1,144 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf430
+{\fonttbl\f0\fswiss\fcharset0 ArialMT;\f1\froman\fcharset0 TimesNewRomanPSMT;\f2\fmodern\fcharset0 CourierNewPSMT;
+}
+{\colortbl;\red255\green255\blue255;}
+\vieww12000\viewh15840\viewkind0
+\deftab720
+\pard\pardeftab720\sb240\sa60\qc
+
+\f0\b\fs32 \cf0 Microsoft Visual Studio 2005 Add-In Users Guide\
+\pard\pardeftab720\qc
+
+\f1\b0\fs24 \cf0 \expnd0\expndtw0\kerning0
+~Draft~\
+\pard\pardeftab720\sb240\sa60\ql\qnatural
+
+\f0\i\b\fs28 \cf0 License\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\i0\b0\fs24 \cf0 \kerning1\expnd0\expndtw0 \
+ * Licensed to the Apache Software Foundation (ASF) under one   *\
+ * or more contributor license agreements.  See the NOTICE file *\
+ * distributed with this work for additional information        *\
+ * regarding copyright ownership.  The ASF licenses this file   *\
+ * to you under the Apache License, Version 2.0 (the            *\
+ * "License"); you may not use this file except in compliance   *\
+ * with the License.  You may obtain a copy of the License at   *\
+ *                                                              *\
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *\
+ *                                                              *\
+ * Unless required by applicable law or agreed to in writing,   *\
+ * software distributed under the License is distributed on an  *\
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *\
+ * KIND, either express or implied.  See the License for the    *\
+ * specific language governing permissions and limitations      *\
+ * under the License.                                           *
+\fs28 \
+
+\i\b \expnd0\expndtw0\kerning0
+\
+\pard\pardeftab720\sb240\sa60\ql\qnatural
+\cf0 About the Add-In\
+\pard\pardeftab720\ql\qnatural
+
+\f1\fs24 \cf0 Microsoft Visual Studio 2005 Add-In
+\i0\b0  is a plugin provided by Etch framework to integrate Etch Compiler and Etch C# runtime library into Visual Studio 2005 IDE.  Developers who use C# to develop Etch network service and client can use this Add-In to generate Etch C# binding and stub code without leaving the IDE.  Also, Etch C# library is available in the list of standard .Net components.  Developers can reference the library without browsing into the Etch library directory.  \
+\pard\pardeftab720\sb240\sa60\ql\qnatural
+
+\f0\i\b\fs28 \cf0 Installation and Uninstallation\
+\pard\pardeftab720\sa120\ql\qnatural
+
+\f1\i0\b0\fs24 \cf0 A wizard-driven installer is available for developers to install and uninstall the Add-In effortlessly.  The installer, 
+\i\b VSAddInSetup.exe
+\i0\b0 , is in the 
+\i\b plugins
+\i0\b0  folder inside Etch home directory.  \
+To install the Add-In, run 
+\i\b VSAddInSetup.exe
+\i0\b0  and specified your Etch home directory and the install directory for the Add-In.  Please close all instances of Visual Studio 2005 before installation.  After installation, you can find 
+\i\b Etch
+\i0\b0  listed as one of the Add-Ins in the 
+\i\b Add-In Manager
+\i0\b0  (
+\i\b Tools, Add-in Manager\'85
+\i0\b0 ).     \
+\pard\pardeftab720\sa120\qc
+
+\f2\fs20 \cf0 \
+\pard\pardeftab720\sa120\ql\qnatural
+
+\f1\fs24 \cf0 To uninstall the Add-In, user can either perform the action from 
+\i\b Control Panel
+\i0\b0 , 
+\i\b Add or Remove Programs, Visual Studio for Etch
+\i0\b0  or 
+\i\b Start
+\i0\b0 , 
+\i\b All Programs
+\i0\b0 , 
+\i\b Visual Studio Add-In for Etch
+\i0\b0 , 
+\i\b Uninstall
+\i0\b0 .  All instances of Visual Studio 2005 must be closed before uninstallation.  The uninstaller restarts Visual Studio 2005 when the uninstallation process is done.\
+\pard\pardeftab720\sb240\sa60\ql\qnatural
+
+\f0\i\b\fs28 \cf0 Etch C# Runtime Reference\
+\pard\pardeftab720\ql\qnatural
+
+\f1\i0\b0\fs24 \cf0 The Add-In adds the library path of Etch installation into Visual Studio 2005\'92s default assembly folders.  When developers need to add Etch C# runtime as one of the references into the project, the 
+\i\b Etch4CS
+\i0\b0  library can be easily located in the 
+\i\b .NET
+\i0\b0  tab of 
+\i\b Add Reference
+\i0\b0  window.    \
+\pard\pardeftab720\sb240\sa60\qc
+\cf0 \
+\pard\pardeftab720\sb240\sa60\ql\qnatural
+\cf0 \
+\pard\pardeftab720\sb240\sa60\ql\qnatural
+
+\f0\i\b\fs28 \cf0 Generate Etch C# Binding\
+\pard\pardeftab720\ql\qnatural
+
+\f1\i0\b0\fs24 \cf0 The Add-In integrates with Etch Compiler for developers to generate Etch C# binding and stub code inside 
+\i\b Visual Studio 2005 IDE
+\i0\b0 .  The Add-In provides three context menu items in 
+\i\b Solution Explorer
+\i0\b0 ; developers can right-mouse click on an Etch network service definition file (
+\i\b .etch
+\i0\b0 )  in a development project then create the bindings and stub code by selecting one of the three Etch related menu items.\
+\
+
+\i\b Etch (Both)
+\i0\b0 : Generate both server and client binding and stub code.\
+
+\i\b Etch (Server)
+\i0\b0 : Generate server side binding and stub code.\
+
+\i\b Etch (Client)
+\i0\b0 : Generate client side binding and stub code.\
+\
+The Etch compiler generated files reside under the same directory as Etch network service definition file (
+\i\b .etch)
+\i0\b0  file.  \
+\
+\pard\pardeftab720\qc
+
+\f2\fs20 \cf0 \
+\
+\
+\
+\
+\pard\pardeftab720\ql\qnatural
+
+\f1\fs24 \cf0 To view Etch compiler generated files, developers can click on \'93
+\i\b Show All Files
+\i0\b0 \'94 toolbar button on 
+\i\b Solution Explorer
+\i0\b0  then select files and include them into the working project.  \
+\
+\pard\pardeftab720\qc
+\cf0  
+\f2\fs20 \
+}
\ No newline at end of file
diff --git a/plugins/visualstudio-addin/installer/modern-install.ico b/plugins/visualstudio-addin/installer/modern-install.ico
new file mode 100644
index 0000000..bc25e62
--- /dev/null
+++ b/plugins/visualstudio-addin/installer/modern-install.ico
Binary files differ
diff --git a/plugins/visualstudio-addin/installer/modern-uninstall.ico b/plugins/visualstudio-addin/installer/modern-uninstall.ico
new file mode 100644
index 0000000..84cce22
--- /dev/null
+++ b/plugins/visualstudio-addin/installer/modern-uninstall.ico
Binary files differ
diff --git a/plugins/visualstudio-addin/installer/visualstudio.nsi b/plugins/visualstudio-addin/installer/visualstudio.nsi
new file mode 100644
index 0000000..c11973b
--- /dev/null
+++ b/plugins/visualstudio-addin/installer/visualstudio.nsi
@@ -0,0 +1,135 @@
+; Script generated by the HM NIS Edit Script Wizard.
+
+; Licensed to the Apache Software Foundation (ASF) under one   *
+; or more contributor license agreements.  See the NOTICE file *
+; distributed with this work for additional information        *
+; regarding copyright ownership.  The ASF licenses this file   *
+; to you under the Apache License, Version 2.0 (the            *
+; "License"); you may not use this file except in compliance   *
+; with the License.  You may obtain a copy of the License at   *
+;                                                              *
+;   http://www.apache.org/licenses/LICENSE-2.0                 *
+;                                                              *
+; Unless required by applicable law or agreed to in writing,   *
+; software distributed under the License is distributed on an  *
+; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+; KIND, either express or implied.  See the License for the    *
+; specific language governing permissions and limitations      *
+; under the License.                                           *
+
+; HM NIS Edit Wizard helper defines
+!define PRODUCT_NAME "Visual Studio Add-In for Apache Etch"
+!define PRODUCT_VERSION "1.0"
+!define PRODUCT_PUBLISHER "Apache Software Foundation"
+!define PRODUCT_WEB_SITE "http://incubator.apache.org/projects/etch.html"
+!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
+!define PRODUCT_UNINST_ROOT_KEY "HKLM"
+!define ETCH_CS_ASSEMBLY_FOLDER "SOFTWARE\Microsoft\.NETFramework\AssemblyFolders\Etch"
+!define SHELL_FOLDERS "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
+!define VS_FOLDER "SOFTWARE\Microsoft\VisualStudio\8.0"
+
+; MUI 1.67 compatible ------
+!include "MUI.nsh"
+
+; MUI Settings
+!define MUI_ABORTWARNING
+!define MUI_ICON "modern-install.ico"
+!define MUI_UNICON "modern-uninstall.ico"
+!define MUI_WELCOMEPAGE_TITLE_3LINES
+
+; Welcome page
+!insertmacro MUI_PAGE_WELCOME
+
+; Etch Installation Folder
+Var ETCH_HOME
+!define MUI_DIRECTORYPAGE_VARIABLE $ETCH_HOME
+!define MUI_PAGE_HEADER_TEXT "Apache Etch Home Directory."
+!define MUI_PAGE_HEADER_SUBTEXT "Choose the folder in which Etch package is installed."
+!define MUI_DIRECTORYPAGE_TEXT_TOP "Please browse to Apache Etch home directory."
+!define MUI_DIRECTORYPAGE_TEXT_DESTINATION "Apache Etch home directory"
+!insertmacro MUI_PAGE_DIRECTORY
+
+; Directory page
+!insertmacro MUI_PAGE_DIRECTORY
+
+; Instfiles page
+!insertmacro MUI_PAGE_INSTFILES
+
+; Finish page
+!insertmacro MUI_PAGE_FINISH
+
+; Uninstaller pages
+!insertmacro MUI_UNPAGE_INSTFILES
+
+; Language files
+!insertmacro MUI_LANGUAGE "English"
+
+; MUI end ------
+
+Name "${PRODUCT_NAME}"
+OutFile "VSAddInSetup.exe"
+InstallDir "$PROGRAMFILES\Visual Studio Add-In for Apache Etch"
+ShowInstDetails hide
+ShowUnInstDetails hide
+XPStyle "on"
+RequestExecutionLevel admin
+
+Section "Visual Studio Add-In for Apache Etch" SEC01
+  SetOutPath "$INSTDIR"
+  SetOverwrite try
+  File "EtchAddIn.dll"
+  File "Etch.AddIn"
+  File "VS2005_AddIn_User_Guide.rtf"
+  WriteRegStr HKLM "${ETCH_CS_ASSEMBLY_FOLDER}" "" "$ETCH_HOME\lib"
+  ReadRegStr $0 HKCU "${SHELL_FOLDERS}" Personal
+  SetOutPath "$0\Visual Studio 2005\Addins\"
+  SetOverwrite try
+  File "EtchAddIn.dll"
+  File "Etch.AddIn"
+SectionEnd
+
+Section -AdditionalIcons
+  SetOutPath $INSTDIR
+  CreateDirectory "$SMPROGRAMS\Visual Studio Add-In for Apache Etch"
+  CreateShortCut "$SMPROGRAMS\Visual Studio Add-In for Apache Etch\User Guide.lnk" "$INSTDIR\VS2005_AddIn_User_Guide.rtf"
+  CreateShortCut "$SMPROGRAMS\Visual Studio Add-In for Apache Etch\Uninstall.lnk" "$INSTDIR\uninst.exe"
+SectionEnd
+
+Section -Post
+  WriteUninstaller "$INSTDIR\uninst.exe"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
+SectionEnd
+
+Function un.onUninstSuccess
+  HideWindow
+  MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) was successfully removed from your computer."
+  ReadRegStr $0 HKLM "${VS_FOLDER}" InstallDir
+  ExecWait '$0\devenv.exe /ResetAddin Etch'
+FunctionEnd
+
+Function un.onInit
+  MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove $(^Name)?" IDYES +2
+  Abort
+FunctionEnd
+
+Section Uninstall
+  MessageBox MB_ICONEXCLAMATION|MB_OK|MB_TOPMOST "Please close Visual Studio 2005 and click OK to continue."
+  DeleteRegValue HKLM "${ETCH_CS_ASSEMBLY_FOLDER}" ""
+  DeleteRegKey HKLM "${ETCH_CS_ASSEMBLY_FOLDER}"
+  ReadRegStr $0 HKCU "${SHELL_FOLDERS}" Personal
+  Delete "$0\Visual Studio 2005\Addins\EtchAddIn.dll"
+  Delete "$0\Visual Studio 2005\Addins\Etch.AddIn"
+  Delete "$INSTDIR\EtchAddIn.dll"
+  Delete "$INSTDIR\Etch.AddIn"
+  Delete "$INSTDIR\VS2005_AddIn_User_Guide.rtf"
+  Delete "$INSTDIR\uninst.exe"
+  Delete "$SMPROGRAMS\Visual Studio Add-In for Apache Etch\User Guide.lnk"
+  Delete "$SMPROGRAMS\Visual Studio Add-In for Apache Etch\Uninstall.lnk"
+  RMDir "$SMPROGRAMS\Visual Studio Add-In for Apache Etch"
+  DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
+  SetAutoClose true
+SectionEnd
diff --git a/plugins/visualstudio-addin/postbuild/AssemblyInfo.cs b/plugins/visualstudio-addin/postbuild/AssemblyInfo.cs
new file mode 100644
index 0000000..8377f08
--- /dev/null
+++ b/plugins/visualstudio-addin/postbuild/AssemblyInfo.cs
@@ -0,0 +1,74 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]		
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the 
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing. 
+//
+// Notes: 
+//   (*) If no key is specified, the assembly is not signed.
+//   (*) KeyName refers to a key that has been installed in the Crypto Service
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains
+//       a key.
+//   (*) If the KeyFile and the KeyName values are both specified, the 
+//       following processing occurs:
+//       (1) If the KeyName can be found in the CSP, that key is used.
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key 
+//           in the KeyFile is installed into the CSP and used.
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+//       When specifying the KeyFile, the location of the KeyFile should be
+//       relative to the project output directory which is
+//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+//       located in the project directory, you would specify the AssemblyKeyFile 
+//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+//       documentation for more information on this.
+//
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]
diff --git a/plugins/visualstudio-addin/postbuild/PostBuild.bat b/plugins/visualstudio-addin/postbuild/PostBuild.bat
new file mode 100644
index 0000000..2fa0cef
--- /dev/null
+++ b/plugins/visualstudio-addin/postbuild/PostBuild.bat
@@ -0,0 +1,57 @@
+@rem  Licensed to the Apache Software Foundation (ASF) under one   *
+@rem  or more contributor license agreements.  See the NOTICE file *
+@rem  distributed with this work for additional information        *
+@rem  regarding copyright ownership.  The ASF licenses this file   *
+@rem  to you under the Apache License, Version 2.0 (the            *
+@rem  "License"); you may not use this file except in compliance   *
+@rem  with the License.  You may obtain a copy of the License at   *
+@rem                                                               *
+@rem    http://www.apache.org/licenses/LICENSE-2.0                 *
+@rem                                                               *
+@rem  Unless required by applicable law or agreed to in writing,   *
+@rem  software distributed under the License is distributed on an  *
+@rem  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+@rem  KIND, either express or implied.  See the License for the    *
+@rem  specific language governing permissions and limitations      *
+@rem  under the License.                                           *
+@echo off
+setlocal
+
+if "%1" == "" goto usage
+
+call "%VS71COMNTOOLS%\vsvars32.bat" >nul
+set DeployDir=..\installer
+
+if not exist %DeployDir%	mkdir %DeployDir%
+
+if exist postbuild.txt del postbuild.txt /F /Q
+
+REM Clear shadow copies of dlls
+gacutil /cdl                                                            >> postbuild.txt
+
+@echo ****** Removing assemblies from GAC ******                        >> postbuild.txt
+gacutil /uf EtchAddIn                                                   >> postbuild.txt
+
+@echo.                                                                  >> postbuild.txt
+
+@echo ****** Installing common assemblies ******                        >> postbuild.txt
+xcopy ..\etch-addin\bin\EtchAddIn.dll                                   %DeployDir%     /Y     >> postbuild.txt
+xcopy ..\etch-addin\Etch.AddIn                                          %DeployDir%     /Y     >> postbuild.txt
+
+@echo.                                                                  >> postbuild.txt
+
+gacutil /i %DeployDir%\EtchAddIn.dll                                    >> postbuild.txt
+
+echo.                                                                   >> postbuild.txt
+
+goto done
+
+goto done
+
+:usage
+echo Usage: PostBuild.bat [CONFIGURATION]
+echo Configuration is any valid VS.NET configuration (Debug, Release, etc).
+
+goto done
+
+:done
diff --git a/plugins/visualstudio-addin/postbuild/PostBuild.csproj b/plugins/visualstudio-addin/postbuild/PostBuild.csproj
new file mode 100644
index 0000000..a6495e2
--- /dev/null
+++ b/plugins/visualstudio-addin/postbuild/PostBuild.csproj
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <ProjectType>Local</ProjectType>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{2D861A88-063A-4E10-B414-EEB4E9D915A1}</ProjectGuid>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ApplicationIcon>
+    </ApplicationIcon>
+    <AssemblyKeyContainerName>
+    </AssemblyKeyContainerName>
+    <AssemblyName>PostBuild</AssemblyName>
+    <AssemblyOriginatorKeyFile>
+    </AssemblyOriginatorKeyFile>
+    <DefaultClientScript>JScript</DefaultClientScript>
+    <DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
+    <DefaultTargetSchema>IE50</DefaultTargetSchema>
+    <DelaySign>false</DelaySign>
+    <OutputType>Library</OutputType>
+    <RootNamespace>PostBuild</RootNamespace>
+    <RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
+    <StartupObject>
+    </StartupObject>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <OutputPath>.\</OutputPath>
+    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
+    <BaseAddress>285212672</BaseAddress>
+    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
+    <ConfigurationOverrideFile>
+    </ConfigurationOverrideFile>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <DebugSymbols>true</DebugSymbols>
+    <FileAlignment>4096</FileAlignment>
+    <NoStdLib>false</NoStdLib>
+    <NoWarn>
+    </NoWarn>
+    <Optimize>false</Optimize>
+    <RegisterForComInterop>false</RegisterForComInterop>
+    <RemoveIntegerChecks>false</RemoveIntegerChecks>
+    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+    <WarningLevel>4</WarningLevel>
+    <DebugType>full</DebugType>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <OutputPath>.\</OutputPath>
+    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
+    <BaseAddress>285212672</BaseAddress>
+    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
+    <ConfigurationOverrideFile>
+    </ConfigurationOverrideFile>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <DebugSymbols>false</DebugSymbols>
+    <FileAlignment>4096</FileAlignment>
+    <NoStdLib>false</NoStdLib>
+    <NoWarn>
+    </NoWarn>
+    <Optimize>true</Optimize>
+    <RegisterForComInterop>false</RegisterForComInterop>
+    <RemoveIntegerChecks>false</RemoveIntegerChecks>
+    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+    <WarningLevel>4</WarningLevel>
+    <DebugType>none</DebugType>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <ItemGroup>
+    <None Include="PostBuild.bat" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AssemblyInfo.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent>
+    </PreBuildEvent>
+    <PostBuildEvent>PostBuild.bat $(ConfigurationName)</PostBuildEvent>
+  </PropertyGroup>
+</Project>
diff --git a/plugins/visualstudio-addin/visualstudio-addin.sln b/plugins/visualstudio-addin/visualstudio-addin.sln
new file mode 100644
index 0000000..f7b0c94
--- /dev/null
+++ b/plugins/visualstudio-addin/visualstudio-addin.sln
@@ -0,0 +1,45 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+# Licensed to the Apache Software Foundation (ASF) under one   *
+# or more contributor license agreements.  See the NOTICE file *
+# distributed with this work for additional information        *
+# regarding copyright ownership.  The ASF licenses this file   *
+# to you under the Apache License, Version 2.0 (the            *
+# "License"); you may not use this file except in compliance   *
+# with the License.  You may obtain a copy of the License at   *
+#                                                              *
+#   http://www.apache.org/licenses/LICENSE-2.0                 *
+#                                                              *
+# Unless required by applicable law or agreed to in writing,   *
+# software distributed under the License is distributed on an  *
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+# KIND, either express or implied.  See the License for the    *
+# specific language governing permissions and limitations      *
+# under the License.                                           *
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Etch-AddIn", "etch-addin\Etch-AddIn.csproj", "{77EBC514-6834-486D-B5E2-CE17B26BF202}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PostBuild", "postbuild\PostBuild.csproj", "{2D861A88-063A-4E10-B414-EEB4E9D915A1}"
+	ProjectSection(ProjectDependencies) = postProject
+		{77EBC514-6834-486D-B5E2-CE17B26BF202} = {77EBC514-6834-486D-B5E2-CE17B26BF202}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{77EBC514-6834-486D-B5E2-CE17B26BF202}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{77EBC514-6834-486D-B5E2-CE17B26BF202}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{77EBC514-6834-486D-B5E2-CE17B26BF202}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{77EBC514-6834-486D-B5E2-CE17B26BF202}.Release|Any CPU.Build.0 = Release|Any CPU
+		{2D861A88-063A-4E10-B414-EEB4E9D915A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{2D861A88-063A-4E10-B414-EEB4E9D915A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{2D861A88-063A-4E10-B414-EEB4E9D915A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{2D861A88-063A-4E10-B414-EEB4E9D915A1}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/scripts/Bamboo.bat b/scripts/Bamboo.bat
new file mode 100644
index 0000000..17f41d2
--- /dev/null
+++ b/scripts/Bamboo.bat
@@ -0,0 +1,33 @@
+@rem  Licensed to the Apache Software Foundation (ASF) under one   *
+@rem  or more contributor license agreements.  See the NOTICE file *
+@rem  distributed with this work for additional information        *
+@rem  regarding copyright ownership.  The ASF licenses this file   *
+@rem  to you under the Apache License, Version 2.0 (the            *
+@rem  "License"); you may not use this file except in compliance   *
+@rem  with the License.  You may obtain a copy of the License at   *
+@rem                                                               *
+@rem    http://www.apache.org/licenses/LICENSE-2.0                 *
+@rem                                                               *
+@rem  Unless required by applicable law or agreed to in writing,   *
+@rem  software distributed under the License is distributed on an  *
+@rem  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+@rem  KIND, either express or implied.  See the License for the    *
+@rem  specific language governing permissions and limitations      *
+@rem  under the License.                                           *
+@echo off
+:: This batch file is a wrapper so that we can set up our environment, and then
+:: kick off a build in bamboo
+::  (dixson) this really only useful in the Etch committers build-env
+
+
+:: Run our env setup script
+call %TOOLS_DIR%\Environment.bat -qnc -p ETCH
+set ETCH_HOME=
+
+:: Hack to get DOTNET defined. Environment.bat should do it.
+set DOTNET_HOME=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
+
+:: Call ant with the arguments that we pass in
+cd ..
+call ant %*
+
diff --git a/scripts/Compile Csharp Etch Files Lnx.launch b/scripts/Compile Csharp Etch Files Lnx.launch
new file mode 100644
index 0000000..7d1ddc9
--- /dev/null
+++ b/scripts/Compile Csharp Etch Files Lnx.launch
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!--

+ * Licensed to the Apache Software Foundation (ASF) under one   *

+ * or more contributor license agreements.  See the NOTICE file *

+ * distributed with this work for additional information        *

+ * regarding copyright ownership.  The ASF licenses this file   *

+ * to you under the Apache License, Version 2.0 (the            *

+ * "License"); you may not use this file except in compliance   *

+ * with the License.  You may obtain a copy of the License at   *

+ *                                                              *

+ *   http://www.apache.org/licenses/LICENSE-2.0                 *

+ *                                                              *

+ * Unless required by applicable law or agreed to in writing,   *

+ * software distributed under the License is distributed on an  *

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+ * KIND, either express or implied.  See the License for the    *

+ * specific language governing permissions and limitations      *

+ * under the License.                                           *

+ -->

+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">

+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/scripts/compEtchFilesForCsharp.bash"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc}"/>

+</launchConfiguration>

diff --git a/scripts/Compile Csharp Etch Files Win.launch b/scripts/Compile Csharp Etch Files Win.launch
new file mode 100644
index 0000000..cca583d
--- /dev/null
+++ b/scripts/Compile Csharp Etch Files Win.launch
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!--

+ * Licensed to the Apache Software Foundation (ASF) under one   *

+ * or more contributor license agreements.  See the NOTICE file *

+ * distributed with this work for additional information        *

+ * regarding copyright ownership.  The ASF licenses this file   *

+ * to you under the Apache License, Version 2.0 (the            *

+ * "License"); you may not use this file except in compliance   *

+ * with the License.  You may obtain a copy of the License at   *

+ *                                                              *

+ *   http://www.apache.org/licenses/LICENSE-2.0                 *

+ *                                                              *

+ * Unless required by applicable law or agreed to in writing,   *

+ * software distributed under the License is distributed on an  *

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+ * KIND, either express or implied.  See the License for the    *

+ * specific language governing permissions and limitations      *

+ * under the License.                                           *

+ -->

+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">

+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">

+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>

+</listAttribute>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/scripts/compEtchFilesForCsharp.bat"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc}"/>

+</launchConfiguration>

diff --git a/scripts/Compile Java Etch Files Lnx.launch b/scripts/Compile Java Etch Files Lnx.launch
new file mode 100644
index 0000000..921a0e9
--- /dev/null
+++ b/scripts/Compile Java Etch Files Lnx.launch
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!--

+ * Licensed to the Apache Software Foundation (ASF) under one   *

+ * or more contributor license agreements.  See the NOTICE file *

+ * distributed with this work for additional information        *

+ * regarding copyright ownership.  The ASF licenses this file   *

+ * to you under the Apache License, Version 2.0 (the            *

+ * "License"); you may not use this file except in compliance   *

+ * with the License.  You may obtain a copy of the License at   *

+ *                                                              *

+ *   http://www.apache.org/licenses/LICENSE-2.0                 *

+ *                                                              *

+ * Unless required by applicable law or agreed to in writing,   *

+ * software distributed under the License is distributed on an  *

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+ * KIND, either express or implied.  See the License for the    *

+ * specific language governing permissions and limitations      *

+ * under the License.                                           *

+ -->

+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">

+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/scripts/compEtchFilesForJava.bash"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc}"/>

+</launchConfiguration>

diff --git a/scripts/Compile Java Etch Files Win.launch b/scripts/Compile Java Etch Files Win.launch
new file mode 100644
index 0000000..af80ad1
--- /dev/null
+++ b/scripts/Compile Java Etch Files Win.launch
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!--

+ * Licensed to the Apache Software Foundation (ASF) under one   *

+ * or more contributor license agreements.  See the NOTICE file *

+ * distributed with this work for additional information        *

+ * regarding copyright ownership.  The ASF licenses this file   *

+ * to you under the Apache License, Version 2.0 (the            *

+ * "License"); you may not use this file except in compliance   *

+ * with the License.  You may obtain a copy of the License at   *

+ *                                                              *

+ *   http://www.apache.org/licenses/LICENSE-2.0                 *

+ *                                                              *

+ * Unless required by applicable law or agreed to in writing,   *

+ * software distributed under the License is distributed on an  *

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+ * KIND, either express or implied.  See the License for the    *

+ * specific language governing permissions and limitations      *

+ * under the License.                                           *

+ -->

+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">

+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>

+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">

+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>

+</listAttribute>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/scripts/compEtchFilesForJava.bat"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc}"/>

+</launchConfiguration>

diff --git a/scripts/Compile Xml Etch Files Lnx.launch b/scripts/Compile Xml Etch Files Lnx.launch
new file mode 100644
index 0000000..9c9ef02
--- /dev/null
+++ b/scripts/Compile Xml Etch Files Lnx.launch
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!--

+ * Licensed to the Apache Software Foundation (ASF) under one   *

+ * or more contributor license agreements.  See the NOTICE file *

+ * distributed with this work for additional information        *

+ * regarding copyright ownership.  The ASF licenses this file   *

+ * to you under the Apache License, Version 2.0 (the            *

+ * "License"); you may not use this file except in compliance   *

+ * with the License.  You may obtain a copy of the License at   *

+ *                                                              *

+ *   http://www.apache.org/licenses/LICENSE-2.0                 *

+ *                                                              *

+ * Unless required by applicable law or agreed to in writing,   *

+ * software distributed under the License is distributed on an  *

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+ * KIND, either express or implied.  See the License for the    *

+ * specific language governing permissions and limitations      *

+ * under the License.                                           *

+ -->

+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">

+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/scripts/compEtchFilesForXml.bash"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc}"/>

+</launchConfiguration>

diff --git a/scripts/Compile Xml Etch Files Win.launch b/scripts/Compile Xml Etch Files Win.launch
new file mode 100644
index 0000000..eed4f76
--- /dev/null
+++ b/scripts/Compile Xml Etch Files Win.launch
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!--

+ * Licensed to the Apache Software Foundation (ASF) under one   *

+ * or more contributor license agreements.  See the NOTICE file *

+ * distributed with this work for additional information        *

+ * regarding copyright ownership.  The ASF licenses this file   *

+ * to you under the Apache License, Version 2.0 (the            *

+ * "License"); you may not use this file except in compliance   *

+ * with the License.  You may obtain a copy of the License at   *

+ *                                                              *

+ *   http://www.apache.org/licenses/LICENSE-2.0                 *

+ *                                                              *

+ * Unless required by applicable law or agreed to in writing,   *

+ * software distributed under the License is distributed on an  *

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+ * KIND, either express or implied.  See the License for the    *

+ * specific language governing permissions and limitations      *

+ * under the License.                                           *

+ -->

+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">

+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>

+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">

+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>

+</listAttribute>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/scripts/compEtchFilesForXml.bat"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc}"/>

+</launchConfiguration>

diff --git a/scripts/Etch - csharp, all, force.launch b/scripts/Etch - csharp, all, force.launch
new file mode 100644
index 0000000..7dd9573
--- /dev/null
+++ b/scripts/Etch - csharp, all, force.launch
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!--

+ * Licensed to the Apache Software Foundation (ASF) under one   *

+ * or more contributor license agreements.  See the NOTICE file *

+ * distributed with this work for additional information        *

+ * regarding copyright ownership.  The ASF licenses this file   *

+ * to you under the Apache License, Version 2.0 (the            *

+ * "License"); you may not use this file except in compliance   *

+ * with the License.  You may obtain a copy of the License at   *

+ *                                                              *

+ *   http://www.apache.org/licenses/LICENSE-2.0                 *

+ *                                                              *

+ * Unless required by applicable law or agreed to in writing,   *

+ * software distributed under the License is distributed on an  *

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+ * KIND, either express or implied.  See the License for the    *

+ * specific language governing permissions and limitations      *

+ * under the License.                                           *

+ -->

+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">

+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>

+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">

+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>

+</listAttribute>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/scripts/etch-eclipse.bat"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-q&#13;&#10;-b csharp&#13;&#10;-w all,force&#13;&#10;-n&#13;&#10;-d ../../../target/generated-sources/main/etch/csharp&#13;&#10;${resource_name}"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${container_loc}"/>

+</launchConfiguration>

diff --git a/scripts/Etch - csharp, all.launch b/scripts/Etch - csharp, all.launch
new file mode 100644
index 0000000..ef9ac4d
--- /dev/null
+++ b/scripts/Etch - csharp, all.launch
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!--

+ * Licensed to the Apache Software Foundation (ASF) under one   *

+ * or more contributor license agreements.  See the NOTICE file *

+ * distributed with this work for additional information        *

+ * regarding copyright ownership.  The ASF licenses this file   *

+ * to you under the Apache License, Version 2.0 (the            *

+ * "License"); you may not use this file except in compliance   *

+ * with the License.  You may obtain a copy of the License at   *

+ *                                                              *

+ *   http://www.apache.org/licenses/LICENSE-2.0                 *

+ *                                                              *

+ * Unless required by applicable law or agreed to in writing,   *

+ * software distributed under the License is distributed on an  *

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+ * KIND, either express or implied.  See the License for the    *

+ * specific language governing permissions and limitations      *

+ * under the License.                                           *

+ -->

+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">

+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>

+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">

+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>

+</listAttribute>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/scripts/etch-eclipse.bat"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-q&#13;&#10;-b csharp&#13;&#10;-w all&#13;&#10;-n&#13;&#10;-d ../../../target/generated-sources/main/etch/csharp&#13;&#10;${resource_name}"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${container_loc}"/>

+</launchConfiguration>

diff --git a/scripts/Etch - csharp.launch b/scripts/Etch - csharp.launch
new file mode 100644
index 0000000..34ccd1e
--- /dev/null
+++ b/scripts/Etch - csharp.launch
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!--

+ * Licensed to the Apache Software Foundation (ASF) under one   *

+ * or more contributor license agreements.  See the NOTICE file *

+ * distributed with this work for additional information        *

+ * regarding copyright ownership.  The ASF licenses this file   *

+ * to you under the Apache License, Version 2.0 (the            *

+ * "License"); you may not use this file except in compliance   *

+ * with the License.  You may obtain a copy of the License at   *

+ *                                                              *

+ *   http://www.apache.org/licenses/LICENSE-2.0                 *

+ *                                                              *

+ * Unless required by applicable law or agreed to in writing,   *

+ * software distributed under the License is distributed on an  *

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+ * KIND, either express or implied.  See the License for the    *

+ * specific language governing permissions and limitations      *

+ * under the License.                                           *

+ -->

+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">

+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>

+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">

+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>

+</listAttribute>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/scripts/etch-eclipse.bat"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-q&#13;&#10;-b csharp&#13;&#10;-n&#13;&#10;-d ../../../target/generated-sources/main/etch/csharp&#13;&#10;${resource_name}"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${container_loc}"/>

+</launchConfiguration>

diff --git a/scripts/Etch - java, all, client.launch b/scripts/Etch - java, all, client.launch
new file mode 100644
index 0000000..a55b7c0
--- /dev/null
+++ b/scripts/Etch - java, all, client.launch
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!--

+ * Licensed to the Apache Software Foundation (ASF) under one   *

+ * or more contributor license agreements.  See the NOTICE file *

+ * distributed with this work for additional information        *

+ * regarding copyright ownership.  The ASF licenses this file   *

+ * to you under the Apache License, Version 2.0 (the            *

+ * "License"); you may not use this file except in compliance   *

+ * with the License.  You may obtain a copy of the License at   *

+ *                                                              *

+ *   http://www.apache.org/licenses/LICENSE-2.0                 *

+ *                                                              *

+ * Unless required by applicable law or agreed to in writing,   *

+ * software distributed under the License is distributed on an  *

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+ * KIND, either express or implied.  See the License for the    *

+ * specific language governing permissions and limitations      *

+ * under the License.                                           *

+ -->

+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">

+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>

+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">

+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>

+</listAttribute>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/scripts/etch-eclipse.bat"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-q&#13;&#10;-b java&#13;&#10;-w all,client&#13;&#10;-n&#13;&#10;-d ../../../target/generated-sources/main/etch/java&#13;&#10;${resource_name}"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${container_loc}"/>

+</launchConfiguration>

diff --git a/scripts/Etch - java, all, force.launch b/scripts/Etch - java, all, force.launch
new file mode 100644
index 0000000..eb85964
--- /dev/null
+++ b/scripts/Etch - java, all, force.launch
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!--

+ * Licensed to the Apache Software Foundation (ASF) under one   *

+ * or more contributor license agreements.  See the NOTICE file *

+ * distributed with this work for additional information        *

+ * regarding copyright ownership.  The ASF licenses this file   *

+ * to you under the Apache License, Version 2.0 (the            *

+ * "License"); you may not use this file except in compliance   *

+ * with the License.  You may obtain a copy of the License at   *

+ *                                                              *

+ *   http://www.apache.org/licenses/LICENSE-2.0                 *

+ *                                                              *

+ * Unless required by applicable law or agreed to in writing,   *

+ * software distributed under the License is distributed on an  *

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+ * KIND, either express or implied.  See the License for the    *

+ * specific language governing permissions and limitations      *

+ * under the License.                                           *

+ -->

+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">

+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>

+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">

+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>

+</listAttribute>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/scripts/etch-eclipse.bat"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-q&#13;&#10;-b java&#13;&#10;-w all,force&#13;&#10;-n&#13;&#10;-d ../../../target/generated-sources/main/etch/java&#13;&#10;${resource_name}"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${container_loc}"/>

+</launchConfiguration>

diff --git a/scripts/Etch - java, all, server.launch b/scripts/Etch - java, all, server.launch
new file mode 100644
index 0000000..c944f84
--- /dev/null
+++ b/scripts/Etch - java, all, server.launch
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!--

+ * Licensed to the Apache Software Foundation (ASF) under one   *

+ * or more contributor license agreements.  See the NOTICE file *

+ * distributed with this work for additional information        *

+ * regarding copyright ownership.  The ASF licenses this file   *

+ * to you under the Apache License, Version 2.0 (the            *

+ * "License"); you may not use this file except in compliance   *

+ * with the License.  You may obtain a copy of the License at   *

+ *                                                              *

+ *   http://www.apache.org/licenses/LICENSE-2.0                 *

+ *                                                              *

+ * Unless required by applicable law or agreed to in writing,   *

+ * software distributed under the License is distributed on an  *

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+ * KIND, either express or implied.  See the License for the    *

+ * specific language governing permissions and limitations      *

+ * under the License.                                           *

+ -->

+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">

+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>

+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">

+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>

+</listAttribute>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/scripts/etch-eclipse.bat"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-q&#13;&#10;-b java&#13;&#10;-w all,server&#13;&#10;-n&#13;&#10;-d ../../../target/generated-sources/main/etch/java&#13;&#10;${resource_name}"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${container_loc}"/>

+</launchConfiguration>

diff --git a/scripts/Etch - java, all.launch b/scripts/Etch - java, all.launch
new file mode 100644
index 0000000..4519b6b
--- /dev/null
+++ b/scripts/Etch - java, all.launch
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!--

+ * Licensed to the Apache Software Foundation (ASF) under one   *

+ * or more contributor license agreements.  See the NOTICE file *

+ * distributed with this work for additional information        *

+ * regarding copyright ownership.  The ASF licenses this file   *

+ * to you under the Apache License, Version 2.0 (the            *

+ * "License"); you may not use this file except in compliance   *

+ * with the License.  You may obtain a copy of the License at   *

+ *                                                              *

+ *   http://www.apache.org/licenses/LICENSE-2.0                 *

+ *                                                              *

+ * Unless required by applicable law or agreed to in writing,   *

+ * software distributed under the License is distributed on an  *

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+ * KIND, either express or implied.  See the License for the    *

+ * specific language governing permissions and limitations      *

+ * under the License.                                           *

+ -->

+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">

+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>

+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">

+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>

+</listAttribute>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/scripts/etch-eclipse.bat"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-q&#13;&#10;-b java&#13;&#10;-w all&#13;&#10;-n&#13;&#10;-d ../../../target/generated-sources/main/etch/java&#13;&#10;${resource_name}"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${container_loc}"/>

+</launchConfiguration>

diff --git a/scripts/Etch - java.launch b/scripts/Etch - java.launch
new file mode 100644
index 0000000..c97ebcb
--- /dev/null
+++ b/scripts/Etch - java.launch
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!--

+ * Licensed to the Apache Software Foundation (ASF) under one   *

+ * or more contributor license agreements.  See the NOTICE file *

+ * distributed with this work for additional information        *

+ * regarding copyright ownership.  The ASF licenses this file   *

+ * to you under the Apache License, Version 2.0 (the            *

+ * "License"); you may not use this file except in compliance   *

+ * with the License.  You may obtain a copy of the License at   *

+ *                                                              *

+ *   http://www.apache.org/licenses/LICENSE-2.0                 *

+ *                                                              *

+ * Unless required by applicable law or agreed to in writing,   *

+ * software distributed under the License is distributed on an  *

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+ * KIND, either express or implied.  See the License for the    *

+ * specific language governing permissions and limitations      *

+ * under the License.                                           *

+ -->

+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">

+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>

+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">

+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>

+</listAttribute>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/scripts/etch-eclipse.bat"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-q&#13;&#10;-b java&#13;&#10;-n&#13;&#10;-d ../../../target/generated-sources/main/etch/java&#13;&#10;${resource_name}"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${container_loc}"/>

+</launchConfiguration>

diff --git a/scripts/Etch - xml.launch b/scripts/Etch - xml.launch
new file mode 100644
index 0000000..c69c898
--- /dev/null
+++ b/scripts/Etch - xml.launch
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!--

+ * Licensed to the Apache Software Foundation (ASF) under one   *

+ * or more contributor license agreements.  See the NOTICE file *

+ * distributed with this work for additional information        *

+ * regarding copyright ownership.  The ASF licenses this file   *

+ * to you under the Apache License, Version 2.0 (the            *

+ * "License"); you may not use this file except in compliance   *

+ * with the License.  You may obtain a copy of the License at   *

+ *                                                              *

+ *   http://www.apache.org/licenses/LICENSE-2.0                 *

+ *                                                              *

+ * Unless required by applicable law or agreed to in writing,   *

+ * software distributed under the License is distributed on an  *

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *

+ * KIND, either express or implied.  See the License for the    *

+ * specific language governing permissions and limitations      *

+ * under the License.                                           *

+ -->

+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">

+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>

+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">

+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>

+</listAttribute>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/scripts/etch-eclipse.bat"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-q&#13;&#10;-b xml&#13;&#10;-n&#13;&#10;-d ../../../target/generated-sources/main/etch/xml&#13;&#10;${resource_name}"/>

+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${container_loc}"/>

+</launchConfiguration>

diff --git a/scripts/README.txt b/scripts/README.txt
new file mode 100644
index 0000000..045de11
--- /dev/null
+++ b/scripts/README.txt
@@ -0,0 +1,15 @@
+These scripts and launch configurations are used in conjunction with eclipse.
+
+NOTE: These are windows versions. If you are using unix, you'll have to come up
+with your own versions of these.
+
+In order for these scripts to work properly, you also need to add a variable to
+your environment before starting eclipse:
+
+ETCH_DEPENDENT_JARS=C:\workspace-etch\tools\velocity\1.5\velocity-dep-1.5.jar
+
+If you're using clover, you'll need to add clover to that:
+
+ETCH_DEPENDENT_JARS=C:\workspace-etch\tools\velocity\1.5\velocity-dep-1.5.jar;C:\workspace-etch\tools\clover-ant\2.3.2\lib\clover.jar
+
+In the above, please edit the path as appropriate for your local environment.
diff --git a/scripts/antsetup.bat b/scripts/antsetup.bat
new file mode 100644
index 0000000..192d4da
--- /dev/null
+++ b/scripts/antsetup.bat
@@ -0,0 +1,50 @@
+@rem  Licensed to the Apache Software Foundation (ASF) under one   *
+@rem  or more contributor license agreements.  See the NOTICE file *
+@rem  distributed with this work for additional information        *
+@rem  regarding copyright ownership.  The ASF licenses this file   *
+@rem  to you under the Apache License, Version 2.0 (the            *
+@rem  "License"); you may not use this file except in compliance   *
+@rem  with the License.  You may obtain a copy of the License at   *
+@rem                                                               *
+@rem    http://www.apache.org/licenses/LICENSE-2.0                 *
+@rem                                                               *
+@rem  Unless required by applicable law or agreed to in writing,   *
+@rem  software distributed under the License is distributed on an  *
+@rem  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+@rem  KIND, either express or implied.  See the License for the    *
+@rem  specific language governing permissions and limitations      *
+@rem  under the License.                                           *
+
+rem -- java builds --
+
+set TOOLS_DIR=C:\wks\tools
+set ANT_HOME=%TOOLS_DIR%\apache-ant\1.7.0
+rem set JAVA_HOME=C:\Program Files\Java\jdk1.6.0_06
+rem optional
+rem set CLOVER_HOME=%TOOLS_DIR%\clover-ant\2.3.2
+rem /optional
+PATH %ANT_HOME%\bin;%JAVA_HOME%\bin;%PATH%
+
+rem -- dotnet builds --
+
+rem optional
+set DOTNET_HOME=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
+set NUNIT_HOME=%TOOLS_DIR%\NUnit\2.4.7
+PATH %DOTNET_HOME%;%NUNIT_HOME%\bin;%PATH%
+rem /optional
+
+rem -- mono builds --
+
+rem optional
+rem set MONO_HOME=...
+rem /optional
+
+rem -- installer builds --
+
+rem optional
+set NSIS_HOME=%TOOLS_DIR%\nsis\2.23
+rem /optional
+
+rem -- standalone example builds --
+
+rem set ETCH_HOME=...
diff --git a/scripts/compEtchFilesForCsharp.bash b/scripts/compEtchFilesForCsharp.bash
new file mode 100755
index 0000000..76e0385
--- /dev/null
+++ b/scripts/compEtchFilesForCsharp.bash
@@ -0,0 +1,73 @@
+#!/usr/local/bin/bash
+#  Licensed to the Apache Software Foundation (ASF) under one   *
+#  or more contributor license agreements.  See the NOTICE file *
+#  distributed with this work for additional information        *
+#  regarding copyright ownership.  The ASF licenses this file   *
+#  to you under the Apache License, Version 2.0 (the            *
+#  "License"); you may not use this file except in compliance   *
+#  with the License.  You may obtain a copy of the License at   *
+#                                                               *
+#    http://www.apache.org/licenses/LICENSE-2.0                 *
+#                                                               *
+#  Unless required by applicable law or agreed to in writing,   *
+#  software distributed under the License is distributed on an  *
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+#  KIND, either express or implied.  See the License for the    *
+#  specific language governing permissions and limitations      *
+#  under the License.                                           *
+
+set -e
+#set -x
+
+q=-q
+b="-b csharp"
+d="-d ../../../target/generated-sources/main/etch/csharp"
+i="-I ."
+n=-n
+
+walf="-w all,force"
+ 
+testsdir=tests/src/main/etch
+examplesdir=examples
+
+x=`pwd`/
+
+pushd $testsdir > /dev/null
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Async.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Bar.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Baz.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        BigIdl.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Closing.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Cuae.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Foo.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Inheritance.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i $walf  Test1.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Test2.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Test3.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Test4.etch
+# *** Test5.etch is a negative test ***
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Test6.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i $walf  TestIncludes.etch
+# *** TestReservedWords.etch is a negative test ***
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Types.etch
+popd > /dev/null
+
+pushd $examplesdir > /dev/null
+
+pushd chat/src/main/etch > /dev/null
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Chat.etch
+popd > /dev/null
+
+pushd distmap/src/main/etch > /dev/null
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        DistributedHashTable.etch
+popd > /dev/null
+
+pushd example/src/main/etch > /dev/null
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Example.etch
+popd > /dev/null
+
+pushd perf/src/main/etch > /dev/null
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Perf.etch
+popd > /dev/null
+
+popd > /dev/null
diff --git a/scripts/compEtchFilesForCsharp.bat b/scripts/compEtchFilesForCsharp.bat
new file mode 100644
index 0000000..377ffa7
--- /dev/null
+++ b/scripts/compEtchFilesForCsharp.bat
@@ -0,0 +1,72 @@
+@rem  Licensed to the Apache Software Foundation (ASF) under one   *
+@rem  or more contributor license agreements.  See the NOTICE file *
+@rem  distributed with this work for additional information        *
+@rem  regarding copyright ownership.  The ASF licenses this file   *
+@rem  to you under the Apache License, Version 2.0 (the            *
+@rem  "License"); you may not use this file except in compliance   *
+@rem  with the License.  You may obtain a copy of the License at   *
+@rem                                                               *
+@rem    http://www.apache.org/licenses/LICENSE-2.0                 *
+@rem                                                               *
+@rem  Unless required by applicable law or agreed to in writing,   *
+@rem  software distributed under the License is distributed on an  *
+@rem  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+@rem  KIND, either express or implied.  See the License for the    *
+@rem  specific language governing permissions and limitations      *
+@rem  under the License.                                           *
+@set q=-q
+@set b=-b csharp
+@set d=-d ../../../target/generated-sources/main/etch/csharp
+@set i=-I .
+@set n=-n
+
+@set walf=-w all,force
+
+@set testsdir=tests\src\main\etch
+@set examplesdir=examples
+
+@set x=%CD%\
+@pushd %testsdir%
+
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Async.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Bar.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Baz.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        BigIdl.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Closing.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Cuae.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Foo.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Inheritance.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i% %walf% Test1.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Test2.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Test3.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Test4.etch
+@rem *** Test5.etch is a negative test ***
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Test6.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i% %walf% TestIncludes.etch
+@rem *** TestReservedWords.etch is a negative test ***
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Types.etch
+
+@popd
+@pushd %examplesdir%
+
+@pushd chat\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Chat.etch
+@popd
+
+@pushd distmap\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        DistributedHashTable.etch
+@popd
+
+@pushd example\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Example.etch
+@popd
+
+@pushd perf\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Perf.etch
+@popd
+
+@popd
+
+@pushd interoptester\example\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        IOT.etch
+@popd
diff --git a/scripts/compEtchFilesForJava.bash b/scripts/compEtchFilesForJava.bash
new file mode 100755
index 0000000..b630794
--- /dev/null
+++ b/scripts/compEtchFilesForJava.bash
@@ -0,0 +1,73 @@
+#!/usr/local/bin/bash
+#  Licensed to the Apache Software Foundation (ASF) under one   *
+#  or more contributor license agreements.  See the NOTICE file *
+#  distributed with this work for additional information        *
+#  regarding copyright ownership.  The ASF licenses this file   *
+#  to you under the Apache License, Version 2.0 (the            *
+#  "License"); you may not use this file except in compliance   *
+#  with the License.  You may obtain a copy of the License at   *
+#                                                               *
+#    http://www.apache.org/licenses/LICENSE-2.0                 *
+#                                                               *
+#  Unless required by applicable law or agreed to in writing,   *
+#  software distributed under the License is distributed on an  *
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+#  KIND, either express or implied.  See the License for the    *
+#  specific language governing permissions and limitations      *
+#  under the License.                                           *
+
+set -e
+#set -x
+
+q=-q
+b="-b java"
+d="-d ../../../target/generated-sources/main/etch/java"
+i="-I ."
+n=-n
+
+walf="-w all,force"
+ 
+testsdir=tests/src/main/etch
+examplesdir=examples
+
+x=`pwd`/
+
+pushd $testsdir > /dev/null
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Async.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Bar.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Baz.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        BigIdl.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Closing.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Cuae.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Foo.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Inheritance.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i $walf  Test1.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Test2.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Test3.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Test4.etch
+# *** Test5.etch is a negative test ***
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Test6.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i $walf  TestIncludes.etch
+# *** TestReservedWords.etch is a negative test ***
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Types.etch
+popd > /dev/null
+
+pushd $examplesdir > /dev/null
+
+pushd chat/src/main/etch > /dev/null
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Chat.etch
+popd > /dev/null
+
+pushd distmap/src/main/etch > /dev/null
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        DistributedHashTable.etch
+popd > /dev/null
+
+pushd example/src/main/etch > /dev/null
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Example.etch
+popd > /dev/null
+
+pushd perf/src/main/etch > /dev/null
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Perf.etch
+popd > /dev/null
+
+popd > /dev/null
diff --git a/scripts/compEtchFilesForJava.bat b/scripts/compEtchFilesForJava.bat
new file mode 100644
index 0000000..fe567c2
--- /dev/null
+++ b/scripts/compEtchFilesForJava.bat
@@ -0,0 +1,77 @@
+@rem  Licensed to the Apache Software Foundation (ASF) under one   *
+@rem  or more contributor license agreements.  See the NOTICE file *
+@rem  distributed with this work for additional information        *
+@rem  regarding copyright ownership.  The ASF licenses this file   *
+@rem  to you under the Apache License, Version 2.0 (the            *
+@rem  "License"); you may not use this file except in compliance   *
+@rem  with the License.  You may obtain a copy of the License at   *
+@rem                                                               *
+@rem    http://www.apache.org/licenses/LICENSE-2.0                 *
+@rem                                                               *
+@rem  Unless required by applicable law or agreed to in writing,   *
+@rem  software distributed under the License is distributed on an  *
+@rem  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+@rem  KIND, either express or implied.  See the License for the    *
+@rem  specific language governing permissions and limitations      *
+@rem  under the License.                                           *
+@set q=-q
+@set b=-b java
+@set d=-d ../../../target/generated-sources/main/etch/java
+@set i=-I .
+@set n=-n
+
+@set walf=-w all,force
+
+@set testsdir=tests\src\main\etch
+@set examplesdir=examples
+
+@set x=%CD%\
+@pushd %testsdir%
+
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Async.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Bar.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Baz.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        BigIdl.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Closing.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Cuae.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Foo.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Inheritance.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i% %walf% Test1.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Test2.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Test3.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Test4.etch
+@rem *** Test5.etch is a negative test ***
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Test6.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i% %walf% TestIncludes.etch
+@rem *** TestReservedWords.etch is a negative test ***
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Types.etch
+
+@popd
+@pushd %examplesdir%
+
+@pushd chat\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Chat.etch
+@popd
+
+@pushd distmap\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        DistributedHashTable.etch
+@popd
+
+@pushd example\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Example.etch
+@popd
+
+@pushd perf\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Perf.etch
+@popd
+
+@popd
+
+@pushd services\config\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Configuration.etch
+@popd
+
+@pushd interoptester\example\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        IOT.etch
+@popd
+
diff --git a/scripts/compEtchFilesForXml.bash b/scripts/compEtchFilesForXml.bash
new file mode 100755
index 0000000..d5c3e04
--- /dev/null
+++ b/scripts/compEtchFilesForXml.bash
@@ -0,0 +1,73 @@
+#!/usr/local/bin/bash
+#  Licensed to the Apache Software Foundation (ASF) under one   *
+#  or more contributor license agreements.  See the NOTICE file *
+#  distributed with this work for additional information        *
+#  regarding copyright ownership.  The ASF licenses this file   *
+#  to you under the Apache License, Version 2.0 (the            *
+#  "License"); you may not use this file except in compliance   *
+#  with the License.  You may obtain a copy of the License at   *
+#                                                               *
+#    http://www.apache.org/licenses/LICENSE-2.0                 *
+#                                                               *
+#  Unless required by applicable law or agreed to in writing,   *
+#  software distributed under the License is distributed on an  *
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+#  KIND, either express or implied.  See the License for the    *
+#  specific language governing permissions and limitations      *
+#  under the License.                                           *
+
+set -e
+#set -x
+
+q=-q
+b="-b xml"
+d="-d ../../../target/generated-sources/main/etch/xml"
+i="-I ."
+n=-n
+
+walf="-w all,force"
+ 
+testsdir=tests/src/main/etch
+examplesdir=examples
+
+x=`pwd`/
+
+pushd $testsdir > /dev/null
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Async.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Bar.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Baz.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        BigIdl.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Closing.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Cuae.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Foo.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Inheritance.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i $walf  Test1.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Test2.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Test3.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Test4.etch
+# *** Test5.etch is a negative test ***
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Test6.etch
+${x}scripts/etch-eclipse.bash $q $b $n $d $i $walf  TestIncludes.etch
+# *** TestReservedWords.etch is a negative test ***
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Types.etch
+popd > /dev/null
+
+pushd $examplesdir > /dev/null
+
+pushd chat/src/main/etch > /dev/null
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Chat.etch
+popd > /dev/null
+
+pushd distmap/src/main/etch > /dev/null
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        DistributedHashTable.etch
+popd > /dev/null
+
+pushd example/src/main/etch > /dev/null
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Example.etch
+popd > /dev/null
+
+pushd perf/src/main/etch > /dev/null
+${x}scripts/etch-eclipse.bash $q $b $n $d $i        Perf.etch
+popd > /dev/null
+
+popd > /dev/null
diff --git a/scripts/compEtchFilesForXml.bat b/scripts/compEtchFilesForXml.bat
new file mode 100644
index 0000000..3d981fe
--- /dev/null
+++ b/scripts/compEtchFilesForXml.bat
@@ -0,0 +1,72 @@
+@rem  Licensed to the Apache Software Foundation (ASF) under one   *
+@rem  or more contributor license agreements.  See the NOTICE file *
+@rem  distributed with this work for additional information        *
+@rem  regarding copyright ownership.  The ASF licenses this file   *
+@rem  to you under the Apache License, Version 2.0 (the            *
+@rem  "License"); you may not use this file except in compliance   *
+@rem  with the License.  You may obtain a copy of the License at   *
+@rem                                                               *
+@rem    http://www.apache.org/licenses/LICENSE-2.0                 *
+@rem                                                               *
+@rem  Unless required by applicable law or agreed to in writing,   *
+@rem  software distributed under the License is distributed on an  *
+@rem  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+@rem  KIND, either express or implied.  See the License for the    *
+@rem  specific language governing permissions and limitations      *
+@rem  under the License.                                           *
+@set q=-q
+@set b=-b xml
+@set d=-d ../../../target/generated-sources/main/etch/xml
+@set i=-I .
+@set n=-n
+
+@set walf=-w all,force
+
+@set testsdir=tests\src\main\etch
+@set examplesdir=examples
+
+@set x=%CD%\
+@pushd %testsdir%
+
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Async.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Bar.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Baz.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        BigIdl.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Closing.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Cuae.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Foo.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Inheritance.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i% %walf% Test1.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Test2.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Test3.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Test4.etch
+@rem *** Test5.etch is a negative test ***
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Test6.etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i% %walf% TestIncludes.etch
+@rem *** TestReservedWords.etch is a negative test ***
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Types.etch
+
+@popd
+@pushd %examplesdir%
+
+@pushd chat\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Chat.etch
+@popd
+
+@pushd distmap\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        DistributedHashTable.etch
+@popd
+
+@pushd example\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Example.etch
+@popd
+
+@pushd perf\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        Perf.etch
+@popd
+
+@popd
+
+@pushd interoptester\example\src\main\etch
+@call %x%scripts\etch-eclipse.bat %q% %b% %n% %d% %i%        IOT.etch
+@popd
diff --git a/scripts/etch-eclipse.bash b/scripts/etch-eclipse.bash
new file mode 100755
index 0000000..54274be
--- /dev/null
+++ b/scripts/etch-eclipse.bash
@@ -0,0 +1,43 @@
+#!/usr/local/bin/bash
+#  Licensed to the Apache Software Foundation (ASF) under one   *
+#  or more contributor license agreements.  See the NOTICE file *
+#  distributed with this work for additional information        *
+#  regarding copyright ownership.  The ASF licenses this file   *
+#  to you under the Apache License, Version 2.0 (the            *
+#  "License"); you may not use this file except in compliance   *
+#  with the License.  You may obtain a copy of the License at   *
+#                                                               *
+#    http://www.apache.org/licenses/LICENSE-2.0                 *
+#                                                               *
+#  Unless required by applicable law or agreed to in writing,   *
+#  software distributed under the License is distributed on an  *
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+#  KIND, either express or implied.  See the License for the    *
+#  specific language governing permissions and limitations      *
+#  under the License.                                           *
+
+#set -x
+set -e
+
+#echo etch $*
+#exit
+
+# Copyright 2008 Cisco Systems
+# This script is for the support of the various launch configurations
+# used with eclipse.
+
+if test -z "$ETCH_DEPENDENT_JARS"; then
+echo Environment variable ETCH_DEPENDENT_JARS not set.
+exit 1
+fi
+
+ETCH_HOME=`dirname "$0"`/..
+
+if test \! -d "$ETCH_HOME/bin/etch"; then
+#echo Cannot find etch classes.
+exit 1
+fi
+
+#echo java -cp "$ETCH_HOME/bin:$ETCH_DEPENDENT_JARS" etch.compiler.EtchMain ${1+"$@"}
+echo etch ${1+"$@"}
+java -cp "$ETCH_HOME/bin:$ETCH_DEPENDENT_JARS" etch.compiler.EtchMain ${1+"$@"}
diff --git a/scripts/etch-eclipse.bat b/scripts/etch-eclipse.bat
new file mode 100644
index 0000000..45b3c66
--- /dev/null
+++ b/scripts/etch-eclipse.bat
@@ -0,0 +1,35 @@
+@rem  Licensed to the Apache Software Foundation (ASF) under one   *
+@rem  or more contributor license agreements.  See the NOTICE file *
+@rem  distributed with this work for additional information        *
+@rem  regarding copyright ownership.  The ASF licenses this file   *
+@rem  to you under the Apache License, Version 2.0 (the            *
+@rem  "License"); you may not use this file except in compliance   *
+@rem  with the License.  You may obtain a copy of the License at   *
+@rem                                                               *
+@rem    http://www.apache.org/licenses/LICENSE-2.0                 *
+@rem                                                               *
+@rem  Unless required by applicable law or agreed to in writing,   *
+@rem  software distributed under the License is distributed on an  *
+@rem  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+@rem  KIND, either express or implied.  See the License for the    *
+@rem  specific language governing permissions and limitations      *
+@rem  under the License.                                           *
+@echo off
+
+rem This script is for the support of the various launch configurations
+rem used with eclipse.
+
+if "%ETCH_DEPENDENT_JARS%" neq "" goto test_etch_exist
+echo Environment variable ETCH_DEPENDENT_JARS not set.
+exit /b 1
+goto :eof
+
+:test_etch_exist
+if exist "%~dp0..\bin\org\apache\etch" goto run_etch
+echo Cannot find etch classes.
+exit /b 1
+goto :eof
+
+:run_etch
+echo etch %*
+java -cp "%~dp0..\bin;%ETCH_DEPENDENT_JARS%" org.apache.etch.compiler.EtchMain %*
diff --git a/scripts/vs-2k5-task.bat b/scripts/vs-2k5-task.bat
new file mode 100644
index 0000000..ace8537
--- /dev/null
+++ b/scripts/vs-2k5-task.bat
@@ -0,0 +1,66 @@
+@rem  Licensed to the Apache Software Foundation (ASF) under one   *
+@rem  or more contributor license agreements.  See the NOTICE file *
+@rem  distributed with this work for additional information        *
+@rem  regarding copyright ownership.  The ASF licenses this file   *
+@rem  to you under the Apache License, Version 2.0 (the            *
+@rem  "License"); you may not use this file except in compliance   *
+@rem  with the License.  You may obtain a copy of the License at   *
+@rem                                                               *
+@rem    http://www.apache.org/licenses/LICENSE-2.0                 *
+@rem                                                               *
+@rem  Unless required by applicable law or agreed to in writing,   *
+@rem  software distributed under the License is distributed on an  *
+@rem  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+@rem  KIND, either express or implied.  See the License for the    *
+@rem  specific language governing permissions and limitations      *
+@rem  under the License.                                           *
+
+@rem -------------------------------------------------------------
+@rem Build a standard Visual Studio .NET solution.
+@rem
+@rem Command line arguments:
+@rem    %1 -> The filename of the solution to build
+@rem    %2 -> The configuration to build
+@rem -------------------------------------------------------------
+
+@setlocal
+@set LIB=
+@set INCLUDE=
+@set VsDotNet=devenv.com
+@if "%VsDotNetDir%"==""  set VsDotNetDir=%VS80COMNTOOLS%
+call "%VsDotNetDir%\vsvars32.bat" >nul
+
+@if "%3"=="" goto withoutproject
+
+@if /i "%2"=="clean" goto clean
+@if /i "%2"=="Clean" goto clean
+
+%VsDotNet% %1 /build %2 /project %3
+@goto end
+
+:clean
+%VsDotNet% %1 /clean Debug /project %3
+@if NOT %ERRORLEVEL%==0 @goto end
+
+%VsDotNet% %1 /clean Release /project %3
+@goto end
+
+:withoutproject
+
+@if /i "%2"=="clean" goto cleannoproject
+@if /i "%2"=="Clean" goto cleannoproject
+
+%VsDotNet% %1 /build %2
+@goto end
+
+:cleannoproject
+%VsDotNet% %1 /clean Debug
+@if NOT %ERRORLEVEL%==0 @goto end
+
+%VsDotNet% %1 /clean Release
+@goto end
+
+:end
+@echo.
+@echo ERRORLEVEL = %ERRORLEVEL%
+@exit %ERRORLEVEL%
diff --git a/services/config/configtestplan.txt b/services/config/configtestplan.txt
new file mode 100644
index 0000000..f23ae2a
--- /dev/null
+++ b/services/config/configtestplan.txt
@@ -0,0 +1,37 @@
+possible yaml updates:
+
+update key value in map: scalar -> scalar [update1]
+add scalar key to map [update2]
+remove scalar key from map [update3]
+
+update element in list: scalar -> scalar [update4]
+add scalar element to list [update5]
+remove scalar element from list [update6]
+
+add map key to map [update7]
+add list key to map [update8]
+remove map key from map [update9]
+remove list key from map [update10]
+
+add map element to list [update11]
+add list element to list [update12]
+remove map element from list [update13]
+remove list element from list [update14]
+
+update key value in map: scalar -> map [update15]
+update key value in map: scalar -> list [update16]
+update key value in map: map -> scalar [update17]
+update key value in map: map -> map [update18]
+update key value in map: map -> list [update19]
+update key value in map: list -> scalar [update20]
+update key value in map: list -> map [update21]
+update key value in map: list -> list [update22]
+
+update element in list: scalar -> map [update23]
+update element in list: scalar -> list [update24]
+update element in list: map -> scalar [update25]
+update element in list: map -> map [update26]
+update element in list: map -> list [update27]
+update element in list: list -> scalar [update28]
+update element in list: list -> map [update29]
+update element in list: list -> list [update30]
diff --git a/services/config/empty.yml b/services/config/empty.yml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/services/config/empty.yml
diff --git a/services/config/example/local.yml b/services/config/example/local.yml
new file mode 100644
index 0000000..8dd685b
--- /dev/null
+++ b/services/config/example/local.yml
@@ -0,0 +1,2 @@
+configUri: tcp://localhost:4001/services/config/example/remote?TcpTransport.reconnectDelay=4000

+blah: 2
\ No newline at end of file
diff --git a/services/config/example/local2.yml b/services/config/example/local2.yml
new file mode 100644
index 0000000..c5d820b
--- /dev/null
+++ b/services/config/example/local2.yml
@@ -0,0 +1 @@
+listenUri: tcp://0.0.0.0:4002

diff --git a/services/config/example/remote.yml b/services/config/example/remote.yml
new file mode 100644
index 0000000..c5d820b
--- /dev/null
+++ b/services/config/example/remote.yml
@@ -0,0 +1 @@
+listenUri: tcp://0.0.0.0:4002

diff --git a/services/config/example/src/main/etch/ConfigExample.etch b/services/config/example/src/main/etch/ConfigExample.etch
new file mode 100644
index 0000000..8503cf8
--- /dev/null
+++ b/services/config/example/src/main/etch/ConfigExample.etch
@@ -0,0 +1,6 @@
+module org.apache.etch.services.config.example
+
+service ConfigExample
+{
+	int add( int x, int y )
+}
diff --git a/services/config/example/src/main/java/org/apache/etch/services/config/example/ImplConfigExampleClient.java b/services/config/example/src/main/java/org/apache/etch/services/config/example/ImplConfigExampleClient.java
new file mode 100644
index 0000000..6e7e77b
--- /dev/null
+++ b/services/config/example/src/main/java/org/apache/etch/services/config/example/ImplConfigExampleClient.java
@@ -0,0 +1,49 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.services.config.example;
+
+/**
+ * Your custom implementation of BaseConfigExampleClient. Add methods here to provide
+ * implementations of messages from the server.
+ */
+public class ImplConfigExampleClient extends BaseConfigExampleClient
+{
+	/**
+	 * Constructs the ImplConfigExampleClient.
+	 *
+	 * @param server a connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	public ImplConfigExampleClient( RemoteConfigExampleServer server )
+	{
+		this.server = server;
+	}
+	
+	/**
+	 * A connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	@SuppressWarnings( "unused" )
+	private final RemoteConfigExampleServer server;
+
+	// TODO insert methods here to provide implementations of ConfigExampleClient
+	// messages from the server.
+}
\ No newline at end of file
diff --git a/services/config/example/src/main/java/org/apache/etch/services/config/example/ImplConfigExampleServer.java b/services/config/example/src/main/java/org/apache/etch/services/config/example/ImplConfigExampleServer.java
new file mode 100644
index 0000000..a9e70d1
--- /dev/null
+++ b/services/config/example/src/main/java/org/apache/etch/services/config/example/ImplConfigExampleServer.java
@@ -0,0 +1,52 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.services.config.example;
+
+/**
+ * Your custom implementation of BaseConfigExampleServer. Add methods here to provide
+ * implementations of messages from the client.
+ */
+public class ImplConfigExampleServer extends BaseConfigExampleServer
+{
+	/**
+	 * Constructs the ImplConfigExampleServer.
+	 *
+	 * @param client a connection to the client session. Use this to send a
+	 * message to the client.
+	 */
+	public ImplConfigExampleServer( RemoteConfigExampleClient client )
+	{
+		this.client = client;
+	}
+	
+	/**
+	 * A connection to the client session. Use this to send a
+	 * message to the client.
+	 */
+	@SuppressWarnings( "unused" )
+	private final RemoteConfigExampleClient client;
+
+	@Override
+	public Integer add( Integer x, Integer y )
+	{
+		return x + y;
+	}
+}
diff --git a/services/config/example/src/main/java/org/apache/etch/services/config/example/MainConfigExampleClient.java b/services/config/example/src/main/java/org/apache/etch/services/config/example/MainConfigExampleClient.java
new file mode 100644
index 0000000..1e3d3f0
--- /dev/null
+++ b/services/config/example/src/main/java/org/apache/etch/services/config/example/MainConfigExampleClient.java
@@ -0,0 +1,58 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.services.config.example;
+
+/**
+ * Main program for ConfigExampleClient. This program makes a connection to the
+ * listener created by MainConfigExampleListener.
+ */
+public class MainConfigExampleClient implements ConfigExampleHelper.ConfigExampleClientFactory
+{
+	/**
+	 * Main program for ConfigExampleClient.
+	 * 
+	 * @param args command line arguments.
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		// TODO Change to correct URI
+		String uri = "tcp://localhost:4002";
+		
+		RemoteConfigExampleServer server = ConfigExampleHelper.newServer( uri, null,
+			new MainConfigExampleClient() );
+
+		// Connect to the service
+		server._startAndWaitUp( 4000 );
+
+		Integer z = server.add( 4, 5 );
+		System.out.println( "add 4, 5 => "+z );
+
+		// Disconnect from the service
+		server._stopAndWaitDown( 4000 );
+	}
+
+	public ConfigExampleClient newConfigExampleClient( RemoteConfigExampleServer server )
+		throws Exception
+	{
+		return new ImplConfigExampleClient( server );
+	}
+}
diff --git a/services/config/example/src/main/java/org/apache/etch/services/config/example/MainConfigExampleListener1.java b/services/config/example/src/main/java/org/apache/etch/services/config/example/MainConfigExampleListener1.java
new file mode 100644
index 0000000..478ca2a
--- /dev/null
+++ b/services/config/example/src/main/java/org/apache/etch/services/config/example/MainConfigExampleListener1.java
@@ -0,0 +1,59 @@
+/*
+ * $Id$
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.etch.services.config.example;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.services.config.example.ConfigExampleHelper.ConfigExampleServerFactory;
+import org.apache.etch.util.core.io.Transport;
+
+/**
+ * Main program for ConfigExampleServer. This program makes a listener to accept
+ * connections from MainConfigExampleClient. This is a standard etch listener.
+ */
+public class MainConfigExampleListener1 implements ConfigExampleServerFactory
+{
+	/**
+	 * Main program for ConfigExampleServer.
+	 * 
+	 * @param args command line arguments.
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		// Define the listener uri.
+		String uri = "tcp://0.0.0.0:4002";
+		System.out.println( "listen uri = " + uri );
+
+		// Create the listener stack.
+		ServerFactory listener = ConfigExampleHelper.newListener( uri, null,
+			new MainConfigExampleListener1() );
+		System.out.println( "listener created " + listener );
+
+		// Start the listener stack.
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+		System.out.println( "listener started " + listener );
+	}
+
+	public ConfigExampleServer newConfigExampleServer(
+		RemoteConfigExampleClient client )
+	{
+		return new ImplConfigExampleServer( client );
+	}
+}
diff --git a/services/config/example/src/main/java/org/apache/etch/services/config/example/MainConfigExampleListener2.java b/services/config/example/src/main/java/org/apache/etch/services/config/example/MainConfigExampleListener2.java
new file mode 100644
index 0000000..6108644
--- /dev/null
+++ b/services/config/example/src/main/java/org/apache/etch/services/config/example/MainConfigExampleListener2.java
@@ -0,0 +1,70 @@
+/*
+ * $Id$
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.etch.services.config.example;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.services.config.ConfigurationServer;
+import org.apache.etch.services.config.YamlConfig;
+import org.apache.etch.services.config.example.ConfigExampleHelper.ConfigExampleServerFactory;
+import org.apache.etch.util.core.io.Transport;
+
+/**
+ * Main program for ConfigExampleServer. This program makes a listener to accept
+ * connections from MainConfigExampleClient. This is a standard etch listener
+ * modified to load the listen uri from a local config at startup.
+ */
+public class MainConfigExampleListener2 implements ConfigExampleServerFactory
+{
+	private static final String LOCAL = "services/config/example/local2";
+
+	private static final String LISTEN_URI = "listenUri";
+
+	/**
+	 * Main program for ConfigExampleServer.
+	 * 
+	 * @param args command line arguments.
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		// Open the local config.
+		ConfigurationServer local = new YamlConfig( null, LOCAL );
+		System.out.println( "loaded local configuration named '" + LOCAL + "'" );
+
+		// Get the listener uri from the local config.
+		String uri = local.getStringPath( local.getRoot(), LISTEN_URI );
+		System.out.println( "listen uri = " + uri );
+
+		// Create the listener stack.
+		ServerFactory listener = ConfigExampleHelper.newListener( uri, null,
+			new MainConfigExampleListener2() );
+		System.out.println( "listener created " + listener );
+
+		// Start the listener stack.
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+		System.out.println( "listener started " + listener );
+	}
+
+	public ConfigExampleServer newConfigExampleServer(
+		RemoteConfigExampleClient client )
+	{
+		return new ImplConfigExampleServer( client );
+	}
+}
diff --git a/services/config/example/src/main/java/org/apache/etch/services/config/example/MainConfigExampleListener3.java b/services/config/example/src/main/java/org/apache/etch/services/config/example/MainConfigExampleListener3.java
new file mode 100644
index 0000000..02b8922
--- /dev/null
+++ b/services/config/example/src/main/java/org/apache/etch/services/config/example/MainConfigExampleListener3.java
@@ -0,0 +1,112 @@
+/*
+ * $Id$
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.etch.services.config.example;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.services.config.ConfigurationClient;
+import org.apache.etch.services.config.ConfigurationServer;
+import org.apache.etch.services.config.YamlConfig;
+import org.apache.etch.services.config.example.ConfigExampleHelper.ConfigExampleServerFactory;
+import org.apache.etch.util.core.io.Transport;
+
+/**
+ * Main program for ConfigExampleServer. This program makes a listener to accept
+ * connections from MainConfigExampleClient. This is a standard etch listener
+ * modified to load the listen uri from a local config file at startup and
+ * whenever the file changes.
+ */
+public class MainConfigExampleListener3 implements ConfigExampleServerFactory
+{
+	private static final String LOCAL = "services/config/example/local2";
+
+	private static final String LISTEN_URI = "listenUri";
+
+	/**
+	 * Main program for ConfigExampleServer.
+	 * 
+	 * @param args command line arguments.
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		// Create the server session factory.
+		factory = new MainConfigExampleListener3();
+		
+		// Open the local config.
+		local = new YamlConfig( new MyLocalConfigurationClient(), LOCAL );
+		System.out.println( "loaded local configuration named '" + LOCAL + "'" );
+
+		// Subscribe to changes in the local config.
+		local.subscribe( local.getRoot() );
+		System.out.println( "subscribed to changes in '" + LOCAL + "'" );
+	}
+	
+	private static ConfigExampleServerFactory factory;
+	
+	private static ConfigurationServer local;
+	
+	private static class MyLocalConfigurationClient implements
+		ConfigurationClient
+	{
+		public void configValuesChanged( Object[] updated )
+		{
+			System.out.println( "local config changed" );
+			try
+			{
+				resetListener();
+			}
+			catch ( Exception e )
+			{
+				e.printStackTrace();
+			}
+		}
+	}
+
+	private static void resetListener() throws Exception
+	{
+		// Stop the old listener.
+		if (listener != null)
+		{
+			System.out.println( "stopping listener " + listener );
+			listener.transportControl( Transport.STOP_AND_WAIT_DOWN, 4000 );
+			listener = null;
+		}
+		
+		// Get the listener uri from the local config.
+		String uri = local.getStringPath( local.getRoot(), LISTEN_URI );
+		System.out.println( "listen uri = " + uri );
+		
+		// Create the listener stack.
+		listener = ConfigExampleHelper.newListener( uri, null, factory );
+		System.out.println( "listener created " + listener );
+
+		// Start the listener stack.
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+		System.out.println( "listener started " + listener );
+	}
+	
+	private static ServerFactory listener;
+
+	public ConfigExampleServer newConfigExampleServer(
+		RemoteConfigExampleClient client )
+	{
+		return new ImplConfigExampleServer( client );
+	}
+}
diff --git a/services/config/example/src/main/java/org/apache/etch/services/config/example/MainConfigExampleListener4.java b/services/config/example/src/main/java/org/apache/etch/services/config/example/MainConfigExampleListener4.java
new file mode 100644
index 0000000..aba47b2
--- /dev/null
+++ b/services/config/example/src/main/java/org/apache/etch/services/config/example/MainConfigExampleListener4.java
@@ -0,0 +1,201 @@
+/*
+ * $Id$
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.etch.services.config.example;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.services.config.BaseConfigurationClient;
+import org.apache.etch.services.config.ConfigurationClient;
+import org.apache.etch.services.config.ConfigurationHelper;
+import org.apache.etch.services.config.ConfigurationServer;
+import org.apache.etch.services.config.RemoteConfigurationServer;
+import org.apache.etch.services.config.YamlConfig;
+import org.apache.etch.services.config.ConfigurationHelper.ConfigurationClientFactory;
+import org.apache.etch.services.config.example.ConfigExampleHelper.ConfigExampleServerFactory;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.io.Session;
+import org.apache.etch.util.core.io.Transport;
+
+/**
+ * Main program for ConfigExampleServer. This program makes a listener to accept
+ * connections from MainConfigExampleClient. This is a standard etch listener
+ * modified to load the listen uri from a remote config whenever it changes.
+ * The remote config is defined in a local config, which is also monitored for
+ * changes.
+ */
+public class MainConfigExampleListener4 implements ConfigExampleServerFactory
+{
+	private static final String LOCAL = "services/config/example/local";
+
+	private static final String CONFIG_URI = "configUri";
+
+	private static final String LISTEN_URI = "listenUri";
+
+	/**
+	 * Main program for ConfigExampleServer.
+	 * 
+	 * @param args command line arguments.
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		// Create the server session factory.
+		factory = new MainConfigExampleListener4();
+		
+		// Create the remote config client factory.
+		configClientFactory = new MyConfigurationClientFactory();
+		
+		// Open the local config.
+		local = new YamlConfig( new MyLocalConfigurationClient(), LOCAL );
+		System.out.println( "loaded local configuration named '" + LOCAL + "'" );
+
+		// Subscribe to changes in the local config.
+		local.subscribe( local.getRoot() );
+		System.out.println( "subscribed to changes in '" + LOCAL + "'" );
+	}
+
+	private static ConfigExampleServerFactory factory;
+	
+	private static ConfigurationClientFactory configClientFactory;
+
+	private static ConfigurationServer local;
+
+	private static class MyLocalConfigurationClient implements
+		ConfigurationClient
+	{
+		public void configValuesChanged( Object[] updated )
+		{
+			System.out.println( "local config changed" );
+			try
+			{
+				resetRemoteConfig();
+			}
+			catch ( Exception e )
+			{
+				e.printStackTrace();
+			}
+		}
+	}
+
+	private static void resetRemoteConfig() throws Exception
+	{
+		if (remote != null)
+		{
+			System.out.println( "stopping remote config" );
+			remote._stopAndWaitDown( 4000 );
+			remote = null;
+		}
+		
+		// Get the remote config uri from the local config.
+		configUri = local.getStringPath( local.getRoot(), CONFIG_URI );
+		System.out.println( "remote config uri = " + configUri );
+
+		// Create the remote config stack.
+		remote = ConfigurationHelper.newServer( configUri, null, configClientFactory );
+		System.out.println( "remote config created "+remote );
+		
+		// Start the remote config stack.
+		System.out.println( "starting remote config "+remote );
+		remote._start();
+	}
+
+	private static String configUri;
+	
+	private static RemoteConfigurationServer remote;
+
+	private static class MyConfigurationClientFactory implements
+		ConfigurationClientFactory
+	{
+		public ConfigurationClient newConfigurationClient(
+			RemoteConfigurationServer server ) throws Exception
+		{
+			return new MyRemoteConfigurationClient();
+		}
+	}
+
+	private static class MyRemoteConfigurationClient extends
+		BaseConfigurationClient
+	{
+		@Override
+		public void _sessionNotify( Object event ) throws Exception
+		{
+			if (event == Session.UP)
+			{
+				System.out.println( "remote config service connection is up" );
+				
+				String configName = new URL( configUri ).getUri();
+				System.out.println( "remote config name = '"
+					+ configName + "'" );
+				
+				root = remote.loadConfig( configName );
+				System.out.println( "loaded remote config named '"
+					+ configName + "'" );
+				
+				System.out.println( "subscribing to remote config" );
+				remote.subscribe( root );
+			}
+		}
+
+		@Override
+		public void configValuesChanged( Object[] updated )
+		{
+			try
+			{
+				resetListener();
+			}
+			catch ( Exception e )
+			{
+				e.printStackTrace();
+			}
+		}
+	}
+	
+	private static Object root;
+
+	private static void resetListener() throws Exception
+	{
+		// Stop the old listener.
+		if (listener != null)
+		{
+			System.out.println( "stopping listener " + listener );
+			listener.transportControl( Transport.STOP_AND_WAIT_DOWN, 4000 );
+			listener = null;
+		}
+		
+		// Get the listener uri from the remote config.
+		String uri = remote.getStringPath( root, LISTEN_URI );
+		System.out.println( "listen uri = " + uri );
+
+		// Create the listener stack.
+		listener = ConfigExampleHelper.newListener( uri, null, factory );
+		System.out.println( "listener created " + listener );
+		
+		// Start the Listener
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+		System.out.println( "listener started " + listener );
+	}
+
+	private static ServerFactory listener;
+
+	public ConfigExampleServer newConfigExampleServer(
+		RemoteConfigExampleClient client )
+	{
+		return new ImplConfigExampleServer( client );
+	}
+}
diff --git a/services/config/local.yml b/services/config/local.yml
new file mode 100644
index 0000000..46e1d1a
--- /dev/null
+++ b/services/config/local.yml
@@ -0,0 +1,2 @@
+---

+configUri: tcp://localhost:4001/services/config/remote

diff --git a/services/config/remote.yml b/services/config/remote.yml
new file mode 100644
index 0000000..3f94384
--- /dev/null
+++ b/services/config/remote.yml
@@ -0,0 +1,26 @@
+bool: true

+bool2: "false"

+int: 23

+int2: "34"

+int3: abc

+dbl: 4.5

+dbl2: "5.6"

+dbl3: 67

+dbl4: abc

+str: boo

+str2: false

+date: 12/19/2008

+date2: !java.util.Date 12/23/2008

+users:

+  fred: 1234

+  mary: 2345

+  alice: 9876

+  jack: 8765

+primes:

+  - 1

+  - 2

+  - 3

+  - 5

+  - 7

+  - 11

+  - 13

diff --git a/services/config/src/main/etch/Configuration.etch b/services/config/src/main/etch/Configuration.etch
new file mode 100644
index 0000000..ee51fc5
--- /dev/null
+++ b/services/config/src/main/etch/Configuration.etch
@@ -0,0 +1,426 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.services.config
+
+/**
+ * Configuration service provides access to configuration data. The data is
+ * modeled as a general tree structure with a root node which might be a scalar
+ * (boolean, int, double, string, Datetime), a List, or a Map. A List is
+ * indexed by int starting at 0, while a Map is indexed by non-empty string,
+ * generally following identifier syntax (case-sensitive, initial alpha then
+ * alphanumeric) but not required to. Each node in this tree is assigned an id.
+ * The id of the root node is null.
+ *
+ * At a given node in the tree, you may navigate up to the parent, down to the
+ * children, get the name, get the path (absolute, from the root), get the value
+ * if a scalar, enumerate the children if a List or Map, test if it is the root,
+ * a List, or a Map.
+ *
+ * This interface is only used to query configuration data, it does not include
+ * a facility to list available configurations, nor to manage configurations. It
+ * also does not include methods to alter existing configuration data, but it
+ * does allow you to subscribe to receive notification of changes.
+ *
+ * Configuration data is organized into separate spaces. The space is called out
+ * by name. You must have authorization to access the named space. There is no
+ * particular meaning to the name outside the interpretation given by the target
+ * service implementation. The configurations might come from a database, a
+ * directory tree of yaml files, etc. For services, anyway, a good idea would be
+ * to use the service name as it appears in the name service directory entry.
+ *
+ * Here is an example use of these interfaces:
+ *
+ * RemoteConfigurationServer server = ConfigurationHelper.newServer( ... );
+ * server._startAndWaitUp( 4000 );
+ * server.loadConfig( "org.apache.etch.services.ns.NameService/titan" );
+ * String host = server.getStringPath( null, "host" );
+ * int port = server.getIntegerPath( null, "port" );
+ *
+ * A path is a string delimited with '/' characters, much like a file system
+ * path. A path which begins with a '/' is absolute and begins at the root.
+ * Otherwise the path is relative to a specified node. The special names '.'
+ * and '..' may be used to refer to the current node and the parent node.
+ * When a path traverses a List, the index in the list is give as an integer in
+ * the path (e.g., /users/1/age). This would refer to the age of the 2nd user
+ * in a list of users. When a path is specified as null or blank, it is the same
+ * as '.'.
+ */
+@Timeout( 30000 )
+service Configuration
+{
+	/**
+	 * ConfigurationException is used to report any problem loading a
+	 * Configuration.
+	 * @param msg a text description of the problem.
+	 */
+	exception ConfigurationException( string msg )
+	
+	/**
+	 * Loads a configuration. Any previous configuration is discarded along
+	 * with any subscriptions. Depending upon the configuration service
+	 * capabilities, it may be able to monitor the configuration for changes
+	 * and automatically load them.
+	 * @param name the name of the configuration.
+	 * @return the id of the root node.
+	 * @throws ConfigurationException if there is any problem.
+	 */
+	@Authorize( canLoad, name )
+	object loadConfig( string name )
+		throws ConfigurationException
+	
+	/**
+	 * Unloads the current configuration if any.
+	 */
+	void unloadConfig()
+	
+	/**
+	 * Tests whether the configuration exists and can be loaded by this user.
+	 * @param name the name of the configuration.
+	 * @return true if the configuration exists and can be loaded by this user.
+	 */
+	boolean canLoad( string name )
+	
+	/**
+	 * Tests whether a configuration has been loaded.
+	 * @return true if a configuration has been loaded.
+	 */
+	boolean isLoaded()
+	
+	/**
+	 * Returns the id of the root node.
+	 * @return the id of the root node.
+	 */
+	object getRoot()
+	
+	/////////////////////
+	// NODE PROPERTIES //
+	/////////////////////
+	
+	/**
+	 * Gets the parent of a node.
+	 * @param id the id of a node.
+	 * @return the id of the parent of the node, or null if it is the root.
+	 */
+	object getParent( object id )
+	
+	/**
+	 * Gets the name of a node which is a child of a map or list.
+	 * @param id the id of a node.
+	 * @return the name of the node. The name is a string if the parent is a
+	 * Map or a List, or "" (the empty string) if the value is the root.
+	 */
+	string getName( object id )
+	
+	/**
+	 * Gets the index of a node which is a child of a list.
+	 * @param id the id of a node.
+	 * @return the index of the node if the parent is a list, or null otherwise.
+	 */
+	int getIndex( object id )
+	
+	/**
+	 * Gets the path of a node.
+	 * @param id the id of a node.
+	 * @return the concatenation of the names of the ancestors of the node
+	 * with "/" between the names.
+	 */
+	string getPath( object id )
+	
+	/**
+	 * Tests whether a node is the root.
+	 * @param id the id of a node.
+	 * @return true if the node is the root.
+	 */
+	boolean isRoot( object id )
+	
+	/**
+	 * Tests whether a node is a List.
+	 * @param id the id of a node.
+	 * @return true if the node is a List.
+	 */
+	boolean isList( object id )
+	
+	/**
+	 * Tests whether a node is a Map.
+	 * @param id the id of a node.
+	 * @return true if the node is a Map.
+	 */
+	boolean isMap( object id )
+	
+	/**
+	 * Gets the number of children of a node which is a List or Map.
+	 * @param id the id of a node.
+	 * @return the number of children.
+	 */
+	int size( object id )
+	
+	//////////////
+	// CHILDREN //
+	//////////////
+	
+	/**
+	 * Lists the ids of the children of a node.
+	 * @param id the id of a node.
+	 * @param offset index into the result set of the first item to return. If
+	 * null, 0 is used.
+	 * @param count count of items to return. If null, all remaining items are
+	 * returned.
+	 * @return array of child ids, or null if the node is a scalar node.
+	 */
+	object[] listConfigIds( object id, int offset, int count )
+	
+	/**
+	 * Lists the ids of the children of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @param offset index into the result set of the first item to return. If
+	 * null, 0 is used.
+	 * @param count count of items to return. If null, all remaining items are
+	 * returned.
+	 * @return array of child ids, or null if the node is a scalar node.
+	 */
+	object[] listConfigPathIds( object id, string path, int offset, int count )
+	
+	/**
+	 * Gets the id of a child of a node by index. The node must be a List.
+	 * @param id the id of a node.
+	 * @param index an index of the child node. Starts at 0.
+	 * @return id of the child.
+	 */
+	object getConfigIndex( object id, int index )
+
+	/**
+	 * Gets the id of a child of a node by path. The nodes along the path must
+	 * all be a List or Map except the last. Whenever a path element is being
+	 * applied to a list node, it must be an integer.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return id of the child.
+	 */
+	object getConfigPath( object id, string path )
+	
+	////////////////////////
+	// NODE / PATH ACCESS //
+	////////////////////////
+	
+	/**
+	 * Tests whether a node has a value.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return true if the node has a value.
+     */
+	boolean hasValuePath( object id, string path )
+	
+	/**
+	 * Gets the value value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return the value of the node, or null if none. Note that the value may
+	 * not be the expected type. That depends upon the underlying
+	 * implementation. If you want the value as a specific type, use
+	 * getTypePath() methods below.
+     */
+	object getValuePath( object id, string path )
+
+	/**
+	 * Gets the boolean value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return the value of the node, or null if none.
+     */
+	boolean getBooleanPath( object id, string path )
+
+	/**
+	 * Gets the integer value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return the value of the node, or null if none.
+     */
+	int getIntegerPath( object id, string path )
+
+	/**
+	 * Gets the double value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return the value of the node, or null if none.
+     */
+	double getDoublePath( object id, string path )
+
+	/**
+	 * Gets the string value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return the value of the node, or null if none.
+     */
+	string getStringPath( object id, string path )
+
+	/**
+	 * Gets the Datetime value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return the value of the node, or null if none.
+     */
+	Datetime getDatePath( object id, string path )
+	
+	/**
+	 * Gets the List value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @param depth if any of the values in the list are themselves maps or
+	 * lists, recursively get those values too up to the specified depth. Depth
+	 * value of 0 means only get the values of the node itself.
+	 * @return the List value of the node.
+	 */
+	List getListPath( object id, string path, int depth )
+	
+	/**
+	 * Gets the Map value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @param depth if any of the values in the map are themselves maps or
+	 * lists, recursively get those values too up to the specified depth. Depth
+	 * value of 0 means only get the values of the node itself.
+	 * @return the Map value of the node.
+	 */
+	Map getMapPath( object id, string path, int depth )
+	
+	/////////////////
+	// NODE ACCESS //
+	/////////////////
+
+	/**
+	 * Tests whether a node has a value.
+	 * @param id the id of a node.
+	 * @return true if the node has a value.
+     */
+	boolean hasValue( object id )
+	
+	/**
+	 * Gets the value value of a node.
+	 * @param id the id of a node.
+	 * @return the value of the node, or null if none. Note that the value may
+	 * not be the expected type. That depends upon the underlying
+	 * implementation. If you want the value as a specific type, use getType()
+	 * methods below.
+     */
+	object getValue( object id )
+
+	/**
+	 * Gets the boolean value of a node.
+	 * @param id the id of a node.
+	 * @return the value of the node, or null if none.
+     */
+	boolean getBoolean( object id )
+
+	/**
+	 * Gets the integer value of a node.
+	 * @param id the id of a node.
+	 * @return the value of the node, or null if none.
+     */
+	int getInteger( object id )
+
+	/**
+	 * Gets the double value of a node.
+	 * @param id the id of a node.
+	 * @return the value of the node, or null if none.
+     */
+	double getDouble( object id )
+
+	/**
+	 * Gets the string value of a node.
+	 * @param id the id of a node.
+	 * @return the value of the node, or null if none.
+     */
+	string getString( object id )
+
+	/**
+	 * Gets the Datetime value of a node.
+	 * @param id the id of a node.
+	 * @return the value of the node, or null if none.
+     */
+	Datetime getDate( object id )
+	
+	/**
+	 * Gets the List value of a node.
+	 * @param id the id of a node.
+	 * @param depth if any of the values in the list are themselves maps or
+	 * lists, recursively get those values too up to the specified depth. Depth
+	 * value of 0 means only get the values of the node itself.
+	 * @return the List value of the node.
+	 */
+	List getList( object id, int depth )
+	
+	/**
+	 * Gets the Map value of a node.
+	 * @param id the id of a node.
+	 * @param depth if any of the values in the map are themselves maps or
+	 * lists, recursively get those values too up to the specified depth. Depth
+	 * value of 0 means only get the values of the node itself.
+	 * @return the Map value of the node.
+	 */
+	Map getMap( object id, int depth )
+	
+	/////////////////////////
+	// CHANGE NOTIFICATION //
+	/////////////////////////
+	
+	/**
+	 * Subscribes to changes at or below a node.
+	 * @param id the id of a node.
+	 */
+	void subscribe( object id )
+	
+	/**
+	 * Subscribes to changes at or below a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 */
+	void subscribePath( object id, string path )
+	
+	/**
+	 * Unsubscribes to changes at or below a node.
+	 * @param id the id of a node.
+	 */
+	void unsubscribe( object id )
+	
+	/**
+	 * Unsubscribes to changes at or below a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 */
+	void unsubscribePath( object id, string path )
+	
+	/**
+	 * Unsubscribes to all changes.
+	 */
+	void unsubscribeAll()
+	
+	/**
+	 * Notifies client of changes to the values of nodes. Added or deleted nodes
+	 * are treated as updates to the parent. Reporting is done on a best effort
+	 * basis. The nodes reported might be an ancestor of the nodes which
+	 * actually changed.
+	 * @param updated the ids of nodes that have been updated.
+	 */
+	@Direction( Client )
+	@AsyncReceiver( Queued )
+	void configValuesChanged( object[] updated )
+}
diff --git a/services/config/src/main/java/org/apache/etch/services/config/ImplConfigurationClient.java b/services/config/src/main/java/org/apache/etch/services/config/ImplConfigurationClient.java
new file mode 100644
index 0000000..4e1259e
--- /dev/null
+++ b/services/config/src/main/java/org/apache/etch/services/config/ImplConfigurationClient.java
@@ -0,0 +1,49 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.services.config;
+
+/**
+ * Your custom implementation of BaseConfigurationClient. Add methods here to provide
+ * implementations of messages from the server.
+ */
+public class ImplConfigurationClient extends BaseConfigurationClient
+{
+	/**
+	 * Constructs the ImplConfigurationClient.
+	 *
+	 * @param server a connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	public ImplConfigurationClient( RemoteConfigurationServer server )
+	{
+		this.server = server;
+	}
+	
+	/**
+	 * A connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	@SuppressWarnings( "unused" )
+	private final RemoteConfigurationServer server;
+
+	// TODO insert methods here to provide implementations of ConfigurationClient
+	// messages from the server.
+}
\ No newline at end of file
diff --git a/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationClient.java b/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationClient.java
new file mode 100644
index 0000000..1b13134
--- /dev/null
+++ b/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationClient.java
@@ -0,0 +1,88 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.services.config;
+
+import org.apache.etch.util.URL;
+
+/**
+ * Main program for ConfigurationClient. This program makes a connection to the
+ * listener created by MainConfigurationListener.
+ */
+public class MainConfigurationClient implements
+	ConfigurationHelper.ConfigurationClientFactory
+{
+	/**
+	 * Main program for ConfigurationClient.
+	 * 
+	 * @param args command line arguments.
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		// get our configUri from a local config file.
+		ConfigurationServer local = new YamlConfig( null, "services/config/local" );
+		String configUri = local.getStringPath( local.getRoot(), "configUri" );
+		System.out.println( "configUri = "+configUri );
+		local.unloadConfig();
+		local = null;
+		
+		RemoteConfigurationServer server = ConfigurationHelper.newServer(
+			configUri, null, new MainConfigurationClient() );
+
+		// Connect to the service.
+		server._startAndWaitUp( 4000 );
+		System.out.println( "connected to config service" );
+		
+		String name = new URL( configUri ).getUri();
+		Object root = server.loadConfig( name );
+		System.out.println( "loaded configuration named '"+name+"'" );
+		
+		// Load a config and play with it.
+		System.out.println( "bool = "+server.getBooleanPath( root, "bool" ) );
+		System.out.println( "int = "+server.getIntegerPath( root, "int" ) );
+		System.out.println( "dbl = "+server.getDoublePath( root, "dbl" ) );
+		System.out.println( "str = "+server.getStringPath( root, "str" ) );
+		System.out.println( "date = "+server.getDatePath( root, "date" ) );
+		
+		System.out.println( "users/mary = "+server.getStringPath( root, "users/mary" ) );
+		
+		Object users = server.getConfigPath( root, "users" );
+		System.out.println( "users/mary = "+server.getStringPath( users, "mary" ) );
+		System.out.println( "users/alice = "+server.getStringPath( users, "alice" ) );
+
+		System.out.println( "primes/4 = "+server.getIntegerPath( root, "primes/4" ) );
+		System.out.println( "primes/5 = "+server.getIntegerPath( root, "primes/5" ) );
+		
+		System.out.println( "paths:" );
+		for (Object o: server.listConfigIds( root, null, null ))
+			System.out.println( server.getPath( o ) );
+		System.out.println( "done." );
+		
+		// Disconnect from the service.
+		server._stopAndWaitDown( 4000 );
+	}
+
+	public ConfigurationClient newConfigurationClient(
+		RemoteConfigurationServer server ) throws Exception
+	{
+		return new ImplConfigurationClient( server );
+	}
+}
diff --git a/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationListener.java b/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationListener.java
new file mode 100644
index 0000000..80bdeda
--- /dev/null
+++ b/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationListener.java
@@ -0,0 +1,94 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.services.config;
+
+import org.apache.etch.bindings.java.support.ObjSession;
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.services.config.Configuration.ConfigurationException;
+import org.apache.etch.util.core.io.Session;
+import org.apache.etch.util.core.io.Transport;
+
+
+
+/**
+ * Main program for ConfigurationServer. This program makes a listener to accept
+ * connections from MainConfigurationClient.
+ */
+public class MainConfigurationListener implements ConfigurationHelper.ConfigurationServerFactory
+{
+	/**
+	 * Main program for ConfigurationServer.
+	 * 
+	 * @param args command line arguments.
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		// TODO Change to correct URI
+		String uri = "tcp://0.0.0.0:4001";
+		
+		ServerFactory listener = ConfigurationHelper.newListener( uri, null,
+			new MainConfigurationListener() );
+
+		// Start the Listener
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+	}
+
+	public ConfigurationServer newConfigurationServer(
+		RemoteConfigurationClient client ) throws ConfigurationException
+	{
+		return new MyYamlConfig( client );
+	}
+	
+	/**
+	 * Wrapper around YamlConfig which watches for {@link Session#DOWN} and
+	 * unloads the config (thus canceling all subscriptions).
+	 */
+	public static class MyYamlConfig extends YamlConfig implements ObjSession
+	{
+		/**
+		 * Constructs MyYamlConfig.
+		 * @param client
+		 * @throws ConfigurationException
+		 */
+		public MyYamlConfig( ConfigurationClient client ) throws ConfigurationException
+		{
+			super( client );
+		}
+
+		public Object _sessionQuery( Object query ) throws Exception
+		{
+			throw new UnsupportedOperationException( "unknown query "+query );
+		}
+		
+		public void _sessionControl( Object control, Object value )
+			throws Exception
+		{
+			throw new UnsupportedOperationException( "unknown control "+control );
+		}
+
+		public void _sessionNotify( Object event ) throws Exception
+		{
+			if (event == Session.DOWN)
+				unloadConfig();
+		}
+	}
+}
diff --git a/services/config/src/main/java/org/apache/etch/services/config/YamlConfig.java b/services/config/src/main/java/org/apache/etch/services/config/YamlConfig.java
new file mode 100644
index 0000000..4b43553
--- /dev/null
+++ b/services/config/src/main/java/org/apache/etch/services/config/YamlConfig.java
@@ -0,0 +1,1395 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.services.config;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.apache.etch.util.AlarmListener;
+import org.apache.etch.util.AlarmManager;
+import org.apache.etch.util.Assertion;
+import org.apache.etch.util.IdGenerator;
+import org.apache.etch.util.Todo;
+import org.apache.etch.util.TodoManager;
+import org.ho.yaml.Yaml;
+import org.ho.yaml.exception.YamlException;
+
+
+/** Local Yaml implementation of ConfigurationServer */
+public class YamlConfig implements ConfigurationServer
+{
+	/**
+	 * Constructs an empty YamlConfigurationServer.
+	 * @param client 
+	 * @throws ConfigurationException 
+	 */
+	public YamlConfig( ConfigurationClient client )
+		throws ConfigurationException
+	{
+		this( client, null );
+	}
+	
+	/**
+	 * Constructs a YamlConfigurationServer, then loads the config.
+	 * @param client 
+	 * @param name
+	 * @throws ConfigurationException
+	 */
+	public YamlConfig( ConfigurationClient client, String name )
+		throws ConfigurationException
+	{
+		this.client = client;
+		if (name == null)
+			return;
+		loadConfig( name );
+	}
+	
+	private final ConfigurationClient client;
+
+	////////////////////
+	// PUBLIC METHODS //
+	////////////////////
+
+	public Object loadConfig( String name )
+		throws ConfigurationException
+	{
+		unloadConfig();
+		
+		File f = mkfile( name );
+		
+		for (int i = 0; i < 4; i++)
+		{
+			long t0 = f.lastModified();
+			Object o = loadConfig0( f );
+			long t1 = f.lastModified();
+			
+			if (t1 == t0)
+			{
+				configs = importConfigs( o );
+				file = f;
+				lastModified = t0;
+				subs = Collections.synchronizedSet( new HashSet<Integer>() );
+				return getRoot();
+			}
+			
+			try
+			{
+				Thread.sleep( 1000 );
+			}
+			catch ( InterruptedException e )
+			{
+				break;
+			}
+		}
+		
+		throw new ConfigurationException( "config is changing: "+name );
+	}
+
+	public void unloadConfig()
+	{
+		unsubscribeAll();
+		file = null;
+		lastModified = null;
+		configs = null;
+		subs = null;
+	}
+
+	public Boolean canLoad( String name )
+	{
+		try
+		{
+			mkfile( name );
+			return true;
+		}
+		catch ( ConfigurationException e )
+		{
+			return false;
+		}
+	}
+
+	public Boolean isLoaded()
+	{
+		return configs != null;
+	}
+
+	public Object getRoot()
+	{
+		if (!isLoaded())
+			throw new IllegalStateException( "no config loaded" );
+		
+		if (configs.size() == 0)
+			throw new IllegalStateException( "config is empty" );
+		
+		return toId( 0 );
+	}
+	
+	/////////////////////
+	// NODE PROPERTIES //
+	/////////////////////
+
+	public Object getParent( Object id )
+	{
+		return toId( getConf( id ).parent );
+	}
+
+	public String getName( Object id )
+	{
+		return getConf( id ).name();
+	}
+
+	public Integer getIndex( Object id )
+	{
+		return getConf( id ).index();
+	}
+
+	public String getPath( Object id )
+	{
+		return getConf( id ).getPath();
+	}
+
+	public Boolean isRoot( Object id )
+	{
+		return getConf( id ).isRoot();
+	}
+
+	public Boolean isList( Object id )
+	{
+		return getConf( id ).isList();
+	}
+
+	public Boolean isMap( Object id )
+	{
+		return getConf( id ).isMap();
+	}
+	
+	public Integer size( Object id )
+	{
+		return getConf( id ).size();
+	}
+	
+	//////////////
+	// CHILDREN //
+	//////////////
+
+	public Object[] listConfigIds( Object id, Integer offset, Integer count )
+	{
+		Conf c = getConf( id );
+		
+		if (c.isList())
+			return toIdArray( c.list(), offset, count );
+		
+		if (c.isMap())
+			return toIdArray( c.map().values(), offset, count );
+		
+		throw new NoSuchElementException( "value is not a List or a Map" );
+	}
+	
+	public Object[] listConfigPathIds( Object id, String path, Integer offset,
+		Integer count )
+	{
+		return listConfigIds( getConfigPath( id, path ), offset, count );
+	}
+
+	public Object getConfigIndex( Object id, Integer index )
+	{
+		if (index == null)
+			throw new IllegalArgumentException( "index == null" );
+		
+		Conf c = getConf( id );
+		
+		if (c.isList())
+		{
+			List<Integer> list = c.list();
+			
+			if (index < 0 || index >= list.size())
+				throw new IllegalArgumentException(
+					"index < 0 || index >= list.size()" );
+			
+			return toId( c.list().get( index ) );
+		}
+		
+		throw new IllegalArgumentException( "value is not a List" );
+	}
+
+	public Object getConfigPath( Object id, String path )
+	{
+		checkPath( path );
+		// path is not null.
+		
+		// id == null: path must be absolute.
+		// id != null: path may be relative or absolute.
+		
+		if (id == null)
+		{
+			if (!isAbsolute( path ))
+				throw new IllegalArgumentException(
+					"path must be absolute when id == null" );
+			
+			id = getRoot();
+			path = abs2rel( path );
+		}
+		else
+		{
+			if (isAbsolute( path ))
+			{
+				id = getRoot();
+				path = abs2rel( path );
+			}
+			else
+			{
+				getConf( id );
+			}
+		}
+		
+		// id is not null
+		
+		Integer iid = fromId( id );
+		
+		// if we have a simple path just let getConfig0 handle it
+		
+		if (path.indexOf( '/' ) < 0)
+			return toId( getConfigName( iid, path ) );
+		
+		// complex path
+		
+		StringTokenizer st = new StringTokenizer( path, "/" );
+		while (iid != null && st.hasMoreTokens())
+			iid = getConfigName( iid, st.nextToken() );
+		
+		return toId( iid );
+	}
+
+	////////////////////////
+	// NODE / PATH ACCESS //
+	////////////////////////
+
+	public Boolean hasValuePath( Object id, String path )
+	{
+		return hasValue( getConfigPath( id, path ) );
+	}
+
+	public Object getValuePath( Object id, String path )
+	{
+		return getValue( getConfigPath( id, path ) );
+	}
+
+	public Boolean getBooleanPath( Object id, String path )
+	{
+		return getBoolean( getConfigPath( id, path ) );
+	}
+
+	public Integer getIntegerPath( Object id, String path )
+	{
+		return getInteger( getConfigPath( id, path ) );
+	}
+
+	public Double getDoublePath( Object id, String path )
+	{
+		return getDouble( getConfigPath( id, path ) );
+	}
+
+	public String getStringPath( Object id, String path )
+	{
+		return getString( getConfigPath( id, path ) );
+	}
+
+	public Date getDatePath( Object id, String path )
+	{
+		return getDate( getConfigPath( id, path ) );
+	}
+
+	public List<?> getListPath( Object id, String path, Integer depth )
+	{
+		return getList( getConfigPath( id, path ), depth );
+	}
+
+	public Map<?, ?> getMapPath( Object id, String path, Integer depth )
+	{
+		return getMap( getConfigPath( id, path ), depth );
+	}
+	
+	/////////////////
+	// NODE VALUES //
+	/////////////////
+
+	public Boolean hasValue( Object id )
+	{
+		if (id == null)
+			return false;
+		return getConf( id ).hasValue();
+	}
+
+	public Object getValue( Object id )
+	{
+		if (id == null)
+			return null;
+		return getConf( id ).getValue();
+	}
+
+	public Boolean getBoolean( Object id )
+	{
+		if (id == null)
+			return null;
+		return getConf( id ).getBoolean();
+	}
+
+	public Integer getInteger( Object id )
+	{
+		if (id == null)
+			return null;
+		return getConf( id ).getInteger();
+	}
+
+	public Double getDouble( Object id )
+	{
+		if (id == null)
+			return null;
+		return getConf( id ).getDouble();
+	}
+
+	public String getString( Object id )
+	{
+		if (id == null)
+			return null;
+		return getConf( id ).getString();
+	}
+
+	public Date getDate( Object id )
+	{
+		if (id == null)
+			return null;
+		return getConf( id ).getDate();
+	}
+
+	public List<?> getList( Object id, Integer depth )
+	{
+		if (id == null)
+			return null;
+		return getConf( id ).getList( depth );
+	}
+
+	public Map<?, ?> getMap( Object id, Integer depth )
+	{
+		if (id == null)
+			return null;
+		return getConf( id ).getMap( depth );
+	}
+	
+	/////////////////////////
+	// CHANGE NOTIFICATION //
+	/////////////////////////
+
+	public void subscribe( Object id )
+	{
+		if (id == null)
+			return;
+		
+		int iid = fromId( id );
+		getConf0( iid );
+		
+		synchronized (subs)
+		{
+			if (subs.isEmpty())
+				AlarmManager.staticAdd( LISTENER, null, INTERVAL );
+			
+			subs.add( iid );
+		}
+		
+		fireConfigValuesChanged( new Object[] { id } );
+	}
+	
+	private void fireConfigValuesChanged( final Object[] updated )
+	{
+		TodoManager.addTodo( new Todo()
+		{
+
+			public void doit( TodoManager mgr ) throws Exception
+			{
+				client.configValuesChanged( updated );
+			}
+
+			public void exception( TodoManager mgr, Exception e )
+			{
+				e.printStackTrace();
+			}
+		} );
+	}
+	
+	public void subscribePath( Object id, String path )
+	{
+		subscribe( getConfigPath( id, path ) );
+	}
+
+	public void unsubscribe( Object id )
+	{
+		if (id == null)
+			return;
+		
+		int iid = fromId( id );
+		getConf0( iid );
+		
+		synchronized (subs)
+		{
+			if (!subs.remove( iid ))
+				return;
+			
+			if (subs.isEmpty())
+				AlarmManager.staticRemove( LISTENER );
+		}
+	}
+
+	public void unsubscribePath( Object id, String path )
+	{
+		unsubscribe( getConfigPath( id, path ) );
+	}
+	
+	public void unsubscribeAll()
+	{
+		if (subs == null)
+			return;
+		
+		AlarmManager.staticRemove( LISTENER );
+		
+		synchronized (subs)
+		{
+			for (Integer iid: subs)
+				getConf0( iid );
+			subs.clear();
+		}
+	}
+
+	/////////////
+	// PRIVATE //
+	/////////////
+	
+	///CLOVER:OFF
+	
+	/**
+	 * Dumps the config space.
+	 */
+	public void dump()
+	{
+		for (Map.Entry<Integer, Conf> me: configs.entrySet())
+			System.out.printf( "%d: %s\n", me.getKey(), me.getValue() );
+		System.out.println( "done" );
+	}
+	
+	///CLOVER:ON
+	
+	private static final int ID_RADIX = Character.MAX_RADIX;
+	
+	private String abs2rel( String path )
+	{
+		Assertion.check( isAbsolute( path ), "path is absolute" );
+		return path.substring( 1 );
+	}
+
+	private static boolean isAbsolute( String path )
+	{
+		checkPath( path );
+		return path.startsWith( "/" );
+	}
+	
+	private static void checkPath( String path )
+	{
+		if (path == null)
+			throw new IllegalArgumentException( "path == null" );
+	}
+
+	private Object toId( Integer iid )
+	{
+		if (iid == null)
+			return null;
+		return "#"+Integer.toString( iid, ID_RADIX )+"#";
+	}
+
+	private int fromId( Object id )
+	{
+		if (id == null)
+			throw new IllegalArgumentException( "id == null" );
+		
+		if (!(id instanceof String))
+			throw new IllegalArgumentException( "id is not valid: "+id );
+		
+		String s = (String) id;
+		
+		if (!s.startsWith( "#" ))
+			throw new IllegalArgumentException( "id is not valid: "+id );
+		
+		if (!s.endsWith( "#" ))
+			throw new IllegalArgumentException( "id is not valid: "+id );
+		
+		try
+		{
+			return Integer.parseInt( s.substring( 1 )
+				.substring( 0, s.length()-2 ), ID_RADIX );
+		}
+		catch ( StringIndexOutOfBoundsException e )
+		{
+			throw new IllegalArgumentException( "id is not valid: "+id );
+		}
+		catch ( NumberFormatException e )
+		{
+			throw new IllegalArgumentException( "id is not valid: "+id );
+		}
+	}
+	
+	private int INTERVAL = 5*1000;
+	
+	private final static int FAIL_INTERVAL = 60*1000;
+
+	private static final String configDir = ".";
+	
+	private final AlarmListener LISTENER = new AlarmListener()
+	{
+		public int wakeup( AlarmManager manager, Object state, long due )
+		{
+			try
+			{
+				updateConfig();
+				return INTERVAL;
+			}
+			catch ( Exception e )
+			{
+				e.printStackTrace();
+				return FAIL_INTERVAL;
+			}
+		}
+	};
+	
+	private File mkfile( String name ) throws ConfigurationException
+	{
+		if (name == null || name.length() == 0)
+			throw new ConfigurationException( "name is null or blank" );
+		
+		// filter out references to non-existent configs.
+		
+		File f = new File( name+".yml" );
+		if (!f.isFile() || !f.canRead())
+			throw new ConfigurationException( "could not verify name: "+name );
+		
+		// make sure the config is in the config directory.
+		
+		try
+		{
+			String fcp = f.getCanonicalPath();
+//			System.out.println( "fcp = "+fcp );
+			
+			String cd = new File( configDir ).getCanonicalPath() + File.separatorChar;
+//			System.out.println( "cd = "+cd );
+			
+			if (!fcp.startsWith( cd ))
+				throw new ConfigurationException( "could not verify name: "+name );
+		}
+		catch ( IOException e )
+		{
+			throw new ConfigurationException( "could not verify name: "+name );
+		}
+		
+		return f;
+	}
+
+	private File file;
+	
+	private Long lastModified;
+
+	private Map<Integer, Conf> configs;
+	
+	private IdGenerator idgen = new IdGenerator( 0 );
+	
+	private Set<Integer> subs;
+	
+	private static Object loadConfig0( File file ) throws ConfigurationException
+	{
+		try
+		{
+			Object o = Yaml.load( file );
+			return o;
+		}
+		catch ( FileNotFoundException e )
+		{
+			throw new ConfigurationException( "file not found: " + file );
+		}
+		catch ( YamlException e )
+		{
+			throw new ConfigurationException( "file not loaded: " + file + "; "+e );
+		}
+	}
+
+	private Map<Integer, Conf> importConfigs( Object root )
+	{
+		Map<Integer, Conf> newConfigs = new HashMap<Integer, Conf>();
+		importObject( newConfigs, null, null, root );
+		return newConfigs;
+	}
+	
+	/**
+	 * This is purely for testing.
+	 */
+	void setConfig( String name ) throws Exception
+	{
+		file = mkfile( name );
+		lastModified = Long.MIN_VALUE;
+	}
+	
+	private void updateConfig() throws ConfigurationException
+	{
+		if (file.lastModified() == lastModified)
+			return;
+		
+		long t0 = file.lastModified();
+		Object o = loadConfig0( file );
+		long t1 = file.lastModified();
+		
+		if (t1 != t0)
+			return;
+		
+		Set<Object> changeIds = new HashSet<Object>();
+		
+		synchronized (subs)
+		{
+			Map<Integer, Conf> newConfigs = new HashMap<Integer, Conf>( configs );
+			Set<Integer> newSubs = Collections.synchronizedSet(
+				new HashSet<Integer>( subs ) );
+			Set<Integer> changeSet = new HashSet<Integer>();
+			
+			updateObject( newConfigs, newSubs, changeSet, 0,
+				null, null, o );
+			
+			// compute those ids in changeSet or their ancestors that
+			// are subscribed to.
+			computeChangeIds( changeIds, newConfigs, newSubs, changeSet );
+
+			lastModified = t0;
+			configs = newConfigs;
+			subs = newSubs;
+		}
+		
+		fireConfigValuesChanged( changeIds.toArray() );
+	}
+
+	private void computeChangeIds( Set<Object> changeIds,
+		Map<Integer, Conf> newConfigs, Set<Integer> newSubs, Set<Integer> changeSet )
+	{
+		for (int iid: changeSet)
+			computeChangeIds( changeIds, newConfigs, newSubs, iid );
+	}
+
+	private void computeChangeIds( Set<Object> changeIds,
+		Map<Integer, Conf> newConfigs, Set<Integer> newSubs, int iid )
+	{
+		if (newSubs.contains( iid ))
+		{
+			changeIds.add( toId( iid ) );
+		}
+		else
+		{
+			Conf c = newConfigs.get( iid );
+			if (c.parent != null)
+				computeChangeIds( changeIds, newConfigs, newSubs, c.parent );
+		}
+	}
+
+	private int importObject( Map<Integer, Conf> newConfigs, Integer parent, Object nameOrIndex,
+		Object value )
+	{
+		if (valueIsList( value ))
+			return importList( newConfigs, parent, nameOrIndex, (List<?>) value );
+		
+		if (valueIsMap( value ))
+			return importMap( newConfigs, parent, nameOrIndex, (Map<?, ?>) value );
+		
+		if (valueIsScalar( value ))
+		{
+			int k = (int) idgen.next();
+			newConfigs.put( k, new Conf( k, parent, nameOrIndex, value ) );
+			return k;
+		}
+		
+		throw new IllegalArgumentException(
+			"don't know how to import type "+value.getClass() );
+	}
+	
+	private static boolean valueIsScalar( Object value )
+	{
+		return value instanceof Boolean || value instanceof Number ||
+			value instanceof String || value instanceof Date;
+	}
+
+	private boolean valueIsList( Object value )
+	{
+		return value instanceof List;
+	}
+
+	private boolean valueIsMap( Object value )
+	{
+		return value instanceof Map;
+	}
+
+	private void updateObject( Map<Integer, Conf> newConfigs, Set<Integer> newSubs,
+		Set<Integer> changeSet, int iid, Integer parent, Object nameOrIndex,
+		Object value )
+	{
+		Conf c = newConfigs.get( iid );
+		
+		Assertion.check( (parent == null && c.parent == null) ||
+			(parent != null && c.parent != null && parent.equals( c.parent )),
+				"parents match" );
+		
+		Assertion.check( (nameOrIndex == null && c.nameOrIndex == null) ||
+			(nameOrIndex != null && c.nameOrIndex != null && nameOrIndex.equals( c.nameOrIndex )),
+			"nameOrIndex match" );
+		
+		if (valueIsList( value ))
+		{
+			if (c.isList())
+			{
+				updateList( newConfigs, newSubs, changeSet, iid, parent, nameOrIndex, (List<?>) value, c );
+				return;
+			}
+			if (c.isMap())
+			{
+				destroyMap( newConfigs, newSubs, iid, c );
+				importList( newConfigs, newSubs, changeSet, iid, parent, nameOrIndex, (List<?>) value );
+				return;
+			}
+			if (c.isScalar())
+			{
+				importList( newConfigs, newSubs, changeSet, iid, parent, nameOrIndex, (List<?>) value );
+				return;
+			}
+			throw new IllegalArgumentException(
+				"don't know how to update to list from type " + c.value.getClass() );
+		}
+		
+		if (valueIsMap( value ))
+		{
+			if (c.isMap())
+			{
+				updateMap( newConfigs, newSubs, changeSet, iid, parent, nameOrIndex, (Map<?, ?>) value, c );
+				return;
+			}
+			if (c.isList())
+			{
+				destroyList( newConfigs, newSubs, iid, c );
+				importMap( newConfigs, newSubs, changeSet, iid, parent, nameOrIndex, (Map<?, ?>) value );
+				return;
+			}
+			if (c.isScalar())
+			{
+				importMap( newConfigs, newSubs, changeSet, iid, parent, nameOrIndex, (Map<?, ?>) value );
+				return;
+			}
+			throw new IllegalArgumentException(
+				"don't know how to update to map from type " + c.value.getClass() );
+		}
+		
+		if (valueIsScalar( value ))
+		{
+			if (c.isMap())
+			{
+				destroyMap( newConfigs, newSubs, iid, c );
+				newConfigs.put( iid, new Conf( iid, parent, nameOrIndex, value ) );
+				add( newConfigs, changeSet, iid );
+				return;
+			}
+			
+			if (c.isList())
+			{
+				destroyList( newConfigs, newSubs, iid, c );
+				newConfigs.put( iid, new Conf( iid, parent, nameOrIndex, value ) );
+				add( newConfigs, changeSet, iid );
+				return;
+			}
+			
+			if (c.isScalar())
+			{
+				if (value.equals( c.value ))
+					return;
+				
+				newConfigs.put( iid, new Conf( iid, parent, nameOrIndex, value ) );
+				add( newConfigs, changeSet, iid );
+				return;
+			}
+		}
+		
+		throw new IllegalArgumentException( "don't know how to update to " +
+			value.getClass() + " from " + c.value.getClass() );
+	}
+
+	private void add( Map<Integer, Conf> newConfigs, Set<Integer> changeSet, int iid )
+	{
+		System.out.println( "changeSet.add( "+iid+" )" );
+		System.out.println( "  conf: "+newConfigs.get( iid ) );
+//		new Throwable().printStackTrace( System.out );
+		
+		changeSet.add( iid );
+	}
+
+	private int importList( Map<Integer, Conf> newConfigs, Integer parent, Object nameOrIndex, List<?> value )
+	{
+		List<Integer> v = new ArrayList<Integer>( value.size() );
+		int k = (int) idgen.next();
+		newConfigs.put( k, new Conf( k, parent, nameOrIndex, Collections.unmodifiableList( v ) ) );
+		
+		int i = 0;
+		for (Object o: value )
+			v.add( importObject( newConfigs, k, i++, o ) );
+		
+		return k;
+	}
+
+	private void importList( Map<Integer, Conf> newConfigs, Set<Integer> newSubs,
+		Set<Integer> changeSet, int iid, Integer parent, Object nameOrIndex,
+		List<?> value )
+	{
+		List<Integer> v = new ArrayList<Integer>( value.size() );
+		newConfigs.put( iid, new Conf( iid, parent, nameOrIndex, Collections.unmodifiableList( v ) ) );
+		add( newConfigs, changeSet, iid );
+		
+		int i = 0;
+		for (Object o: value )
+			v.add( importObject( newConfigs, iid, i++, o ) );
+	}
+
+	private void updateList( Map<Integer, Conf> newConfigs, Set<Integer> newSubs,
+		Set<Integer> changeSet, int iid, Integer parent, Object nameOrIndex,
+		List<?> value, Conf c )
+	{
+		List<Integer> newList = new ArrayList<Integer>( c.list() );
+		boolean changed = false;
+		
+		int n = Math.max( value.size(), newList.size() );
+		for (int i = 0; i < n; i++)
+		{
+			if (i < value.size() && i < newList.size())
+			{
+				updateObject( newConfigs, newSubs, changeSet, newList.get( i ), iid, i, value.get( i ) );
+			}
+			else if (i < newList.size()) // ran out of new values (newList too long)
+			{
+				destroy( newConfigs, newSubs, newList.get( i ) );
+				newList.set( i, null );
+				changed = true;
+				// this entry will eventually be removed...
+			}
+			else // i < value.size() // extending newList
+			{
+				newList.add( importObject( newConfigs, iid, i, value.get( i ) ) );
+				changed = true;
+			}
+		}
+		
+		// trim newList if it is too long.
+		
+		while (newList.size() > value.size())
+			newList.remove( newList.size() - 1 );
+		
+		newConfigs.put( iid, new Conf( iid, parent, nameOrIndex, Collections.unmodifiableList( newList ) ) );
+		
+		if (changed)
+			add( newConfigs, changeSet, iid );
+	}
+
+	private void destroyList( Map<Integer, Conf> newConfigs, Set<Integer> newSubs, int iid, Conf c )
+	{
+		newConfigs.remove( iid );
+		newSubs.remove( iid );
+		for (int i: c.list())
+			destroy( newConfigs, newSubs, i );
+	}
+	
+	private int importMap( Map<Integer, Conf> newConfigs, Integer parent, Object nameOrIndex, Map<?, ?> value )
+	{
+		Map<String, Integer> v = new HashMap<String, Integer>( value.size() * 4 / 3 + 1 );
+		int k = (int) idgen.next();
+		newConfigs.put( k, new Conf( k, parent, nameOrIndex, Collections.unmodifiableMap( v ) ) );
+		
+		for (Map.Entry<?, ?> me: value.entrySet() )
+		{
+			String n = (String) me.getKey();
+			v.put( n, importObject( newConfigs, k, n, me.getValue() ) );
+		}
+		
+		return k;
+	}
+
+	private void importMap( Map<Integer, Conf> newConfigs, Set<Integer> newSubs,
+		Set<Integer> changeSet, int iid, Integer parent, Object nameOrIndex,
+		Map<?, ?> value )
+	{
+		Map<String, Integer> v = new HashMap<String, Integer>( value.size() * 4 / 3 + 1 );
+		newConfigs.put( iid, new Conf( iid, parent, nameOrIndex, Collections.unmodifiableMap( v ) ) );
+		add( newConfigs, changeSet, iid );
+		
+		for (Map.Entry<?, ?> me: value.entrySet() )
+		{
+			String n = (String) me.getKey();
+			v.put( n, importObject( newConfigs, iid, n, me.getValue() ) );
+		}
+	}
+
+	private void updateMap( Map<Integer, Conf> newConfigs, Set<Integer> newSubs,
+		Set<Integer> changeSet, int iid, Integer parent, Object nameOrIndex,
+		Map<?, ?> value, Conf c )
+	{
+		Map<String, Integer> newMap = new HashMap<String, Integer>( c.map() );
+		boolean changed = false;
+		
+		// Look for names in the current map which are not in the new.
+		
+		for (Map.Entry<String, Integer> me: c.map().entrySet())
+		{
+			String name = me.getKey();
+			Integer siid = me.getValue();
+			if (!value.containsKey( name ))
+			{
+				// this name will have to be deleted.
+				newMap.remove( name );
+				destroy( newConfigs, newSubs, siid );
+				changed = true;
+			}
+		}
+		
+		// Look for names in the new map which are not in the current.
+		
+		for (Map.Entry<?, ?> me: value.entrySet())
+		{
+			String name = (String) me.getKey();
+			Object v = me.getValue();
+			if (!newMap.containsKey( name ))
+			{
+				// import the object
+				int k = importObject( newConfigs, iid, name, v );
+				newMap.put( name, k );
+				changed = true;
+			}
+			else
+			{
+				// update the object
+				Integer siid = newMap.get( name );
+				updateObject( newConfigs, newSubs, changeSet, siid, iid, name, v );
+			}
+		}
+		
+		newConfigs.put( iid, new Conf( iid, parent, nameOrIndex, Collections.unmodifiableMap( newMap ) ) );
+		
+		if (changed)
+			add( newConfigs, changeSet, iid );
+	}
+
+	private void destroy( Map<Integer, Conf> newConfigs, Set<Integer> newSubs, int iid )
+	{
+		Conf c = newConfigs.get( iid );
+		if (c.isMap())
+			destroyMap( newConfigs, newSubs, iid, c );
+		else if (c.isList())
+			destroyList( newConfigs, newSubs, iid, c );
+		else if (c.isScalar())
+		{
+			newConfigs.remove( iid );
+			newSubs.remove( iid );
+		}
+		else
+			throw new UnsupportedOperationException(
+				"don't know how to destroy "+c.value.getClass() );
+	}
+
+	private void destroyMap( Map<Integer, Conf> newConfigs, Set<Integer> newSubs, int iid, Conf c )
+	{
+		newConfigs.remove( iid );
+		newSubs.remove( iid );
+		for (int i: c.map().values())
+			destroy( newConfigs, newSubs, i );
+	}
+	
+	private Conf getConf0( int iid )
+	{
+		if (!isLoaded())
+			throw new IllegalStateException( "no config loaded" );
+		
+		Conf c = configs.get( iid );
+		if (c == null)
+			throw new IllegalArgumentException( "no such conf" );
+		return c;
+	}
+	
+	private Conf getConf( Object id )
+	{
+		return getConf0( fromId( id ) );
+	}
+
+	private Object[] toIdArray( Collection<Integer> value, Integer offset,
+		Integer count )
+	{
+		int size = value.size();
+		
+		if (offset == null)
+			offset = 0;
+		else if (offset < 0 || offset > size)
+			throw new IllegalArgumentException(
+				"offset < 0 || offset > size" );
+		
+		if (count == null)
+			count = Integer.MAX_VALUE;
+		else if (count < 0)
+			throw new IllegalArgumentException(
+				"count < 0" );
+		
+		int remaining = size - offset;
+		if (count > remaining)
+			count = remaining;
+		
+		Object[] a = new Object[count];
+		
+		int i = 0;
+		for (int v: value)
+		{
+			if (offset > 0)
+			{
+				offset--;
+				continue;
+			}
+			
+			if (i >= a.length)
+				break;
+			
+			a[i++] = toId( v );
+		}
+		
+		return a;
+	}
+	
+	private Integer getConfigName( int iid, String name )
+	{
+		if (name.length() == 0)
+			return iid;
+		
+		if (name.equals( "." ))
+			return iid;
+		
+		Conf c = getConf0( iid );
+		
+		if (name.equals( ".." ))
+			return c.parent;
+		
+		if (c.isList())
+		{
+			int i = Integer.valueOf( name );
+			// i might be out of range.
+			List<Integer> list = c.list();
+			if (i < 0 || i >= list.size())
+				throw new IllegalArgumentException( "i < 0 || i >= list.size()" );
+			return list.get( i );
+		}
+		
+		if (c.isMap())
+		{
+			Integer i = c.map().get( name );
+			// i might be null.
+			return i;
+		}
+		
+		throw new NoSuchElementException( name );
+	}
+	
+	private class Conf
+	{
+		public Conf( int id, Integer parent, Object nameOrIndex, Object value )
+		{
+			if (parent == null && nameOrIndex != null)
+				throw new IllegalArgumentException(
+					"parent == null && nameOrIndex != null" );
+			
+			if (parent != null && nameOrIndex == null)
+				throw new IllegalArgumentException(
+					"parent != null && nameOrIndex == null" );
+			
+			if (value == null)
+				throw new IllegalArgumentException( "value == null" );
+			
+			this.id = id;
+			this.parent = parent;
+			this.nameOrIndex = nameOrIndex;
+			this.value = value;
+		}
+		
+		private final int id;
+
+		public boolean isScalar()
+		{
+			return valueIsScalar( value );
+		}
+
+		public String getPath()
+		{
+			if (isRoot())
+				return "/";
+			
+			String s = getConf0( parent ).getPath();
+			
+			if (s.equals( "/" ))
+				return s + nameOrIndex;
+			
+			return s + '/' + nameOrIndex;
+		}
+
+		public Integer size()
+		{
+			if (isList())
+				return list().size();
+			
+			if (isMap())
+				return map().size();
+			
+			throw new NoSuchElementException( "value is not a List or a Map" );
+		}
+
+		public Integer index()
+		{
+			if (nameOrIndex == null)
+				return null;
+			
+			if (nameOrIndex instanceof Integer)
+				return (Integer) nameOrIndex;
+			
+			return null;
+		}
+
+		public String name()
+		{
+			if (nameOrIndex == null)
+				return "";
+			
+			if (nameOrIndex instanceof String)
+				return (String) nameOrIndex;
+			
+			return nameOrIndex.toString();
+		}
+
+		public final Integer parent;
+		
+		public final Object nameOrIndex;
+		
+		public final Object value;
+		
+		///CLOVER:OFF
+		
+		@Override
+		public String toString()
+		{
+			return String.format( "Conf %d parent %s nameOrIndex %s, value %s", id, parent, nameOrIndex, value );
+		}
+		
+		///CLOVER:ON
+
+		public boolean isRoot()
+		{
+			return nameOrIndex == null;
+		}
+		
+		public boolean isList()
+		{
+			return valueIsList( value );
+		}
+
+		public boolean isMap()
+		{
+			return valueIsMap( value );
+		}
+		
+		@SuppressWarnings("unchecked")
+		public List<Integer> list()
+		{
+			return (List<Integer>) value;
+		}
+		
+		@SuppressWarnings("unchecked")
+		public Map<String, Integer> map()
+		{
+			return (Map<String, Integer>) value;
+		}
+		
+		public boolean hasValue()
+		{
+			return value != null;
+		}
+		
+		public Object getValue()
+		{
+			return value;
+		}
+		
+		public Boolean getBoolean()
+		{
+			if (value instanceof Boolean)
+				return (Boolean) value;
+			
+			if (value instanceof String)
+				return Boolean.valueOf( (String) value );
+			
+			throw new IllegalArgumentException( "cannot convert value to Boolean" );
+		}
+		
+		public Integer getInteger()
+		{
+			if (value instanceof Integer)
+				return (Integer) value;
+			
+			if (value instanceof String)
+			{
+				try
+				{
+					return Integer.valueOf( (String) value );
+				}
+				catch ( NumberFormatException e )
+				{
+					throw new IllegalArgumentException( "cannot convert value to Integer: "+value );
+				}
+			}
+			
+			throw new IllegalArgumentException( "cannot convert value to Integer" );
+		}
+		
+		public Double getDouble()
+		{
+			if (value instanceof Double)
+				return (Double) value;
+			
+			if (value instanceof Number)
+				return ((Number) value).doubleValue();
+			
+			if (value instanceof String)
+			{
+				try
+				{
+					return Double.valueOf( (String) value );
+				}
+				catch ( NumberFormatException e )
+				{
+					throw new IllegalArgumentException( "cannot convert value to Double: "+value );
+				}
+			}
+			
+			throw new IllegalArgumentException( "cannot convert value to Double" );
+		}
+		
+		public String getString()
+		{
+			if (value instanceof Boolean)
+				return value.toString();
+			if (value instanceof Number)
+				return value.toString();
+			if (value instanceof Date)
+				return value.toString();
+			if (value instanceof String)
+				return (String) value;
+			throw new IllegalArgumentException( "cannot convert value to String" );
+		}
+		
+		@SuppressWarnings("deprecation")
+		public Date getDate()
+		{
+			if (value instanceof Date)
+				return (Date) value;
+			if (value instanceof String)
+				return new Date( (String) value );
+			throw new IllegalArgumentException( "cannot convert value to Date" );
+		}
+		
+		public List<?> getList( Integer depth )
+		{
+			if (isList())
+				return getList0( depth );
+			
+			throw new IllegalArgumentException( "cannot convert value to List" );
+		}
+		
+		private List<?> getList0( Integer depth )
+		{
+			if (depth == null)
+				depth = Integer.MAX_VALUE;
+			
+			if (depth <= 0)
+				return null;
+			
+			List<Object> l = new ArrayList<Object>( list().size() );
+			for (Integer iid: list())
+			{
+				Conf c = getConf0( iid );
+				if (c.isList())
+					l.add( c.getList0( depth-1 ) );
+				else if (c.isMap())
+					l.add( c.getMap0( depth-1 ) );
+				else
+					l.add( c.getValue() );
+			}
+			return l;
+		}
+
+		public Map<?, ?> getMap( Integer depth )
+		{
+			if (isMap())
+				return getMap0( depth );
+			
+			throw new IllegalArgumentException( "cannot convert value to Map: "+value.getClass() );
+		}
+
+		private Map<?, ?> getMap0( Integer depth )
+		{
+			if (depth == null)
+				depth = Integer.MAX_VALUE;
+			
+			if (depth <= 0)
+				return null;
+			
+			Map<String, Object> m = new HashMap<String, Object>( (map().size() * 4 + 2) / 3 );
+			for (Map.Entry<String, Integer> e: map().entrySet())
+			{
+				Conf c = getConf0( e.getValue() );
+				if (c.isList())
+					m.put( e.getKey(), c.getList0( depth-1 ) );
+				else if (c.isMap())
+					m.put( e.getKey(), c.getMap0( depth-1 ) );
+				else
+					m.put( e.getKey(), c.getValue() );
+			}
+			return m;
+		}
+	}
+
+	void setInterval( int newInterval )
+	{
+		INTERVAL = newInterval;
+	}
+}
diff --git a/services/config/src/test/java/org/apache/etch/services/config/TestYamlConfig.java b/services/config/src/test/java/org/apache/etch/services/config/TestYamlConfig.java
new file mode 100644
index 0000000..f0ca4c1
--- /dev/null
+++ b/services/config/src/test/java/org/apache/etch/services/config/TestYamlConfig.java
@@ -0,0 +1,1736 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.services.config;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.etch.services.config.Configuration.ConfigurationException;
+import org.junit.Assert;
+import org.junit.Test;
+
+/** Test of YamlConfig */
+public class TestYamlConfig
+{
+	private static final String REMOTE = "services/config/remote";
+	
+	private static final String BOGUS = "services/config/bogus";
+	
+	private static final String BLANK = "";
+	
+	private static final String EMPTY = "services/config/empty";
+	
+	private static final String DIR = "services/config/dir";
+
+	private static final String UPDATE = "services/config/update";
+	
+	private final MyConfigurationClient client = new MyConfigurationClient();
+	
+	/** @throws Exception */
+	@Test
+	public void construct1() throws Exception
+	{
+		YamlConfig c = new YamlConfig( null );
+		Assert.assertFalse( c.isLoaded() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construct2() throws Exception
+	{
+		YamlConfig c = new YamlConfig( client );
+		Assert.assertFalse( c.isLoaded() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construct3() throws Exception
+	{
+		YamlConfig c = new YamlConfig( null, null );
+		Assert.assertFalse( c.isLoaded() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construct4() throws Exception
+	{
+		YamlConfig c = new YamlConfig( client, null );
+		Assert.assertFalse( c.isLoaded() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construct5() throws Exception
+	{
+		YamlConfig c = new YamlConfig( null, REMOTE );
+		Assert.assertTrue( c.isLoaded() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construct6() throws Exception
+	{
+		YamlConfig c = new YamlConfig( client, REMOTE );
+		Assert.assertTrue( c.isLoaded() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = ConfigurationException.class)
+	public void construct7() throws Exception
+	{
+		new YamlConfig( null, BLANK );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = ConfigurationException.class)
+	public void construct8() throws Exception
+	{
+		new YamlConfig( client, BLANK );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = ConfigurationException.class)
+	public void construct9() throws Exception
+	{
+		new YamlConfig( null, EMPTY );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = ConfigurationException.class)
+	public void construct10() throws Exception
+	{
+		new YamlConfig( client, EMPTY );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = ConfigurationException.class)
+	public void construct11() throws Exception
+	{
+		new YamlConfig( null, DIR );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = ConfigurationException.class)
+	public void construct12() throws Exception
+	{
+		new YamlConfig( client, DIR );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void canload() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null );
+		Assert.assertFalse( c.canLoad( null ) );
+		Assert.assertTrue( c.canLoad( REMOTE ) );
+		Assert.assertFalse( c.canLoad( BOGUS ) );
+		Assert.assertFalse( c.canLoad( BLANK ) );
+		Assert.assertTrue( c.canLoad( EMPTY ) );
+		Assert.assertFalse( c.canLoad( DIR ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = ConfigurationException.class)
+	public void loadConfig1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null );
+		c.loadConfig( null );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void loadConfig2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null );
+		c.loadConfig( REMOTE );
+		Assert.assertTrue( c.isLoaded() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = ConfigurationException.class)
+	public void loadConfig3() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null );
+		c.loadConfig( BOGUS );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = ConfigurationException.class)
+	public void loadConfig4() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null );
+		c.loadConfig( BLANK );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = ConfigurationException.class)
+	public void loadConfig5() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null );
+		c.loadConfig( EMPTY );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = ConfigurationException.class)
+	public void loadConfig6() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null );
+		c.loadConfig( DIR );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void isLoaded() throws Exception
+	{
+		testLoadConfig( null, false );
+		testLoadConfig( REMOTE, true );
+		testLoadConfig( BOGUS, false );
+		testLoadConfig( BLANK, false );
+		testLoadConfig( EMPTY, false );
+		testLoadConfig( DIR, false );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void unloadConfig1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, null );
+		Assert.assertFalse( c.isLoaded() );
+		c.unloadConfig();
+		Assert.assertFalse( c.isLoaded() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void unloadConfig2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, null );
+		Assert.assertFalse( c.isLoaded() );
+		c.unloadConfig();
+		Assert.assertFalse( c.isLoaded() );
+		c.unloadConfig();
+		Assert.assertFalse( c.isLoaded() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void unloadConfig3() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, null );
+		Assert.assertFalse( c.isLoaded() );
+		c.loadConfig( REMOTE );
+		Assert.assertTrue( c.isLoaded() );
+		c.unloadConfig();
+		Assert.assertFalse( c.isLoaded() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void props1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// test properties on the root node
+		
+		testProps( c, r, null, "", null, "/", true, false, true, 15 );
+				
+		// test properties on the users node
+		
+		testProps( c, c.getConfigPath( r, "users" ), r, "users", null, "/users",
+			false, false, true, 4 );
+				
+		// test properties on the primes node
+		
+		testProps( c, c.getConfigPath( r, "primes" ), r, "primes", null,
+			"/primes", false, true, false, 7 );
+				
+		// test properties on the primes/4 node
+		
+		testProps( c, c.getConfigPath( r, "primes/4" ),
+			c.getConfigPath( r, "primes" ), "4", 4, "/primes/4", false, false,
+			false, null );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = NoSuchElementException.class )
+	public void props2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// value is not a List or a Map
+		c.size( c.getConfigPath( r, "primes/4" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void props3() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		// id == null
+		c.size( null );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void props4() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		// id == null
+		c.size( "#" );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void props5() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		// id == null
+		c.size( "#0" );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void props6() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null );
+		// id == null
+		c.size( "#0#" );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void root1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		// try absolute paths for root
+		
+		Assert.assertEquals( r, c.getConfigPath( null, "/" ) ); // root
+		Assert.assertEquals( r, c.getConfigPath( -1, "/" ) ); // root
+		Assert.assertEquals( r, c.getConfigPath( "abc", "/" ) ); // root
+		Assert.assertEquals( r, c.getConfigPath( false, "/" ) ); // root
+		Assert.assertEquals( r, c.getConfigPath( r, "/" ) ); // root
+		
+		// try relative paths for root
+
+		Assert.assertEquals( r, c.getConfigPath( r, "" ) ); // root
+		Assert.assertEquals( r, c.getConfigPath( r, "." ) ); // root
+		Assert.assertEquals( r, c.getConfigPath( r, "./." ) ); // root
+		Assert.assertEquals( r, c.getConfigPath( r, "././." ) ); // root
+		Assert.assertEquals( r, c.getConfigPath( r, "bool/.." ) ); // root
+		
+		// other relative paths
+		
+		Assert.assertNull( c.getConfigPath( r, ".." ) ); // parent
+		Assert.assertNotNull( c.getConfigPath( r, "bool" ) ); // child
+		
+		// bad paths
+
+		Assert.assertNull( c.getConfigPath( r, "blah" ) );
+		Assert.assertNull( c.getConfigPath( r, "blah/blah" ) );
+		Assert.assertNotNull( c.getConfigPath( r, "primes/4" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void root2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// path == null
+		c.getConfigPath( r, null );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void root3() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// path must be absolute when id == null
+		c.getConfigPath( null, "foo" );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void root4() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// id is not valid
+		c.getConfigPath( -1, "foo" );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void root5() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// id is not valid
+		c.getConfigPath( 0, "foo" );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void root6() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// id is not valid
+		c.getConfigPath( 99, "foo" );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void root7() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// id is not valid
+		c.getConfigPath( "abc", "foo" );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void root8() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// id is not valid
+		c.getConfigPath( "#abc#", "foo" );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void root9() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// id is not valid
+		c.getConfigPath( "#?#", "foo" );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void root10() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// id is not valid
+		c.getConfigPath( false, "foo" );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void root11() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// i < 0 || i >= list.size()
+		c.getConfigPath( r, "primes/12" );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void root12() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null );
+		c.getRoot();
+	}
+	
+	/** @throws Exception */
+	@Test( expected = NoSuchElementException.class )
+	public void root13() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// abc
+		c.getConfigPath( r, "primes/4/abc" );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void hasValuePath() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		Assert.assertTrue( c.hasValuePath( r, "." ) );
+		Assert.assertTrue( c.hasValuePath( r, "bool" ) );
+		Assert.assertFalse( c.hasValuePath( r, "blah" ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void getValuePath() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		Assert.assertNotNull( c.getValuePath( r, "." ) );
+		Assert.assertNotNull( c.getValuePath( r, "bool" ) );
+		Assert.assertNull( c.getValuePath( r, "blah" ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void getBooleanPath1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		Assert.assertEquals( true, c.getBooleanPath( r, "bool" ) );
+		Assert.assertEquals( false, c.getBooleanPath( r, "bool2" ) );
+		Assert.assertNull( c.getBooleanPath( r, "blah" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getBooleanPath2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		// cannot convert value to Boolean
+		c.getBooleanPath( r, "." );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getBooleanPath3() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// cannot convert value to Boolean
+		c.getBooleanPath( r, "int" );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void getIntegerPath1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		Assert.assertEquals( 23, c.getIntegerPath( r, "int" ) );
+		Assert.assertEquals( 34, c.getIntegerPath( r, "int2" ) );
+		Assert.assertNull( c.getIntegerPath( r, "blah" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getIntegerPath2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		// cannot convert value to Integer
+		c.getIntegerPath( r, "." );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getIntegerPath3() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// cannot convert value to Integer
+		c.getIntegerPath( r, "bool" );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getIntegerPath4() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// cannot convert value to Integer
+		c.getIntegerPath( r, "int3" );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void getDoublePath1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		Assert.assertEquals( 4.5, c.getDoublePath( r, "dbl" ) );
+		Assert.assertEquals( 5.6, c.getDoublePath( r, "dbl2" ) );
+		Assert.assertEquals( 67, c.getDoublePath( r, "dbl3" ) );
+		Assert.assertNull( c.getDoublePath( r, "blah" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getDoublePath2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		// cannot convert value to Double
+		c.getDoublePath( r, "." );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getDoublePath3() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// cannot convert value to Double
+		c.getDoublePath( r, "bool" );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getDoublePath4() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// cannot convert value to Double
+		c.getDoublePath( r, "dbl4" );
+	}
+	
+	/** @throws Exception */
+	@SuppressWarnings("deprecation")
+	@Test
+	public void getDatePath1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		Assert.assertEquals( new Date( "12/19/2008" ), c.getDatePath( r, "date" ) );
+		Assert.assertEquals( new Date( "12/23/2008" ), c.getDatePath( r, "date2" ) );
+		Assert.assertNull( c.getDatePath( r, "blah" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getDatePath2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		// cannot convert value to Date
+		c.getDatePath( r, "." );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getDatePath3() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// cannot convert value to Date
+		c.getDatePath( r, "bool" );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void getStringPath1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		Assert.assertEquals( "true", c.getStringPath( r, "bool" ) );
+		Assert.assertEquals( "23", c.getStringPath( r, "int" ) );
+		Assert.assertEquals( "4.5", c.getStringPath( r, "dbl" ) );
+		Assert.assertEquals( "boo", c.getStringPath( r, "str" ) );
+		Assert.assertEquals( "12/19/2008", c.getStringPath( r, "date" ) );
+		Assert.assertEquals( "Tue Dec 23 00:00:00 CST 2008", c.getStringPath( r, "date2" ) );
+		Assert.assertNull( c.getStringPath( r, "blah" ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getStringPath2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		// cannot convert value to String
+		c.getStringPath( r, "." );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getStringPath3() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// cannot convert value to String
+		c.getStringPath( r, "primes" );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getStringPath4() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// cannot convert value to String
+		c.getStringPath( r, "users" );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void getListPath1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		List<Integer> l = new ArrayList<Integer>();
+		l.add( 1 );
+		l.add( 2 );
+		l.add( 3 );
+		l.add( 5 );
+		l.add( 7 );
+		l.add( 11 );
+		l.add( 13 );
+
+		Assert.assertEquals( l, c.getListPath( r, "primes", null ) );
+		Assert.assertEquals( l, c.getListPath( r, "primes", 1 ) );
+		Assert.assertNull( c.getListPath( r, "primes", 0 ) );
+		Assert.assertNull( c.getListPath( r, "blah", null ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getListPath2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// cannot convert value to List
+		c.getListPath( r, "users", null );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getListPath3() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// cannot convert value to List
+		c.getListPath( r, "int", null );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void getMapPath1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		Map<String, Object> m = new HashMap<String, Object>();
+		m.put( "fred", 1234 );
+		m.put( "mary", 2345 );
+		m.put( "alice", 9876 );
+		m.put( "jack", 8765 );
+		
+		Assert.assertEquals( m, c.getMapPath( r, "users", null ) );
+		Assert.assertEquals( m, c.getMapPath( r, "users", 1 ) );
+		Assert.assertNull( c.getMapPath( r, "users", 0 ) );
+		Assert.assertNull( c.getMapPath( r, "blah", null ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getMapPath2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// cannot convert value to Map
+		c.getMapPath( r, "primes", null );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getMapPath3() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// cannot convert value to Map
+		c.getMapPath( r, "int", null );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void getConfigIndex1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		Object p = c.getConfigPath( r, "primes" );
+		Assert.assertEquals( 7, c.getInteger( c.getConfigIndex( p, 4 ) ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getConfigIndex2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		Object p = c.getConfigPath( r, "primes" );
+		c.getConfigIndex( p, -1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getConfigIndex3() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		Object p = c.getConfigPath( r, "primes" );
+		c.getConfigIndex( p, 99 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getConfigIndex4() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		Object p = c.getConfigPath( r, "primes" );
+		c.getConfigIndex( p, null );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getConfigIndex5() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		c.getConfigIndex( r, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void getConfigIndex6() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		c.getConfigIndex( null, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void listConfigPathIds1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		Object[] ids = c.listConfigPathIds( r, "users", null, null );
+		Assert.assertEquals( 4, ids.length );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void listConfigPathIds2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		Object[] ids = c.listConfigPathIds( r, "primes", null, null );
+		Assert.assertEquals( 7, ids.length );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = NoSuchElementException.class )
+	public void listConfigPathIds3() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// value is not a List or a Map
+		c.listConfigPathIds( r, "primes/4", null, null );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void listConfigPathIds4() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		Object[] ids = c.listConfigPathIds( r, "primes", 1, 3 );
+		Assert.assertEquals( 3, ids.length );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void listConfigPathIds5() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		Object[] ids = c.listConfigPathIds( r, "primes", 5, 4 );
+		Assert.assertEquals( 2, ids.length );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void listConfigPathIds6() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// offset < 0
+		c.listConfigPathIds( r, "primes", -1, 4 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void listConfigPathIds7() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		Object[] ids = c.listConfigPathIds( r, "primes", 7, 4 );
+		Assert.assertEquals( 0, ids.length );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void listConfigPathIds8() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// offset > size
+		c.listConfigPathIds( r, "primes", 8, 4 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void listConfigPathIds9() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null, REMOTE );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		// count < 0
+		c.listConfigPathIds( r, "primes", 0, -1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subscribePath1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( client, REMOTE );
+		client.setServer( c );
+		
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		c.subscribePath( r, "users" );
+		c.subscribePath( r, "users" );
+		
+		c.subscribePath( r, "primes" );
+		c.subscribePath( r, "primes" );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subscribePath2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( client, REMOTE );
+		client.setServer( c );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		c.subscribePath( r, "blah" );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void unsubscribePath1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( client, REMOTE );
+		client.setServer( c );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		c.subscribePath( r, "users" );
+		c.unsubscribePath( r, "users" );
+		
+		c.subscribePath( r, "primes" );
+		c.unsubscribePath( r, "primes" );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void unsubscribePath2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( client, REMOTE );
+		client.setServer( c );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+
+		c.unsubscribePath( r, "blah" );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void configValuesChanged1() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( client, REMOTE );
+		client.setServer( c );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		Assert.assertEquals( set(), client.changed );
+		
+		c.subscribe( r );
+		Thread.sleep( 100 );
+		Assert.assertEquals( set( r ), client.changed );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void configValuesChanged2() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( client, REMOTE );
+		client.setServer( c );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		Object x = c.getConfigPath( r, "users" );
+		Assert.assertNotNull( x );
+		
+		Assert.assertEquals( set(), client.changed );
+		
+		c.subscribe( x );
+		Thread.sleep( 100 );
+		Assert.assertEquals( set( x ), client.changed );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void configValuesChanged3() throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( client, REMOTE );
+		client.setServer( c );
+		Object r = c.getRoot();
+		Assert.assertNotNull( r );
+		
+		Object x = c.getConfigPath( r, "users" );
+		Assert.assertNotNull( x );
+		
+		Object y = c.getConfigPath( r, "primes" );
+		Assert.assertNotNull( y );
+
+		Assert.assertEquals( set(), client.changed );
+
+		c.subscribe( x );
+		Thread.sleep( 100 );
+		Assert.assertEquals( set( x ), client.changed );
+
+		c.subscribe( y );
+		Thread.sleep( 100 );
+		Assert.assertEquals( set( y ), client.changed );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void update0() throws Exception
+	{
+		YamlConfig c = new YamlConfig( client, UPDATE+0 );
+		client.setServer( c );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update1() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+1 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 3, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update2() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+2 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 6, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( 3, c.getIntegerPath( root, "baz" ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update3() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+3 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 4, c.size( root ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update4() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+4 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 5 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update5() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+5 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4, 5 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update6() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+6 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update7() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+7 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 6, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( map( "x", 6, "y", 7, "z", 8 ), c.getMapPath( root, "map1", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update8() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+8 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 6, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( 3, 4, 5 ), c.getListPath( root, "array1", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update9() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+9 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 4, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update10() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+10 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 4, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update11() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+11 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), map( "d", 8, "e", 9, "f", 10 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update12() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+12 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), list( 4, 5, 6 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update13() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+13 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update14() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+14 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update15() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+15 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( map( "x", 4, "y", 5, "z", 6 ), c.getMapPath( root, "bar", null ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update16() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+16 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( list( 4, 5, 6 ), c.getListPath( root, "bar", null ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update17() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+17 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( 17, c.getIntegerPath( root, "map" ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update18() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+18 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "x", 8, "y", 9, "z", 10 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update19() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+19 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( list( 3, 4, 5 ), c.getListPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update20() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+20 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( 17, c.getIntegerPath( root, "array" ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update21() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+21 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( map( "i", 9, "j", 8 ), c.getMapPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update22() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+22 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 4, 5, 6 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update23() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+23 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), map( "x", 8, "y", 7, "z", 6 ) ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update24() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+24 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 1, 2, 3 ), list( 2, 3, 4 ) ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update25() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+25 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", 25, list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update26() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+26 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "x", 6, "y", 7, "z", 8 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update27() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+27 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", list( 2, 3, 4 ), list( 1, 2, 3 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update28() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+28 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), 34, "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update29() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+29 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), map( "x", 7, "y", 8, "z", 9 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void update30() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+30 );
+		Object root = c.getRoot();
+		
+		Assert.assertEquals( 5, c.size( root ) );
+		Assert.assertEquals( 2, c.getIntegerPath( root, "foo" ) );
+		Assert.assertEquals( 4, c.getIntegerPath( root, "bar" ) );
+		Assert.assertEquals( list( 2, 3, 4 ), c.getListPath( root, "array", null ) );
+		Assert.assertEquals( map( "a", 5, "b", 6, "c", 7 ), c.getMapPath( root, "map", null ) );
+		Assert.assertEquals( list( "fish", map( "a", 5, "b", 6, "c", 7 ), list( 2, 3, 4 ), "bear" ), c.getListPath( root, "list", null ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subscribeUpdate0() throws Exception
+	{
+		setupUpdate( UPDATE+0, "." );
+		Assert.assertEquals( set(), client.changed );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subscribeUpdate1a() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+1, "." );
+		Assert.assertEquals( set( c.getConfigPath( c.getRoot(), "." ) ), client.changed );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subscribeUpdate1b() throws Exception
+	{
+		YamlConfig c = setupUpdate( UPDATE+1, "foo" );
+		Assert.assertEquals( set( c.getConfigPath( c.getRoot(), "foo" ) ), client.changed );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void subscribeUpdate1c() throws Exception
+	{
+		setupUpdate( UPDATE+1, "bar" );
+		Assert.assertEquals( set(), client.changed );
+	}
+	
+	private void testLoadConfig( String name, boolean expected )
+		throws Exception
+	{
+		ConfigurationServer c = new YamlConfig( null );
+		Assert.assertFalse( c.isLoaded() );
+		try { c.loadConfig( name ); } catch ( Exception e ) {}
+		Assert.assertEquals( expected, c.isLoaded() );
+		c.unloadConfig();
+		Assert.assertFalse( c.isLoaded() );
+	}
+	
+	private void testProps( ConfigurationServer c, Object node, Object parent,
+		String name, Integer index, String path, boolean isRoot, boolean isList,
+		boolean isMap, Integer size )
+	{
+		Assert.assertEquals( parent, c.getParent( node ) );
+		Assert.assertEquals( name, c.getName( node ) );
+		Assert.assertEquals( index, c.getIndex( node ) );
+		Assert.assertEquals( path, c.getPath( node ) );
+		Assert.assertEquals( isRoot, c.isRoot( node ) );
+		Assert.assertEquals( isList, c.isList( node ) );
+		Assert.assertEquals( isMap, c.isMap( node ) );
+		if (size != null)
+			Assert.assertEquals( size, c.size( node ) );
+	}
+	
+	private YamlConfig setupUpdate( String updateConfig, String path ) throws Exception
+	{
+		YamlConfig c = new YamlConfig( client, UPDATE+0 );
+		client.setServer( c );
+		Object root = c.getRoot();
+		
+		c.setInterval( 50 );
+		c.subscribePath( root, path );
+		c.setConfig( updateConfig );
+		Thread.sleep( 1000 );
+		c.unsubscribeAll();
+		
+		return c;
+	}
+	
+	private YamlConfig setupUpdate( String updateConfig ) throws Exception
+	{
+		return setupUpdate( updateConfig, "." );
+	}
+	
+	private List<?> list( Object ... objs )
+	{
+		List<Object> list = new ArrayList<Object>( objs.length );
+		for (Object obj: objs)
+			list.add( obj );
+		return list;
+	}
+	
+	private Map<?, ?> map( Object ... objs )
+	{
+		Map<String, Object> map = new HashMap<String, Object>(
+			(objs.length * 2 + 2) / 3 );
+		for (int i = 0; i < objs.length; i += 2)
+			map.put( (String) objs[i], objs[i + 1] );
+		return map;
+	}
+	
+	private Set<?> set( Object ... objs )
+	{
+		Set<Object> set = new HashSet<Object>();
+		for (Object o: objs)
+			set.add( o );
+		return set;
+	}
+	
+	private static class MyConfigurationClient implements ConfigurationClient
+	{
+		public void configValuesChanged( Object[] updated )
+		{
+			Set<Object> changed = new HashSet<Object>();
+			for (Object id: updated)
+			{
+				System.out.println( "id changed: "+id );
+				System.out.println( "path changed: "+server.getPath( id ) );
+				changed.add( id );
+			}
+			this.changed = changed;
+		}
+		
+		private Set<Object> changed = new HashSet<Object>();
+
+		public void setServer( ConfigurationServer server )
+		{
+			this.server = server;
+		}
+		
+		private ConfigurationServer server;
+	}
+}
diff --git a/services/config/update0.yml b/services/config/update0.yml
new file mode 100644
index 0000000..2815702
--- /dev/null
+++ b/services/config/update0.yml
@@ -0,0 +1,10 @@
+# starting point for update tests

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update1.yml b/services/config/update1.yml
new file mode 100644
index 0000000..49efa02
--- /dev/null
+++ b/services/config/update1.yml
@@ -0,0 +1,10 @@
+# update key value in map: scalar -> scalar

+foo: 3

+bar: 4

+array: [2, 3, 4]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update10.yml b/services/config/update10.yml
new file mode 100644
index 0000000..1bdd9c6
--- /dev/null
+++ b/services/config/update10.yml
@@ -0,0 +1,9 @@
+# remove list key from map

+foo: 2

+bar: 4

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update11.yml b/services/config/update11.yml
new file mode 100644
index 0000000..bf02608
--- /dev/null
+++ b/services/config/update11.yml
@@ -0,0 +1,11 @@
+# add map element to list

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - { d: 8, e: 9, f: 10 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update12.yml b/services/config/update12.yml
new file mode 100644
index 0000000..de39bbc
--- /dev/null
+++ b/services/config/update12.yml
@@ -0,0 +1,11 @@
+# add list element to list

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - [ 4, 5, 6 ]

+  - bear

diff --git a/services/config/update13.yml b/services/config/update13.yml
new file mode 100644
index 0000000..8fe3374
--- /dev/null
+++ b/services/config/update13.yml
@@ -0,0 +1,9 @@
+# remove map element from list

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update14.yml b/services/config/update14.yml
new file mode 100644
index 0000000..235ddd8
--- /dev/null
+++ b/services/config/update14.yml
@@ -0,0 +1,9 @@
+# remove list element from list

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - bear

diff --git a/services/config/update15.yml b/services/config/update15.yml
new file mode 100644
index 0000000..ad6b5d3
--- /dev/null
+++ b/services/config/update15.yml
@@ -0,0 +1,10 @@
+# update key value in map: scalar -> map

+foo: 2

+bar: { x: 4, y: 5, z: 6 }

+array: [ 2, 3, 4 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update16.yml b/services/config/update16.yml
new file mode 100644
index 0000000..6979a85
--- /dev/null
+++ b/services/config/update16.yml
@@ -0,0 +1,10 @@
+# update key value in map: scalar -> list

+foo: 2

+bar: [ 4, 5, 6 ]

+array: [ 2, 3, 4 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update17.yml b/services/config/update17.yml
new file mode 100644
index 0000000..9efa303
--- /dev/null
+++ b/services/config/update17.yml
@@ -0,0 +1,10 @@
+# update key value in map: map -> scalar

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: 17

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update18.yml b/services/config/update18.yml
new file mode 100644
index 0000000..5a13787
--- /dev/null
+++ b/services/config/update18.yml
@@ -0,0 +1,10 @@
+# update key value in map: map -> map

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: { x: 8, y: 9, z: 10 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update19.yml b/services/config/update19.yml
new file mode 100644
index 0000000..753cc93
--- /dev/null
+++ b/services/config/update19.yml
@@ -0,0 +1,10 @@
+# update key value in map: map -> list

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: [ 3, 4, 5 ]

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update2.yml b/services/config/update2.yml
new file mode 100644
index 0000000..9865433
--- /dev/null
+++ b/services/config/update2.yml
@@ -0,0 +1,11 @@
+# add scalar key to map

+foo: 2

+bar: 4

+array: [2, 3, 4]

+map: { a: 5, b: 6, c: 7 }

+baz: 3

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update20.yml b/services/config/update20.yml
new file mode 100644
index 0000000..a82d959
--- /dev/null
+++ b/services/config/update20.yml
@@ -0,0 +1,10 @@
+# update key value in map: list -> scalar

+foo: 2

+bar: 4

+array: 17

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update21.yml b/services/config/update21.yml
new file mode 100644
index 0000000..e079be0
--- /dev/null
+++ b/services/config/update21.yml
@@ -0,0 +1,10 @@
+# update key value in map: list -> map

+foo: 2

+bar: 4

+array: { i: 9, j: 8 }

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update22.yml b/services/config/update22.yml
new file mode 100644
index 0000000..d222d0d
--- /dev/null
+++ b/services/config/update22.yml
@@ -0,0 +1,10 @@
+# update key value in map: list -> list

+foo: 2

+bar: 4

+array: [ 4, 5, 6 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update23.yml b/services/config/update23.yml
new file mode 100644
index 0000000..868debe
--- /dev/null
+++ b/services/config/update23.yml
@@ -0,0 +1,10 @@
+# update element in list: scalar -> map

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - { x: 8, y: 7, z: 6 }

diff --git a/services/config/update24.yml b/services/config/update24.yml
new file mode 100644
index 0000000..a5a4255
--- /dev/null
+++ b/services/config/update24.yml
@@ -0,0 +1,10 @@
+# update element in list: scalar -> list

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - [ 2, 3, 4 ]

diff --git a/services/config/update25.yml b/services/config/update25.yml
new file mode 100644
index 0000000..0fe3bf2
--- /dev/null
+++ b/services/config/update25.yml
@@ -0,0 +1,10 @@
+# update element in list: map -> scalar

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - 25

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update26.yml b/services/config/update26.yml
new file mode 100644
index 0000000..957cc2f
--- /dev/null
+++ b/services/config/update26.yml
@@ -0,0 +1,10 @@
+# update element in list: map -> map

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { x: 6, y: 7, z: 8 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update27.yml b/services/config/update27.yml
new file mode 100644
index 0000000..0132baa
--- /dev/null
+++ b/services/config/update27.yml
@@ -0,0 +1,10 @@
+# update element in list: map -> list

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - [ 2, 3, 4 ]

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update28.yml b/services/config/update28.yml
new file mode 100644
index 0000000..a54f25c
--- /dev/null
+++ b/services/config/update28.yml
@@ -0,0 +1,10 @@
+# update element in list: list -> scalar

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - 34

+  - bear

diff --git a/services/config/update29.yml b/services/config/update29.yml
new file mode 100644
index 0000000..a74173e
--- /dev/null
+++ b/services/config/update29.yml
@@ -0,0 +1,10 @@
+# update element in list: list -> map

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - { x: 7, y: 8, z: 9 }

+  - bear

diff --git a/services/config/update3.yml b/services/config/update3.yml
new file mode 100644
index 0000000..4145e9b
--- /dev/null
+++ b/services/config/update3.yml
@@ -0,0 +1,9 @@
+# remove scalar key from map

+bar: 4

+array: [2, 3, 4]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update30.yml b/services/config/update30.yml
new file mode 100644
index 0000000..01ca082
--- /dev/null
+++ b/services/config/update30.yml
@@ -0,0 +1,10 @@
+# update element in list: list -> list

+foo: 2

+bar: 4

+array: [ 2, 3, 4 ]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 2, 3, 4 ]

+  - bear

diff --git a/services/config/update4.yml b/services/config/update4.yml
new file mode 100644
index 0000000..98d3150
--- /dev/null
+++ b/services/config/update4.yml
@@ -0,0 +1,10 @@
+# update element in list: scalar -> scalar

+foo: 2

+bar: 4

+array: [2, 3, 5]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update5.yml b/services/config/update5.yml
new file mode 100644
index 0000000..2ff8922
--- /dev/null
+++ b/services/config/update5.yml
@@ -0,0 +1,10 @@
+# add scalar element to list

+foo: 2

+bar: 4

+array: [2, 3, 4, 5]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update6.yml b/services/config/update6.yml
new file mode 100644
index 0000000..0371374
--- /dev/null
+++ b/services/config/update6.yml
@@ -0,0 +1,10 @@
+# remove scalar element from list

+foo: 2

+bar: 4

+array: [2, 3]

+map: { a: 5, b: 6, c: 7 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update7.yml b/services/config/update7.yml
new file mode 100644
index 0000000..78adf82
--- /dev/null
+++ b/services/config/update7.yml
@@ -0,0 +1,11 @@
+# add map key to map

+foo: 2

+bar: 4

+array: [2, 3, 4]

+map: { a: 5, b: 6, c: 7 }

+map1: { x: 6, y: 7, z: 8 }

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update8.yml b/services/config/update8.yml
new file mode 100644
index 0000000..89f5e91
--- /dev/null
+++ b/services/config/update8.yml
@@ -0,0 +1,11 @@
+# add list key to map

+foo: 2

+bar: 4

+array: [2, 3, 4]

+map: { a: 5, b: 6, c: 7 }

+array1: [3, 4, 5]

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/services/config/update9.yml b/services/config/update9.yml
new file mode 100644
index 0000000..772b82f
--- /dev/null
+++ b/services/config/update9.yml
@@ -0,0 +1,9 @@
+# remove map key from map

+foo: 2

+bar: 4

+array: [2, 3, 4]

+list:

+  - fish

+  - { a: 5, b: 6, c: 7 }

+  - [ 1, 2, 3 ]

+  - bear

diff --git a/tests/build.xml b/tests/build.xml
new file mode 100644
index 0000000..316ae89
--- /dev/null
+++ b/tests/build.xml
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-tests" basedir="." default="help">
+    <description>Functional Tests</description>
+    <property name="Etch.basedir" location="${basedir}/.." />
+    <import file="${Etch.basedir}/build-support/etch.includes.xml" />
+    <target name="help"><echo>Please select a target...</echo></target>
+    
+    <!-- import etch task -->
+    <taskdef
+        onerror="report"
+        resource="org/apache/etch/tools/ant/etch.xml"
+        classpath="${Etch.HOME}/lib/${etch-ant-task.jar}" />
+
+    <!-- set properties -->
+    <property name="target"            location="${basedir}/target" />
+    <property name="src"               location="${basedir}/src" />
+    <property name="bin"               location="${target}/bin" />
+    <property name="generated-sources" location="${target}/generated-sources/" />
+    <property name="classes"           location="${target}/classes" />
+    <property name="test-results"      location="${target}/test-results" />
+    <property name="nunit-results"     location="${target}/nunit-results" />
+
+    <!-- macros -->
+    <macrodef name="etch-test">
+        <attribute name="home" default="${Etch.HOME}" />
+        <attribute name="binding" />
+        <attribute name="file" />
+        <attribute name="what" default="both, intf" />
+        <attribute name="outputDir" default="${generated-sources}/main/etch/@{binding}" />
+        <attribute name="templateOutputDir" default="${src}/main/@{binding}" />
+        <element name="etchelements" implicit="true" optional="true" />
+        <sequential>
+            <etch home="@{home}" binding="@{binding}" outputDir="@{outputDir}" what="@{what}" file="@{file}" >
+                <etchelements />
+            </etch>
+        </sequential>
+    </macrodef>
+    
+    <macrodef name="generate-sources">
+        <attribute name="binding" />
+        <sequential>
+            
+            <!-- generate sources -->
+            <mkdir dir="${generated-sources}/main/etch/@{binding}" />
+            <etch-test binding="@{binding}" file="${src}/main/etch/Async.etch" />
+            <etch-test binding="@{binding}" file="${src}/main/etch/Bar.etch" />
+            <etch-test binding="@{binding}" file="${src}/main/etch/Baz.etch" />
+            <etch-test binding="@{binding}" file="${src}/main/etch/BigIdl.etch" />
+            <etch-test binding="@{binding}" file="${src}/main/etch/Closing.etch" />
+            <etch-test binding="@{binding}" file="${src}/main/etch/Cuae.etch" />
+            <etch-test binding="@{binding}" file="${src}/main/etch/Foo.etch" />
+            <etch-test binding="@{binding}" file="${src}/main/etch/Inheritance.etch" />
+            <etch-test binding="@{binding}" what="all,force" file="${src}/main/etch/Test1.etch" />
+            <etch-test binding="@{binding}" file="${src}/main/etch/Test2.etch" />
+            <etch-test binding="@{binding}" file="${src}/main/etch/Test3.etch" />
+            <etch-test binding="@{binding}" file="${src}/main/etch/Test4.etch" />
+            <etch-test binding="@{binding}" file="${src}/main/etch/Test6.etch" />
+            <etch-test binding="@{binding}" what="all,force" file="${src}/main/etch/TestIncludes.etch" />
+            <etch-test binding="@{binding}" file="${src}/main/etch/Types.etch" />
+        
+            <!-- negative tests -->
+            <!-- <etch-test binding="@{binding}" file="${src}/main/etch/Test5.etch" /> -->
+            <!-- <etch-test binding="@{binding}" file="${src}/main/etch/TestReservedWords.etch" /> -->
+
+        </sequential>
+    </macrodef>
+    
+    <!-- initialize -->
+    <target name="init" >
+        <mkdir dir="${target}" />
+        <mkdir dir="${bin}" />
+        <mkdir dir="${generated-sources}" />
+        <mkdir dir="${classes}" />
+        <mkdir dir="${test-results}" />
+        <mkdir dir="${nunit-results}" />
+    </target>
+    
+    <!-- build the server -->
+    <target name="generate-java" >
+        <generate-sources binding="java" />
+    </target>
+
+    <target name="generate-xml" >
+        <generate-sources binding="xml" />
+    </target>
+    
+    <target name="generate-csharp" >
+        <generate-sources binding="csharp" />
+    </target>
+    
+    <target name="init-sources-for-clover" if="Clover.enabled">
+        <initialize-clover suffix="etchtests" >
+            <fileset dir="${src}/main/java" >
+                <include name="**/*.java" />
+            </fileset>
+            <fileset dir="${generated-sources}/main/etch/java" >
+                <include name="**/*.java" />
+                <exclude name="**/*BigIdl*.java" />
+            </fileset>
+            <testsources dir="${src}/test/java" >
+                <include name="**/*.java" />
+            </testsources>
+        </initialize-clover>
+    </target>
+    
+    <target name="build-java" depends="generate-java,init-sources-for-clover">
+        <!-- compile sources -->
+        <mkdir dir="${classes}" />
+        <javac target="1.5" destdir="${classes}">
+            <src path="${generated-sources}/main/etch/java" />
+            <src path="${src}/main/java" />
+            <src path="${src}/test/java" />
+            <classpath>
+                <pathelement location="${Etch.HOME}/lib/${etch-java-runtime.jar}" />
+                <pathelement location="${Etch.dependency.junit.jar}" />
+                <pathelement location="${Etch.HOME}/lib/${etch-compiler.jar}" />
+            </classpath>
+        </javac>
+    </target>
+    
+    <target name="test-java" depends="build-java" >
+        <!-- Run Unit Tests -->
+        <junit printsummary="yes" haltonfailure="no" dir="${classes}"
+            errorProperty="build.tests.fail" failureProperty="build.tests.fail">
+            <classpath>
+                <pathelement location="${classes}" />
+                <pathelement location="${Etch.HOME}/lib/${etch-java-runtime.jar}" />
+                <pathelement location="${Etch.dependency.junit.jar}" />
+                <pathelement location="${Etch.HOME}/lib/${etch-compiler.jar}" />
+                <!-- TODO: remove if clover not available -->
+                <pathelement location="${Etch.dependency.clover.jar}"/>
+            </classpath>
+            <formatter type="xml"/>
+            <batchtest fork="true" todir="${test-results}">
+                <fileset dir="${src}/test/java">
+                    <include name="**/Test*.java" />
+                    <!-- TODO   debug Test*Xml failures -->
+                    <exclude name="**/Test*Xml.java" />
+                </fileset>
+            </batchtest>
+        </junit>
+    </target>
+    
+    <target name="build-csharp" depends="generate-csharp,build-tests-csharp"
+        if="BUILD.csharp" />
+    
+    <target name="build-tests-csharp"
+        depends="build-tests-csharp-dotnet,build-tests-csharp-mono" />
+    
+    <target name="build-tests-csharp-dotnet" if="USE.dotnet" >
+        <msbuild buildfile="${src}/test/csharp/TestsProj/TestsProj.csproj">
+            <property name="Configuration" value="${Etch.build.target}" />
+        </msbuild>
+    </target>
+    
+    <target name="build-tests-csharp-mono" if="USE.mono" >
+        <echo message="TODO: build w/ mono" />
+    </target>
+
+    <target name="test-csharp" depends="build-csharp" if="BUILD.csharp" >
+        <mkdir dir="${nunit-results}" />
+
+        <nunit xmlout="${nunit-results}/NUnitResults.xml">
+            <testassembly name="${src}/test/csharp/TestsProj/bin/${Etch.build.target}/Tests.dll" />
+        </nunit>
+
+        <xslt style="${Etch.buildSupportDirectory}/NUnitToJUnit.xsl"
+                in="${nunit-results}/NUnitResults.xml" out="${test-results}/TEST-NUnitResults.xml" />
+    </target>
+    
+    <target name="build-xml" depends="generate-xml" >
+    
+    </target>
+    
+    <target name="test-xml" depends="build-xml" >
+    
+    </target>
+    
+    <!-- build sources -->
+    <target name="build" depends="init,build-java,build-csharp,build-xml" />
+
+    <!-- run unit tests -->
+    <target name="test" depends="build,test-java,test-csharp,test-xml" />
+        
+    <!-- clean -->    
+    <target name="clean">
+        <delete dir="${target}" quiet="true" />
+        <delete dir="${src}/test/csharp/TestsProj/obj" />
+        <delete dir="${src}/test/csharp/TestsProj/bin" />
+    </target>
+
+</project>
diff --git a/tests/src/main/csharp/etch.tests/ImplAsyncClient.cs b/tests/src/main/csharp/etch.tests/ImplAsyncClient.cs
new file mode 100644
index 0000000..70f307d
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/ImplAsyncClient.cs
@@ -0,0 +1,77 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using org.apache.etch.tests;
+
+/**
+ * Call to message translator for AsyncClient.
+ */
+namespace etch.tests
+{
+
+	public class ImplAsyncClient : BaseAsyncClient
+	{
+
+		/// 
+		/// <summary>Constructs the ImplAsyncClient.</summary>
+		///
+ 		/// <param name=server></param>
+ 		///
+		public ImplAsyncClient(RemoteAsyncServer server )
+		{
+		    this.server = server;
+            _delegate_sync = my_sync;
+            _delegate_async_free = my_async_free;
+            _delegate_async_queued = my_async_queued;
+
+		}
+
+	    private readonly RemoteAsyncServer server;
+
+        ///
+        /// <summary>Begins the call to sync.</summary>
+        ///
+        public int? my_sync(
+                int? count
+            )
+        {
+            return count > 0 ? server.sync(count - 1) + 1 : 0;
+        }
+        ///
+        /// <summary>Begins the call to async_queued.</summary>
+        ///
+        public int? my_async_queued(
+                int? count
+            )
+        {
+            return count > 0 ? server.async_queued(count - 1) + 1 : 0;
+        }
+        ///
+        /// <summary>Begins the call to async_free.</summary>
+        ///
+        public int? my_async_free(
+                int? count
+            )
+        {
+            return count > 0 ? server.async_free(count - 1) + 1 : 0;
+        }
+
+		
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/ImplAsyncServer.cs b/tests/src/main/csharp/etch.tests/ImplAsyncServer.cs
new file mode 100644
index 0000000..828d856
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/ImplAsyncServer.cs
@@ -0,0 +1,78 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using org.apache.etch.tests;
+
+/**
+ * Call to message translator for AsyncServer.
+ */
+namespace etch.tests
+{
+
+	public class ImplAsyncServer : BaseAsyncServer
+	{
+
+		/// 
+		/// <summary>Constructs the ImplAsyncServer.</summary>
+		///
+ 		/// <param name=client></param>
+ 		///
+		public ImplAsyncServer(RemoteAsyncClient client )
+		{
+		    this.client = client;
+            _delegate_async_free = my_async_free;
+            _delegate_async_queued = my_async_queued;
+            _delegate_sync = my_sync;      
+		}
+
+	    private readonly RemoteAsyncClient client;
+
+
+        ///
+        /// <summary>Begins the call to sync.</summary>
+        ///
+        public int? my_sync(
+                int? count
+            )
+        {
+            return count > 0 ? client.sync(count - 1) + 1 : 0;
+        }
+        ///
+        /// <summary>Begins the call to async_queued.</summary>
+        ///
+        public int? my_async_queued(
+                int? count
+            )
+        {
+            return count > 0 ? client.async_queued(count - 1) + 1 : 0;
+        }
+        ///
+        /// <summary>Begins the call to async_free.</summary>
+        ///
+        public int? my_async_free(
+                int? count
+            )
+        {
+            return count > 0 ? client.async_free(count - 1) + 1 : 0;
+        }
+
+		
+		
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/ImplClosingClient.cs b/tests/src/main/csharp/etch.tests/ImplClosingClient.cs
new file mode 100644
index 0000000..a5f15ab
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/ImplClosingClient.cs
@@ -0,0 +1,54 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using org.apache.etch.tests;
+
+/**
+ * Call to message translator for ClosingClient.
+ */
+namespace etch.tests
+{
+
+	public class ImplClosingClient : BaseClosingClient, ObjSession
+	{
+
+		/// 
+		/// <summary>Constructs the ImplClosingClient.</summary>
+		///
+ 		/// <param name=server></param>
+ 		///
+		public ImplClosingClient(RemoteClosingServer server )
+		{
+		    this.server = server;
+		}
+
+	    private readonly RemoteClosingServer server;
+
+      
+
+        public new void _SessionNotify(Object eventObj)
+        {
+            Console.WriteLine("ImplClosingClient._sessionNotify" + eventObj);
+        }
+
+		
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/ImplClosingServer.cs b/tests/src/main/csharp/etch.tests/ImplClosingServer.cs
new file mode 100644
index 0000000..726e7ec
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/ImplClosingServer.cs
@@ -0,0 +1,65 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using org.apache.etch.tests;
+
+/**
+ * Call to message translator for ClosingServer.
+ */
+namespace etch.tests
+{
+
+	public class ImplClosingServer : BaseClosingServer,ObjSession
+	{
+
+		/// 
+		/// <summary>Constructs the ImplClosingServer.</summary>
+		///
+ 		/// <param name=client></param>
+ 		///
+		public ImplClosingServer(RemoteClosingClient client )
+		{
+		    this.client = client;
+            _delegate_close = Myclose;
+
+		}
+
+	    private readonly RemoteClosingClient client;
+
+        public void Myclose()
+        {
+            Console.WriteLine("ImplClosingServer.sayingStopToClient");
+            client._TransportControl(TransportConsts.STOP, null);
+
+            Console.WriteLine("ImplClosingServer.saidStopToClient");
+        }
+
+       
+
+        public new void _SessionNotify(Object eventObj)
+        {
+            Console.WriteLine("ImplClosingServer _sessionNotify" + eventObj);
+        }
+
+		
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/ImplCuaeClient.cs b/tests/src/main/csharp/etch.tests/ImplCuaeClient.cs
new file mode 100644
index 0000000..2169f44
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/ImplCuaeClient.cs
@@ -0,0 +1,60 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using org.apache.etch.tests;
+using org.apache.etch.tests.types.Cuae;
+
+/**
+ * Call to message translator for CuaeClient.
+ */
+namespace etch.tests
+{
+
+	public class ImplCuaeClient : BaseCuaeClient
+	{
+
+		/// 
+		/// <summary>Constructs the ImplCuaeClient.</summary>
+		///
+ 		/// <param name=server></param>
+ 		///
+		public ImplCuaeClient(RemoteCuaeServer server )
+		{
+		    this.server = server;
+            _delegate_doit2 = Mydoit2;
+		}
+
+	    private readonly RemoteCuaeServer server;
+
+        public Response Mydoit2(
+        Request req
+    )
+        {
+            int? reqNo = req.GetCode();
+            switch (reqNo.GetValueOrDefault())
+            {
+                case 7: return new Response("apple");
+                case 11: return new RespWithCode("banana", 37);
+                case 99: return new Response("prune");
+                default: return new RespWithCode("me putz " + req.code + " in teh bukkit", 101);
+            }
+        }
+		
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/ImplCuaeServer.cs b/tests/src/main/csharp/etch.tests/ImplCuaeServer.cs
new file mode 100644
index 0000000..0ebbca8
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/ImplCuaeServer.cs
@@ -0,0 +1,44 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using org.apache.etch.tests;
+
+/**
+ * Call to message translator for CuaeServer.
+ */
+namespace etch.tests
+{
+
+	public class ImplCuaeServer : BaseCuaeServer
+	{
+
+		/// 
+		/// <summary>Constructs the ImplCuaeServer.</summary>
+		///
+ 		/// <param name=client></param>
+ 		///
+		public ImplCuaeServer(RemoteCuaeClient client ) : base()
+		{
+		
+		}
+	
+		// Implement delegates or provide implementation of client
+		
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/ImplFooClient.cs b/tests/src/main/csharp/etch.tests/ImplFooClient.cs
new file mode 100644
index 0000000..77c4405
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/ImplFooClient.cs
@@ -0,0 +1,46 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using org.apache.etch.tests;
+
+/**
+ * Call to message translator for FooClient.
+ */
+namespace etch.tests
+{
+
+	public class ImplFooClient : BaseFooClient
+	{
+
+		/// 
+		/// <summary>Constructs the ImplFooClient.</summary>
+		///
+ 		/// <param name=server></param>
+ 		///
+		public ImplFooClient(RemoteFooServer server )
+		{
+		    this.server = server;
+		}
+
+	    private readonly RemoteFooServer server;
+	
+		// Implement delegates or provide implementation of server
+		
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/ImplFooServer.cs b/tests/src/main/csharp/etch.tests/ImplFooServer.cs
new file mode 100644
index 0000000..67d9568
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/ImplFooServer.cs
@@ -0,0 +1,112 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using org.apache.etch.tests;
+using org.apache.etch.tests.types.Bar;
+using org.apache.etch.tests.types.Baz;
+using org.apache.etch.tests.types.Foo;
+
+/**
+ * Call to message translator for FooServer.
+ */
+namespace etch.tests
+{
+
+	public class ImplFooServer : BaseFooServer
+	{
+
+		/// 
+		/// <summary>Constructs the ImplFooServer.</summary>
+		///
+ 		/// <param name=client></param>
+ 		///
+		public ImplFooServer(RemoteFooClient client )
+		{
+		    this.client = client;
+            _delegate_foo1 = Myfoo1;
+            _delegate_foo2 = Myfoo2;
+            _delegate_bar1 = Mybar1;
+            _delegate_bar2 = Mybar2;
+            _delegate_baz1 = Mybaz1;
+            _delegate_baz2 = Mybaz2;
+		}
+
+	    private readonly RemoteFooClient client;
+
+        ///
+        /// <summary>Begins the call to foo1.</summary>
+        ///
+        public bool? Myfoo1(
+                FooData fooData
+            )
+        {
+            
+            Console.WriteLine("foo1 called with " + fooData);
+            return true;
+        }
+        ///
+        /// <summary>Begins the call to foo2.</summary>
+        ///
+        public bool? Myfoo2(
+                FooData fooData
+            )
+        {
+
+            Console.WriteLine("foo2 called with " + fooData);
+            return false;
+        }
+
+
+
+        public bool? Mybaz1(
+           BazData bazData
+        )
+        {
+            Console.WriteLine("baz1 called with " + bazData);
+            return true;
+        }
+
+        public bool? Mybaz2(
+           BazData bazData
+        )
+        {
+            Console.WriteLine("baz2 called with " + bazData);
+            return false;
+        }
+
+
+        public bool? Mybar1(
+            BarData barData
+        )
+        {
+            Console.WriteLine("bar1 called with " + barData);
+            return true;
+        }
+
+        public bool? Mybar2(
+            BarData barData
+        )
+        {
+            Console.WriteLine("bar2 called with " + barData);
+            return false;
+        }
+		
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/ImplInheritanceClient.cs b/tests/src/main/csharp/etch.tests/ImplInheritanceClient.cs
new file mode 100644
index 0000000..41ee0c3
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/ImplInheritanceClient.cs
@@ -0,0 +1,46 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using org.apache.etch.tests;
+
+/**
+ * Call to message translator for InheritanceClient.
+ */
+namespace etch.tests
+{
+
+	public class ImplInheritanceClient : BaseInheritanceClient
+	{
+
+		/// 
+		/// <summary>Constructs the ImplInheritanceClient.</summary>
+		///
+ 		/// <param name=server></param>
+ 		///
+		public ImplInheritanceClient(RemoteInheritanceServer server )
+		{
+		    this.server = server;
+		}
+
+	    private readonly RemoteInheritanceServer server;
+	
+		// Implement delegates or provide implementation of server
+		
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/ImplInheritanceServer.cs b/tests/src/main/csharp/etch.tests/ImplInheritanceServer.cs
new file mode 100644
index 0000000..636c971
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/ImplInheritanceServer.cs
@@ -0,0 +1,128 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using org.apache.etch.tests;
+using org.apache.etch.tests.types.Inheritance;
+
+/**
+ * Call to message translator for InheritanceServer.
+ */
+namespace etch.tests
+{
+
+	public class ImplInheritanceServer : BaseInheritanceServer
+	{
+
+		/// 
+		/// <summary>Constructs the ImplInheritanceServer.</summary>
+		///
+ 		/// <param name=client></param>
+ 		///
+		public ImplInheritanceServer(RemoteInheritanceClient client )
+		{
+		    this.client = client;
+            _delegate_f1 = Myf1;
+            _delegate_f2 = Myf2;
+            _delegate_f3 = Myf3;
+            _delegate_f4 = Myf4;
+            _delegate_f5 = Myf5;
+            _delegate_f6 = Myf6;
+            _delegate_f7 = Myf7;
+            _delegate_f8 = Myf8;
+		}
+
+	    private readonly RemoteInheritanceClient client;
+	
+		// Implement delegates or provide implementation of client
+        ///
+        /// <summary>Begins the call to f1.</summary>
+        ///
+        public Object Myf1(
+                Object v
+            )
+        {
+            return v;
+        }
+        ///
+        /// <summary>Begins the call to f2.</summary>
+        ///
+        public S1 Myf2(
+                S1 v
+            )
+        {
+            return v;
+        }
+        ///
+        /// <summary>Begins the call to f3.</summary>
+        ///
+        public S2 Myf3(
+                S2 v
+            )
+        {
+            return v;
+        }
+        ///
+        /// <summary>Begins the call to f4.</summary>
+        ///
+        public S3 Myf4(
+                S3 v
+            )
+        {
+            return v;
+        }
+        ///
+        /// <summary>Begins the call to f5.</summary>
+        ///
+        public Object[] Myf5(
+                Object[] v
+            )
+        {
+            return v;
+        }
+        ///
+        /// <summary>Begins the call to f6.</summary>
+        ///
+        public S1[] Myf6(
+                S1[] v
+            )
+        {
+            return v;
+        }
+        ///
+        /// <summary>Begins the call to f7.</summary>
+        ///
+        public S2[] Myf7(
+                S2[] v
+            )
+        {
+            return v;
+        }
+        ///
+        /// <summary>Begins the call to f8.</summary>
+        ///
+        public S3[] Myf8(
+                S3[] v
+            )
+        {
+            return v;
+        }
+		
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/ImplTypesClient.cs b/tests/src/main/csharp/etch.tests/ImplTypesClient.cs
new file mode 100644
index 0000000..0a68f3d
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/ImplTypesClient.cs
@@ -0,0 +1,46 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using org.apache.etch.tests;
+
+/**
+ * Call to message translator for TypesClient.
+ */
+namespace etch.bindings.csharp.examples.types
+{
+
+	public class ImplTypesClient : BaseTypesClient
+	{
+
+		/// 
+		/// <summary>Constructs the ImplTypesClient.</summary>
+		///
+ 		/// <param name=server></param>
+ 		///
+		public ImplTypesClient(RemoteTypesServer server )
+		{
+		    this.server = server;
+		}
+
+	    private readonly RemoteTypesServer server;
+	
+		// Implement delegates or provide implementation of server
+		
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/ImplTypesServer.cs b/tests/src/main/csharp/etch.tests/ImplTypesServer.cs
new file mode 100644
index 0000000..bfd9155
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/ImplTypesServer.cs
@@ -0,0 +1,87 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using org.apache.etch.tests;
+
+/**
+ * Call to message translator for TypesServer.
+ */
+namespace etch.bindings.csharp.examples.types
+{
+
+    public class ImplTypesServer : BaseTypesServer
+    {
+
+        /// 
+        /// <summary>Constructs the ImplTypesServer.</summary>
+        ///
+        /// <param name=client></param>
+        ///
+        public ImplTypesServer(RemoteTypesClient client)
+        {
+            this.client = client;
+            _delegate_test1 = TestMap;
+            _delegate_test2 = TestSet;
+            _delegate_test3 = TestList;
+            _delegate_test4 = TestDateTime;
+        }
+
+        private readonly RemoteTypesClient client;
+
+        // Implement delegates or provide implementation of client
+
+        public System.Collections.IDictionary TestMap(System.Collections.IDictionary map)
+        {
+            Console.WriteLine("map = " + map);
+            foreach (object key in map.Keys)
+            {
+                string value = (string)map[key];
+                Console.WriteLine(" The key is {0} and value is {1}", key, value);
+            }
+            return map;
+        }
+
+        public System.Collections.IList TestList(System.Collections.IList list)
+        {
+            Console.WriteLine("List = " + list);
+            foreach (object key in list)
+            {
+                Console.WriteLine(" The value in list is {0}", key);
+            }
+            return list;
+        }
+
+        public System.DateTime? TestDateTime(System.DateTime? date)
+        {
+            Console.WriteLine("DateTime = " + date);
+            return date;
+        }
+
+        public System.Collections.Hashtable TestSet(System.Collections.Hashtable table)
+        {
+            foreach (object key in table.Keys)
+            {
+                Console.WriteLine(" The value in set is {0}", key);
+            }
+            return table;
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/MainAsyncClient.cs b/tests/src/main/csharp/etch.tests/MainAsyncClient.cs
new file mode 100644
index 0000000..e62cf8e
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/MainAsyncClient.cs
@@ -0,0 +1,73 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using org.apache.etch.tests;
+
+namespace etch.tests
+{
+
+///
+///<summary> Main implementation for AsyncClient. </summary>
+///
+public class MainAsyncClient : AsyncHelper.AsyncClientFactory
+{
+	///
+	/// <summary>Main for AsyncClient</summary>
+	/// <param name="args"></param>
+	///
+	public static void Main(String[] args)
+	{
+		string uri = "tcp://localhost:4001";
+		if (args.Length > 0)
+			uri = args[0];
+
+		MainAsyncClient implFactory = new MainAsyncClient();
+		RemoteAsyncServer server = AsyncHelper.NewServer( uri, null, implFactory );
+		
+		server._TransportControl(TransportConsts.START_AND_WAIT_UP, 4000 );
+
+		// Insert Your Code Here
+		//---------------------------------------------------------------------
+
+		server._TransportControl(TransportConsts.STOP_AND_WAIT_DOWN, 4000 );
+
+	}
+
+	///
+	/// <summary>Constructs the MainAsyncClient.</summary>
+	///
+	public MainAsyncClient()
+	{
+		// Nothing to do.
+	}
+
+	///
+	/// <summary>Return a new instance of AsyncClient.</summary>
+	/// @param server
+	///
+	public AsyncClient NewAsyncClient( RemoteAsyncServer server )
+	{
+		return new ImplAsyncClient( server );
+	}
+
+}
+
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/MainAsyncListener.cs b/tests/src/main/csharp/etch.tests/MainAsyncListener.cs
new file mode 100644
index 0000000..df1c3d4
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/MainAsyncListener.cs
@@ -0,0 +1,67 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using org.apache.etch.tests;
+
+namespace etch.tests
+{
+
+///
+///<summary> Main implementation for AsyncListener. </summary>
+///
+public class MainAsyncListener : AsyncHelper.AsyncServerFactory
+{
+	///
+ 	/// <summary>Main for AsyncListener.</summary>
+	/// <param name="args"></param>
+	///
+	public static void Main(String[] args)
+	{
+		string uri = "tcp://localhost:4001";
+		if (args.Length > 0)
+			uri = args[0];
+
+		MainAsyncListener implFactory = new MainAsyncListener();
+        ServerFactory listener = AsyncHelper.NewListener(uri, null, implFactory);
+
+		listener.TransportControl( TransportConsts.START_AND_WAIT_UP, 4000 );
+	}
+
+	///
+	/// <summary>Constructs the MainAsyncListener.</summary>
+	///
+	public MainAsyncListener()
+	{
+		// Nothing to do.
+	}
+
+	///
+	/// <summary>Return a new instance of AsyncServer.</summary>
+	/// @param client
+	///
+	public AsyncServer NewAsyncServer( RemoteAsyncClient client )
+	{
+		return new ImplAsyncServer( client );
+	}
+}
+
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/MainClosingClient.cs b/tests/src/main/csharp/etch.tests/MainClosingClient.cs
new file mode 100644
index 0000000..e55dedd
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/MainClosingClient.cs
@@ -0,0 +1,90 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Threading;
+using etch.tests;
+using org.apache.etch.tests;
+
+namespace etch.bindings.csharp.examples.closing
+{
+
+///
+///<summary> Main implementation for ClosingClient. </summary>
+///
+public class MainClosingClient : ClosingHelper.ClosingClientFactory
+{
+	///
+	/// <summary>Main for ClosingClient</summary>
+	/// <param name="args"></param>
+	///
+	public static void Main(String[] args)
+	{
+		string uri = "tcp://localhost:4001";
+		if (args.Length > 0)
+			uri = args[0];
+       
+
+
+		MainClosingClient implFactory = new MainClosingClient();
+		RemoteClosingServer server = ClosingHelper.NewServer( uri, null, implFactory );
+
+        Console.WriteLine("MainClosingClient.startingServer");
+        
+      
+        server._StartAndWaitUp(4000);
+
+        Console.WriteLine("MainClosingClient.serverUp");
+
+        Thread.Sleep(100);
+
+        Console.WriteLine("MainClosingClient.sayingCloseToServer");
+        server.close();
+        Console.WriteLine("MainClosingClient.saidCloseToServer");
+
+        Thread.Sleep(100);
+
+        Console.WriteLine("MainClosingClient.waitingServerDown");
+
+        server._WaitDown(4000);
+
+        Console.WriteLine("MainClosingClient.serverDown");
+
+	}
+
+	///
+	/// <summary>Constructs the MainClosingClient.</summary>
+	///
+	public MainClosingClient()
+	{
+		// Nothing to do.
+	}
+
+	///
+	/// <summary>Return a new instance of ClosingClient.</summary>
+	/// @param server
+	///
+	public ClosingClient NewClosingClient( RemoteClosingServer server )
+	{
+		return new ImplClosingClient( server );
+	}
+
+}
+
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/MainClosingListener.cs b/tests/src/main/csharp/etch.tests/MainClosingListener.cs
new file mode 100644
index 0000000..61f8d74
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/MainClosingListener.cs
@@ -0,0 +1,70 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using etch.tests;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using org.apache.etch.tests;
+
+namespace etch.bindings.csharp.examples.closing
+{
+
+///
+///<summary> Main implementation for ClosingListener. </summary>
+///
+public class MainClosingListener : ClosingHelper.ClosingServerFactory
+{
+	///
+ 	/// <summary>Main for ClosingListener.</summary>
+	/// <param name="args"></param>
+	///
+	public static void Main(String[] args)
+	{
+		string uri = "tcp://localhost:4001";
+	/*	if (args.Length > 0)
+			uri = args[0]; */
+
+		MainClosingListener implFactory = new MainClosingListener();
+        ServerFactory listener = ClosingHelper.NewListener(uri, null, implFactory);
+
+		listener.TransportControl( TransportConsts.START_AND_WAIT_UP, 4000 );
+
+        Console.WriteLine("Listener Started");
+	}
+
+	///
+	/// <summary>Constructs the MainClosingListener.</summary>
+	///
+	public MainClosingListener()
+	{
+		// Nothing to do.
+	}
+
+	///
+	/// <summary>Return a new instance of ClosingServer.</summary>
+	/// @param client
+	///
+	public ClosingServer NewClosingServer( RemoteClosingClient client )
+	{
+		return new ImplClosingServer( client );
+	}
+}
+
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/MainCuaeClient.cs b/tests/src/main/csharp/etch.tests/MainCuaeClient.cs
new file mode 100644
index 0000000..3f74f0b
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/MainCuaeClient.cs
@@ -0,0 +1,101 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using org.apache.etch.tests;
+using org.apache.etch.tests.types.Cuae;
+
+namespace etch.tests
+{
+
+///
+///<summary> Main implementation for CuaeClient. </summary>
+///
+public class MainCuaeClient : CuaeHelper.CuaeClientFactory
+{
+	///
+	/// <summary>Main for CuaeClient</summary>
+	/// <param name="args"></param>
+	///
+	public static void Main(String[] args)
+	{
+		string uri = "tcp://localhost:4001";
+		if (args.Length > 0)
+			uri = args[0];
+
+        MainCuaeListener.Main1(new String[] { });
+
+
+		MainCuaeClient implFactory = new MainCuaeClient();
+		RemoteCuaeServer server = CuaeHelper.NewServer( uri, null, implFactory );
+		
+		server._TransportControl(TransportConsts.START_AND_WAIT_UP, 4000 );
+
+        Console.WriteLine("--------doit(23)-------------------------------------");
+        Console.WriteLine("doit( 23 ) => {0}\n",
+            server.doit1(new Request(23)));
+
+        Console.WriteLine("--------doit(23,\"skiddoo\")-------------------------------------");
+        Console.WriteLine("doit( 23,\"skiddoo\" ) => {0}\n",
+            server.doit1(new ReqWithMessage(23, "skiddoo")));
+
+
+
+        Console.WriteLine("------------doit( 19 )-----------------------------");
+        Console.WriteLine("doit( 19 ) => {0}\n",
+            server.doit1(new Request(19)));
+
+        Console.WriteLine("------------doit( 13 )-----------------------------");
+        Console.WriteLine("doit( 13,\"unlucky friday\" ) => {0}\n",
+            server.doit1(new ReqWithMessage(13, "unlucky friday")));
+
+        Console.WriteLine("----------------------------------------------");
+        Console.WriteLine("doit( 13 ) => {0}\n",
+            server.doit1(new Request(13)));
+
+        Console.WriteLine("--- doit( 23 ) -------------------------------------------");
+        Console.WriteLine("doit( [23] ) => {0}\n",
+            server.doit3(new Request[] { new Request(23) })[0]);
+
+
+		server._TransportControl(TransportConsts.STOP_AND_WAIT_DOWN, 4000 );
+
+	}
+
+	///
+	/// <summary>Constructs the MainCuaeClient.</summary>
+	///
+	public MainCuaeClient()
+	{
+		// Nothing to do.
+	}
+
+	///
+	/// <summary>Return a new instance of CuaeClient.</summary>
+	/// @param server
+	///
+	public CuaeClient NewCuaeClient( RemoteCuaeServer server )
+	{
+		return new ImplCuaeClient( server );
+	}
+
+}
+
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/MainCuaeListener.cs b/tests/src/main/csharp/etch.tests/MainCuaeListener.cs
new file mode 100644
index 0000000..b367fdf
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/MainCuaeListener.cs
@@ -0,0 +1,64 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Transport;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace etch.tests
+{
+
+///
+///<summary> Main implementation for CuaeListener. </summary>
+///
+public class MainCuaeListener : MyCuaeHelper.MyCuaeServerFactory
+{
+	///
+ 	/// <summary>Main for CuaeListener.</summary>
+	/// <param name="args"></param>
+	///
+	public static void Main1(String[] args)
+	{
+		string uri = "tcp://localhost:4001";
+		/*if (args.Length > 0)
+			uri = args[0]; */
+
+		MainCuaeListener implFactory = new MainCuaeListener();
+        ServerFactory listener = MyCuaeHelper.NewListener(uri, null, implFactory);
+
+		listener.TransportControl( TransportConsts.START_AND_WAIT_UP, 4000 );
+	}
+
+	///
+	/// <summary>Constructs the MainCuaeListener.</summary>
+	///
+	public MainCuaeListener()
+	{
+		// Nothing to do.
+	}
+
+
+    public SessionMessage NewMyCuaeServer(DeliveryService d, Pool queued, Pool free, MyValueFactoryCuae vf)
+    {
+        return new MyCuaeServerStub(d, queued, free, vf);
+    }
+}
+
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/MainFooClient.cs b/tests/src/main/csharp/etch.tests/MainFooClient.cs
new file mode 100644
index 0000000..471fcdb
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/MainFooClient.cs
@@ -0,0 +1,107 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using org.apache.etch.tests;
+using org.apache.etch.tests.types.Bar;
+using org.apache.etch.tests.types.Baz;
+using org.apache.etch.tests.types.Foo;
+
+namespace etch.tests
+{
+
+///
+///<summary> Main implementation for FooClient. </summary>
+///
+public class MainFooClient : FooHelper.FooClientFactory
+{
+	///
+	/// <summary>Main for FooClient</summary>
+	/// <param name="args"></param>
+	///
+	public static void Main(String[] args)
+	{
+		string uri = "tcp://localhost:4001";
+        MainFooListener.Main1(null);
+
+		MainFooClient implFactory = new MainFooClient();
+		RemoteFooServer server = FooHelper.NewServer( uri, null, implFactory );
+		
+		server._TransportControl(TransportConsts.START_AND_WAIT_UP, 4000 );
+
+        // Insert Your Code Here
+        //---------------------------------------------------------------------
+        StrStrHashMap bazTable = new StrStrHashMap();
+        bazTable.Add("def", "baz");
+
+        StrStrHashMap barTable = new StrStrHashMap();
+        barTable.Add("def", "bar");
+
+        StrStrHashMap fooTable = new StrStrHashMap();
+        fooTable.Add("def", "foo");
+
+        BazData bazData = new BazData(1, bazTable);
+        BarData barData = new BarData(2, barTable, bazData);
+        FooData fooData = new FooData(3, fooTable, barData, bazData);
+
+        bool? ok;
+
+        ok = server.baz1(bazData);
+        Console.WriteLine("baz1 => " + ok);
+
+        ok = server.baz2(bazData);
+        Console.WriteLine("baz2 => " + ok);
+
+        ok = server.bar1(barData);
+        Console.WriteLine("bar1 => " + ok);
+
+        ok = server.bar2(barData);
+        Console.WriteLine("bar2 => " + ok);
+
+        ok = server.foo1(fooData);
+        Console.WriteLine("foo1 => " + ok);
+
+        ok = server.foo2(fooData);
+        Console.WriteLine("foo2 => " + ok);
+
+		server._TransportControl(TransportConsts.STOP_AND_WAIT_DOWN, 4000 );
+
+	}
+
+	///
+	/// <summary>Constructs the MainFooClient.</summary>
+	///
+	public MainFooClient()
+	{
+		// Nothing to do.
+	}
+
+	///
+	/// <summary>Return a new instance of FooClient.</summary>
+	/// @param server
+	///
+	public FooClient NewFooClient( RemoteFooServer server )
+	{
+		return new ImplFooClient( server );
+	}
+
+}
+
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/MainFooListener.cs b/tests/src/main/csharp/etch.tests/MainFooListener.cs
new file mode 100644
index 0000000..262bb95
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/MainFooListener.cs
@@ -0,0 +1,66 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using org.apache.etch.tests;
+
+namespace etch.tests
+{
+
+///
+///<summary> Main implementation for FooListener. </summary>
+///
+public class MainFooListener : FooHelper.FooServerFactory
+{
+	///
+ 	/// <summary>Main for FooListener.</summary>
+	/// <param name="args"></param>
+	///
+	public static void Main1(String[] args)
+	{
+		string uri = "tcp://localhost:4001";
+	
+
+		MainFooListener implFactory = new MainFooListener();
+        ServerFactory listener = FooHelper.NewListener(uri, null, implFactory);
+
+		listener.TransportControl( TransportConsts.START_AND_WAIT_UP, 4000 );
+	}
+
+	///
+	/// <summary>Constructs the MainFooListener.</summary>
+	///
+	public MainFooListener()
+	{
+		// Nothing to do.
+	}
+
+	///
+	/// <summary>Return a new instance of FooServer.</summary>
+	/// @param client
+	///
+	public FooServer NewFooServer( RemoteFooClient client )
+	{
+		return new ImplFooServer( client );
+	}
+}
+
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/MainInheritanceClient.cs b/tests/src/main/csharp/etch.tests/MainInheritanceClient.cs
new file mode 100644
index 0000000..3819502
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/MainInheritanceClient.cs
@@ -0,0 +1,73 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using org.apache.etch.tests;
+
+namespace etch.tests
+{
+
+///
+///<summary> Main implementation for InheritanceClient. </summary>
+///
+public class MainInheritanceClient : InheritanceHelper.InheritanceClientFactory
+{
+	///
+	/// <summary>Main for InheritanceClient</summary>
+	/// <param name="args"></param>
+	///
+	public static void Main(String[] args)
+	{
+		string uri = "tcp://localhost:4001";
+		if (args.Length > 0)
+			uri = args[0];
+
+		MainInheritanceClient implFactory = new MainInheritanceClient();
+		RemoteInheritanceServer server = InheritanceHelper.NewServer( uri, null, implFactory );
+		
+		server._TransportControl(TransportConsts.START_AND_WAIT_UP, 4000 );
+
+		// Insert Your Code Here
+		//---------------------------------------------------------------------
+
+		server._TransportControl(TransportConsts.STOP_AND_WAIT_DOWN, 4000 );
+
+	}
+
+	///
+	/// <summary>Constructs the MainInheritanceClient.</summary>
+	///
+	public MainInheritanceClient()
+	{
+		// Nothing to do.
+	}
+
+	///
+	/// <summary>Return a new instance of InheritanceClient.</summary>
+	/// @param server
+	///
+	public InheritanceClient NewInheritanceClient( RemoteInheritanceServer server )
+	{
+		return new ImplInheritanceClient( server );
+	}
+
+}
+
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/MainInheritanceListener.cs b/tests/src/main/csharp/etch.tests/MainInheritanceListener.cs
new file mode 100644
index 0000000..26b5a5b
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/MainInheritanceListener.cs
@@ -0,0 +1,67 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using org.apache.etch.tests;
+
+namespace etch.tests
+{
+
+///
+///<summary> Main implementation for InheritanceListener. </summary>
+///
+public class MainInheritanceListener : InheritanceHelper.InheritanceServerFactory
+{ 
+	///
+ 	/// <summary>Main for InheritanceListener.</summary>
+	/// <param name="args"></param>
+	///
+	public static void Main(String[] args)
+	{
+		string uri = "tcp://localhost:4001";
+		if (args.Length > 0)
+			uri = args[0];
+
+		MainInheritanceListener implFactory = new MainInheritanceListener();
+        ServerFactory listener = InheritanceHelper.NewListener(uri, null, implFactory);
+
+		listener.TransportControl( TransportConsts.START_AND_WAIT_UP, 4000 );
+	}
+
+	///
+	/// <summary>Constructs the MainInheritanceListener.</summary>
+	///
+	public MainInheritanceListener()
+	{
+		// Nothing to do.
+	}
+
+	///
+	/// <summary>Return a new instance of InheritanceServer.</summary>
+	/// @param client
+	///
+	public InheritanceServer NewInheritanceServer( RemoteInheritanceClient client )
+	{
+		return new ImplInheritanceServer( client );
+	}
+}
+
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/MainTypesClient.cs b/tests/src/main/csharp/etch.tests/MainTypesClient.cs
new file mode 100644
index 0000000..916bb64
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/MainTypesClient.cs
@@ -0,0 +1,94 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using org.apache.etch.tests;
+
+namespace etch.bindings.csharp.examples.types
+{
+
+    ///
+    ///<summary> Main implementation for TypesClient. </summary>
+    ///
+    public class MainTypesClient : TypesHelper.TypesClientFactory
+    {
+        ///
+        /// <summary>Main for TypesClient</summary>
+        /// <param name="args"></param>
+        ///
+        public static void Main(String[] args)
+        {
+            string uri = "tcp://localhost:4001";
+
+            MainTypesListener.Main1(null);
+            MainTypesClient implFactory = new MainTypesClient();
+            RemoteTypesServer server = TypesHelper.NewServer(uri, null, implFactory);
+
+            server._TransportControl(TransportConsts.START_AND_WAIT_UP, 4000);
+
+            Hashtable table = new Hashtable();
+            table.Add("1", "Entry1");
+            table.Add("2", "Entry2");
+
+            IDictionary map1 = server.test1(table);
+
+
+            ArrayList list = new ArrayList();
+
+            list.Add("List1");
+            IList list1 = server.test3(list);
+
+
+
+            DateTime? date = server.test4(DateTime.Now);
+
+
+            Hashtable set = new Hashtable();
+            set.Add("1", null);
+            set.Add("2", null);
+
+
+            Hashtable retset = server.test2(set);
+
+            server._TransportControl(TransportConsts.STOP_AND_WAIT_DOWN, 4000);
+
+        }
+
+        ///
+        /// <summary>Constructs the MainTypesClient.</summary>
+        ///
+        public MainTypesClient()
+        {
+            // Nothing to do.
+        }
+
+        ///
+        /// <summary>Return a new instance of TypesClient.</summary>
+        /// @param server
+        ///
+        public TypesClient NewTypesClient(RemoteTypesServer server)
+        {
+            return new ImplTypesClient(server);
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/MainTypesListener.cs b/tests/src/main/csharp/etch.tests/MainTypesListener.cs
new file mode 100644
index 0000000..a664ee4
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/MainTypesListener.cs
@@ -0,0 +1,66 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using org.apache.etch.tests;
+
+namespace etch.bindings.csharp.examples.types
+{
+
+///
+///<summary> Main implementation for TypesListener. </summary>
+///
+public class MainTypesListener : TypesHelper.TypesServerFactory
+{
+	///
+ 	/// <summary>Main for TypesListener.</summary>
+	/// <param name="args"></param>
+	///
+	public static void Main1(String[] args)
+	{
+		string uri = "tcp://localhost:4001";
+		
+
+		MainTypesListener implFactory = new MainTypesListener();
+        ServerFactory listener = TypesHelper.NewListener(uri, null, implFactory);
+
+		listener.TransportControl( TransportConsts.START_AND_WAIT_UP, 4000 );
+	}
+
+	///
+	/// <summary>Constructs the MainTypesListener.</summary>
+	///
+	public MainTypesListener()
+	{
+		// Nothing to do.
+	}
+
+	///
+	/// <summary>Return a new instance of TypesServer.</summary>
+	/// @param client
+	///
+	public TypesServer NewTypesServer( RemoteTypesClient client )
+	{
+		return new ImplTypesServer( client );
+	}
+}
+
+}
\ No newline at end of file
diff --git a/tests/src/main/csharp/etch.tests/MyCuaeHelper.cs b/tests/src/main/csharp/etch.tests/MyCuaeHelper.cs
new file mode 100644
index 0000000..124568f
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/MyCuaeHelper.cs
@@ -0,0 +1,79 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Transport;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using org.apache.etch.tests;
+
+namespace etch.tests
+{
+    abstract public class MyCuaeHelper : CuaeHelper
+    {
+        public static ServerFactory NewListener(string uri,
+            Resources resources, MyCuaeServerFactory implFactory)
+        {
+            Resources res = InitResources(resources);
+            Transport<ServerFactory> listener = TransportFactory.GetListener(uri, res);
+            return new MyServerFactory(listener, implFactory);
+        }
+
+        public new class MyServerFactory : DefaultServerFactory
+        {
+            public MyServerFactory(Transport<ServerFactory> listener, MyCuaeServerFactory implFactory)
+                : base(listener, implFactory)
+            {
+                _listener = listener;
+                _implFactory = implFactory;
+            }
+
+            private readonly Transport<ServerFactory> _listener;
+
+            private readonly MyCuaeServerFactory _implFactory;
+
+            public override void NewServer(TransportMessage m, string uri, Resources resources)
+            {
+                ValueFactory vf = (ValueFactory)resources.Get(TransportConsts.VALUE_FACTORY);
+                MailboxManager x = new PlainMailboxManager(m, uri, resources);
+                DeliveryService d = new DefaultDeliveryService(x, uri, resources);
+                Pool qp = (Pool)resources[QUEUED_POOL];
+                Pool fp = (Pool)resources[FREE_POOL];
+                _implFactory.NewMyCuaeServer(d, qp, fp, (MyValueFactoryCuae)vf);
+                d.TransportControl(TransportConsts.START, null);
+            }
+
+            public override ValueFactory NewValueFactory(string uri)
+            {
+                return new ValueFactoryCuae(uri);
+            }
+
+            public override string ToString()
+            {
+                return "MyCuaeHelper.ServerFactory/" + _listener;
+            }
+        }
+
+        public interface MyCuaeServerFactory
+        {
+            SessionMessage NewMyCuaeServer(DeliveryService svc, Pool qp, Pool fp,
+                MyValueFactoryCuae vf);
+        }
+    }
+}
diff --git a/tests/src/main/csharp/etch.tests/MyCuaeServerStub.cs b/tests/src/main/csharp/etch.tests/MyCuaeServerStub.cs
new file mode 100644
index 0000000..a40e646
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/MyCuaeServerStub.cs
@@ -0,0 +1,312 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+
+namespace etch.tests
+{
+    public class MyCuaeServerStub : StubBase
+    {
+
+        static MyCuaeServerStub()
+        {
+            StubHelperRun helper1 = delegate(DeliveryService _src, object obj, Who _sender, Message _msg)
+                                        {
+                                            MyCuaeServerImpl impl = (MyCuaeServerImpl)obj;
+                                            impl.dispatch(_sender,_msg);
+                                        };
+    //        MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_CuaeServer_doit.SetStubHelper(new StubHelper(helper1, StubHelper.AsyncMode.NONE));
+    //        MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_CuaeServer_doit3.SetStubHelper(new StubHelper(helper1, StubHelper.AsyncMode.NONE));
+
+            MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_CuaeServer_doit.SetStubHelper(helper1);
+                   MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_CuaeServer_doit3.SetStubHelper(helper1);
+        }
+
+
+        public MyCuaeServerStub(DeliveryService svc, Pool queued, Pool free, MyValueFactoryCuae vf)
+            : base(svc, new MyCuaeServerImpl(svc, vf), queued, free)
+        {
+
+        }
+
+        public class MyCuaeServerImpl
+        {
+            /**
+             * @param svc
+             * @param vf 
+             */
+            public MyCuaeServerImpl(DeliveryService svc, MyValueFactoryCuae vf)
+            {
+            
+                this.svc = svc;
+                this.vf = vf;
+            }
+
+       
+
+            private DeliveryService svc;
+
+            private MyValueFactoryCuae vf;
+
+            /**
+             * Handle messages from peer.
+             * @param sender
+             * @param msg
+             * @throws Exception
+             */
+            public void dispatch(Who sender, Message msg)
+            {
+                Console.WriteLine("msg = " + msg);
+                if (msg.IsType(MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_CuaeServer_doit))
+                {
+                    StructValue req = (StructValue)msg.Get(MyValueFactoryCuae._mf_req);
+                    MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_Request.CheckIsAssignableFrom(req.GetXType);
+                    int? code = (int?)req.Get(MyValueFactoryCuae._mf_code);
+
+                   // String m;
+                    StructValue resp;
+                    switch (code.GetValueOrDefault())
+                    {
+                        case 23:
+                            resp = new StructValue(MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_Response, vf);
+                            resp.Add(MyValueFactoryCuae._mf_msg,"foo");
+                            delayDoit2a(7);
+                            break;
+
+                        case 19:
+                            resp =
+                                new StructValue(
+                                    MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_RespWithCode, vf);
+                            resp.Add(MyValueFactoryCuae._mf_msg, "bar");
+                            resp.Add(MyValueFactoryCuae._mf_code, 54);
+                            delayDoit2b(11,"heaven");
+                            break;
+
+                        case 13:
+                            resp = new StructValue(MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_Response, vf);
+                            resp.Add(MyValueFactoryCuae._mf_msg, "baz");
+                            delayDoit2a(99);
+                            break;
+
+                        default:
+                            resp =
+                               new StructValue(
+                                   MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_RespWithCode, vf);
+                            resp.Add(MyValueFactoryCuae._mf_msg, " unknown code " + code);
+                            resp.Add(MyValueFactoryCuae._mf_code, 63);
+                            delayDoit2b(23, "killer bee");
+                            break;
+                    }
+
+                    
+
+                    Message rmsg = msg.Reply();
+                    Console.WriteLine("rmsg = " + rmsg);
+                    Console.WriteLine("resp = " + resp);
+                    rmsg.Add(MyValueFactoryCuae._mf_result, resp);
+                    svc.TransportMessage(sender,rmsg);
+                    return;
+                }
+
+                if (msg.IsType(MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_CuaeServer_doit3))
+                {
+                    StructValue[] reqs = (StructValue[]) msg.Get(MyValueFactoryCuae._mf_req);
+                    StructValue req = reqs[0];
+                    MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_Request.CheckIsAssignableFrom(
+                        req.GetXType);
+                    int? code = (int?) req.Get(MyValueFactoryCuae._mf_code);
+
+                    StructValue resp;
+                    switch (code.GetValueOrDefault())
+                    {
+                        case 23:
+                            resp =
+                                new StructValue(MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_Response, vf);
+                            resp.Add(MyValueFactoryCuae._mf_msg, "foo");
+                            delayDoit2a(7);
+                            break;
+
+                        case 19:
+                            resp = new StructValue(MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_RespWithCode, vf);
+                                resp.Add( MyValueFactoryCuae._mf_msg, "bar" );
+                                resp.Add( MyValueFactoryCuae._mf_code, 54 );
+                                delayDoit2b( 11, "heaven" );
+                                break; 
+
+                        case 13:
+                            resp =
+                                new StructValue(MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_Response, vf);
+                            resp.Add(MyValueFactoryCuae._mf_msg, "baz");
+                            delayDoit2a(99);
+                            break;
+
+                          	default:
+                                resp = new StructValue(MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_RespWithCode, vf);
+                                    resp.Add( MyValueFactoryCuae._mf_msg, "unknown code " + code );
+                                    resp.Add( MyValueFactoryCuae._mf_code, 63 );
+                                    delayDoit2b( 23, "killer bee" );
+                                    break; 
+                    }
+
+                    Message rmsg = msg.Reply();
+                    Console.WriteLine("rmsg = " + rmsg);
+                    Console.WriteLine("resp = " + resp);
+                    rmsg.Add(MyValueFactoryCuae._mf_result, new StructValue[] { resp });
+                    svc.TransportMessage(sender,rmsg);
+                    return;
+
+
+                }
+
+
+                throw new Exception("unknown msg type " + msg);
+            }
+
+            private void delayDoit2a(int code)
+            {
+                try
+                {
+                    TodoManager.AddTodo(new ToDoObj(svc,vf,code));
+
+                }
+                catch (Exception e)
+                {
+                    Console.WriteLine(e);
+                }
+            }
+
+            private void delayDoit2b(int code, string msg)
+            {
+                try
+                {
+                    TodoManager.AddTodo(new ToDoObj1(svc, vf, code,msg));
+
+                }
+                catch (Exception e)
+                {
+                    Console.WriteLine(e);
+                }
+            }
+        }
+        
+    }
+
+    public class ToDoObj : Todo
+    {
+        private DeliveryService svc;
+
+        private MyValueFactoryCuae vf;
+
+        private int code;
+
+        public ToDoObj(DeliveryService svc, MyValueFactoryCuae vf, int code)
+        {
+            this.svc = svc;
+            this.vf = vf;
+            this.code = code;
+        }
+        
+        
+        public void Doit( TodoManager mgr ) 
+		{
+            StructValue req = new StructValue(MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_Request, vf);
+						req.Add( MyValueFactoryCuae._mf_code, code );
+						
+						Message msg = new Message( MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_CuaeClient_doit2, vf );
+						msg.Add( MyValueFactoryCuae._mf_req, req );
+						
+						Mailbox mb = svc.BeginCall( msg );
+						Object value = svc.EndCall( mb, MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_CuaeServer__result_doit2 );
+						
+						if (value is Exception)
+						{
+							Exception e = (Exception) value;
+							throw e;
+						}
+						
+						StructValue resp = (StructValue) value;
+				//		resp.CheckType( MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_Response );
+                        MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_Response.CheckIsAssignableFrom(resp.GetXType);
+                        Console.WriteLine( "**** delayDoit2a: req {0} response {1}\n", code, resp );
+			//			String m = (String) resp.Get( MyValueFactoryCuae._mf_msg );
+						
+					}
+
+					public void Exception( TodoManager mgr, Exception e )
+					{
+						Console.WriteLine(e);
+					}
+        
+    }
+
+    public class ToDoObj1 : Todo
+    {
+        private DeliveryService svc;
+
+        private MyValueFactoryCuae vf;
+
+        private int code;
+
+        private string message;
+
+        public ToDoObj1(DeliveryService svc, MyValueFactoryCuae vf, int code, string msg)
+        {
+            this.svc = svc;
+            this.vf = vf;
+            this.code = code;
+            this.message = msg;
+        }
+
+
+        public void Doit(TodoManager mgr)
+        {
+            StructValue req = new StructValue(MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_ReqWithMessage, vf);
+            req.Add(MyValueFactoryCuae._mf_code, code);
+            req.Add(MyValueFactoryCuae._mf_msg, message);
+
+            Message msg = new Message(MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_CuaeClient_doit2, vf);
+            msg.Add(MyValueFactoryCuae._mf_req, req);
+
+            Mailbox mb = svc.BeginCall(msg);
+            Object value = svc.EndCall(mb, MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_CuaeServer__result_doit2 );
+
+            if (value is Exception)
+            {
+                Exception e = (Exception)value;
+                throw e;
+            }
+
+            StructValue resp = (StructValue)value;
+            //		resp.CheckType( MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_Response );
+            MyValueFactoryCuae._mt_etch_bindings_csharp_examples_cuae_Cuae_Response.CheckIsAssignableFrom(resp.GetXType);
+            Console.WriteLine("**** delayDoit2b: req {0} response {1}\n", code, resp);
+            //			String m = (String) resp.Get( MyValueFactoryCuae._mf_msg );
+
+        }
+
+        public void Exception(TodoManager mgr, Exception e)
+        {
+            Console.WriteLine(e);
+        }
+
+    }
+}
diff --git a/tests/src/main/csharp/etch.tests/MyValueFactoryCuae.cs b/tests/src/main/csharp/etch.tests/MyValueFactoryCuae.cs
new file mode 100644
index 0000000..dd6df91
--- /dev/null
+++ b/tests/src/main/csharp/etch.tests/MyValueFactoryCuae.cs
@@ -0,0 +1,230 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+
+namespace etch.tests
+{
+    public class MyValueFactoryCuae : DefaultValueFactory
+    {
+
+        private readonly static TypeMap types = new TypeMap();
+    
+     
+
+	    private readonly static Class2TypeMap class2type = 
+                new Class2TypeMap();
+	
+	
+	
+	public MyValueFactoryCuae() : base("none:",types,class2type)
+	{
+			
+	}
+	static MyValueFactoryCuae()
+	{
+		DefaultValueFactory.Init( types, class2type );
+
+        _mt_etch_bindings_csharp_examples_cuae_CuaeServer_doit.SetAsyncMode(AsyncMode.QUEUED);
+		_mt_etch_bindings_csharp_examples_cuae_CuaeServer_doit.SetResult( _mt_etch_bindings_csharp_examples_cuae_CuaeClient__result_doit );
+        _mt_etch_bindings_csharp_examples_cuae_CuaeClient_doit2.SetAsyncMode(AsyncMode.FREE);
+		_mt_etch_bindings_csharp_examples_cuae_CuaeClient_doit2.SetResult( _mt_etch_bindings_csharp_examples_cuae_CuaeServer__result_doit2 );
+        _mt_etch_bindings_csharp_examples_cuae_CuaeServer_doit3.SetResult(_mt_etch_bindings_csharp_examples_cuae_CuaeClient__result_doit3);
+
+
+
+	//	class2type.Add( typeof( etch.bindings.csharp.examples.cuae.ConstsCuae.Request ), _mt_etch_bindings_csharp_examples_cuae_Cuae_Request );
+	//	_mt_etch_bindings_csharp_examples_cuae_Cuae_Request.SetClass( typeof( etch.bindings.csharp.examples.cuae.ConstsCuae.Request ) );
+		_mt_etch_bindings_csharp_examples_cuae_Cuae_Request.SetImportExportHelper
+			( 
+				new ImportExportHelper( 
+					
+					delegate( ValueFactory vf, Object value ) 
+					{
+						return (StructValue)value;
+					}, 
+					delegate( StructValue sv ) 
+					{
+                        return sv;
+					} 
+				)
+			);
+
+
+	//	class2type.Add( typeof( etch.bindings.csharp.examples.cuae.ConstsCuae.Response ), _mt_etch_bindings_csharp_examples_cuae_Cuae_Response );
+	// 	_mt_etch_bindings_csharp_examples_cuae_Cuae_Response.SetClass( typeof( etch.bindings.csharp.examples.cuae.ConstsCuae.Response ) );
+		_mt_etch_bindings_csharp_examples_cuae_Cuae_Response.SetImportExportHelper
+			( 
+				new ImportExportHelper(
+                    delegate(ValueFactory vf, Object value)
+                    {
+                        return (StructValue)value;
+                    },
+                    delegate(StructValue sv)
+                    {
+                        return sv;
+                    } 
+				)
+			);
+
+        _mt_etch_bindings_csharp_examples_cuae_Cuae_ReqWithMessage.SetSuperType(_mt_etch_bindings_csharp_examples_cuae_Cuae_Request);
+
+        _mt_etch_bindings_csharp_examples_cuae_Cuae_ReqWithMessage.SetImportExportHelper
+            (
+                new ImportExportHelper(
+                    delegate(ValueFactory vf, Object value)
+                    {
+                        return (StructValue)value;
+                    },
+                    delegate(StructValue sv)
+                    {
+                        return sv;
+                    }
+                )
+            );
+
+        _mt_etch_bindings_csharp_examples_cuae_Cuae_RespWithCode.SetSuperType(_mt_etch_bindings_csharp_examples_cuae_Cuae_Response);
+        _mt_etch_bindings_csharp_examples_cuae_Cuae_RespWithCode.SetImportExportHelper
+    (
+        new ImportExportHelper(
+            delegate(ValueFactory vf, Object value)
+            {
+                return (StructValue)value;
+            },
+            delegate(StructValue sv)
+            {
+                return sv;
+            }
+        )
+    );
+
+		// initialize the extern serializers:
+
+		// done updating types and fields, lock them.
+		types.Lock();
+		
+		class2type.Lock();
+
+
+		_mt_etch_bindings_csharp_examples_cuae_Cuae_Request.PutValidator( _mf_code, Validator_int.Get( 0 ) );
+
+        _mt_etch_bindings_csharp_examples_cuae_Cuae_ReqWithMessage.PutValidator(_mf_code, Validator_int.Get(0));
+        _mt_etch_bindings_csharp_examples_cuae_Cuae_ReqWithMessage.PutValidator(_mf_msg, Validator_string.Get(0));
+
+
+		_mt_etch_bindings_csharp_examples_cuae_Cuae_Response.PutValidator( _mf_msg, Validator_string.Get( 0 ) );
+
+        _mt_etch_bindings_csharp_examples_cuae_Cuae_RespWithCode.PutValidator(_mf_msg, Validator_string.Get(0));
+        _mt_etch_bindings_csharp_examples_cuae_Cuae_RespWithCode.PutValidator(_mf_code, Validator_int.Get(0));
+
+
+
+		// params for doit
+        _mt_etch_bindings_csharp_examples_cuae_CuaeServer_doit.PutValidator(_mf_req, Validator_StructValue.Get(_mt_etch_bindings_csharp_examples_cuae_Cuae_Request, 0));
+		_mt_etch_bindings_csharp_examples_cuae_CuaeServer_doit.PutValidator( _mf__messageId, Validator_long.Get( 0 ) );
+
+
+
+		// params for _result_doit
+        _mt_etch_bindings_csharp_examples_cuae_CuaeClient__result_doit.PutValidator(_mf_result, Validator_StructValue.Get(_mt_etch_bindings_csharp_examples_cuae_Cuae_Response, 0));
+		_mt_etch_bindings_csharp_examples_cuae_CuaeClient__result_doit.PutValidator( _mf__messageId, Validator_long.Get( 0 ) );
+		_mt_etch_bindings_csharp_examples_cuae_CuaeClient__result_doit.PutValidator( _mf_result, Validator_RuntimeException.Get() ); // thrown RuntimeException
+		_mt_etch_bindings_csharp_examples_cuae_CuaeClient__result_doit.PutValidator( _mf__inReplyTo, Validator_long.Get( 0 ) );
+
+
+
+		// params for doit2
+        _mt_etch_bindings_csharp_examples_cuae_CuaeClient_doit2.PutValidator(_mf_req, Validator_StructValue.Get(_mt_etch_bindings_csharp_examples_cuae_Cuae_Request, 0));
+		_mt_etch_bindings_csharp_examples_cuae_CuaeClient_doit2.PutValidator( _mf__messageId, Validator_long.Get( 0 ) );
+
+
+
+		// params for _result_doit2
+        _mt_etch_bindings_csharp_examples_cuae_CuaeServer__result_doit2.PutValidator(_mf_result, Validator_StructValue.Get(_mt_etch_bindings_csharp_examples_cuae_Cuae_Response, 0));
+		_mt_etch_bindings_csharp_examples_cuae_CuaeServer__result_doit2.PutValidator( _mf__messageId, Validator_long.Get( 0 ) );
+		_mt_etch_bindings_csharp_examples_cuae_CuaeServer__result_doit2.PutValidator( _mf_result, Validator_RuntimeException.Get() ); // thrown RuntimeException
+		_mt_etch_bindings_csharp_examples_cuae_CuaeServer__result_doit2.PutValidator( _mf__inReplyTo, Validator_long.Get( 0 ) );
+
+        // params for doit3
+        _mt_etch_bindings_csharp_examples_cuae_CuaeServer_doit3.PutValidator(_mf_req, Validator_StructValue.Get(_mt_etch_bindings_csharp_examples_cuae_Cuae_Request, 1));
+        _mt_etch_bindings_csharp_examples_cuae_CuaeServer_doit3.PutValidator(_mf__messageId, Validator_long.Get(0));
+
+
+
+        // params for _result_doit3
+        _mt_etch_bindings_csharp_examples_cuae_CuaeClient__result_doit3.PutValidator(_mf_result,Validator_StructValue.Get(_mt_etch_bindings_csharp_examples_cuae_Cuae_Response, 1) );
+        _mt_etch_bindings_csharp_examples_cuae_CuaeClient__result_doit3.PutValidator(_mf__messageId, Validator_long.Get(0));
+        _mt_etch_bindings_csharp_examples_cuae_CuaeClient__result_doit3.PutValidator(_mf_result, Validator_RuntimeException.Get()); // thrown RuntimeException
+        _mt_etch_bindings_csharp_examples_cuae_CuaeClient__result_doit3.PutValidator(_mf__inReplyTo, Validator_long.Get(0));
+
+        _mt_etch_bindings_csharp_examples_cuae_CuaeServer__result_doit2.Timeout = 500;
+        _mt_etch_bindings_csharp_examples_cuae_CuaeServer__result_doit2.ResponseField = _mf_result;
+
+
+	
+	} // end of static constructor
+
+	
+	
+	/// Type for etch.bindings.csharp.examples.cuae.Cuae.Request 
+	public static XType _mt_etch_bindings_csharp_examples_cuae_Cuae_Request =  types.Get( "etch.bindings.csharp.examples.cuae.Cuae.Request" );
+
+    /// Type for etch.bindings.csharp.examples.cuae.Cuae.ReqWithMessage 
+    public static XType _mt_etch_bindings_csharp_examples_cuae_Cuae_ReqWithMessage = types.Get("etch.bindings.csharp.examples.cuae.Cuae.ReqWithMessage");
+
+	/// Type for etch.bindings.csharp.examples.cuae.Cuae.Response 
+	public static XType _mt_etch_bindings_csharp_examples_cuae_Cuae_Response =  types.Get( "etch.bindings.csharp.examples.cuae.Cuae.Response" );
+
+    /// Type for etch.bindings.csharp.examples.cuae.Cuae.RespWithCode 
+    public static XType _mt_etch_bindings_csharp_examples_cuae_Cuae_RespWithCode = types.Get("etch.bindings.csharp.examples.cuae.Cuae.RespWithCode");
+
+	/// Type for etch.bindings.csharp.examples.cuae.CuaeServer.doit 
+	public static XType _mt_etch_bindings_csharp_examples_cuae_CuaeServer_doit =  types.Get( "etch.bindings.csharp.examples.cuae.CuaeServer.doit" );
+
+	/// Type for etch.bindings.csharp.examples.cuae.CuaeClient._result_doit 
+	public static XType _mt_etch_bindings_csharp_examples_cuae_CuaeClient__result_doit =  types.Get( "etch.bindings.csharp.examples.cuae.CuaeClient._result_doit" );
+
+	/// Type for etch.bindings.csharp.examples.cuae.CuaeClient.doit2 
+	public static XType _mt_etch_bindings_csharp_examples_cuae_CuaeClient_doit2 =  types.Get( "etch.bindings.csharp.examples.cuae.CuaeClient.doit2" );
+
+	/// Type for etch.bindings.csharp.examples.cuae.CuaeServer._result_doit2 
+	public static XType _mt_etch_bindings_csharp_examples_cuae_CuaeServer__result_doit2 =  types.Get( "etch.bindings.csharp.examples.cuae.CuaeServer._result_doit2" );
+
+    /// Type for etch.bindings.csharp.examples.cuae.CuaeServer.doit3 
+    public static XType _mt_etch_bindings_csharp_examples_cuae_CuaeServer_doit3 = types.Get("etch.bindings.csharp.examples.cuae.CuaeServer.doit3");
+
+    /// Type for etch.bindings.csharp.examples.cuae.CuaeClient._result_doit3 
+    public static XType _mt_etch_bindings_csharp_examples_cuae_CuaeClient__result_doit3 = types.Get("etch.bindings.csharp.examples.cuae.CuaeClient._result_doit3");
+
+	
+	
+
+	
+	
+				public static Field _mf_code = new Field( "code" );
+		
+				public static new Field _mf_msg = new Field( "msg" );
+		
+				public static Field _mf_req = new Field( "req" );
+		
+				public static new Field _mf_result = new Field( "result" );
+    }
+}
diff --git a/tests/src/main/etch/Async.etch b/tests/src/main/etch/Async.etch
new file mode 100644
index 0000000..15a0405
--- /dev/null
+++ b/tests/src/main/etch/Async.etch
@@ -0,0 +1,33 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+
+@Timeout( 500 )
+service Async
+{
+	@Direction( Both )
+	int sync( int count )
+	
+	@Direction( Both )
+	@AsyncReceiver( Queued )
+	int async_queued( int count )
+	
+	@Direction( Both )
+	@AsyncReceiver( Free )
+	int async_free( int count )
+}
diff --git a/tests/src/main/etch/Bar.etch b/tests/src/main/etch/Bar.etch
new file mode 100644
index 0000000..f52222f
--- /dev/null
+++ b/tests/src/main/etch/Bar.etch
@@ -0,0 +1,43 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+
+service Bar
+{
+	mixin Baz
+
+	@Extern( java, "org.apache.etch.bindings.java.util.StrStrHashMap", "",
+		"org.apache.etch.bindings.java.util.StrStrHashMapSerializer", "" )
+	@Extern( csharp, "StrStrHashMap", "Org.Apache.Etch.Bindings.Csharp.Util",
+		"StrStrHashMapSerializer", "" )
+	extern BarTable
+	
+	struct BarData( int code, BarTable barTable, BazData bazData )
+
+	/** Method Bar1 **/
+	@Direction( Both )
+	boolean bar1( BarData barData );
+	
+	/** Method Bar2 **/
+	@Direction( Server )
+	boolean bar2( BarData barData );
+	
+	/** Method Bar3 **/
+	@Direction( Client )
+	boolean bar3( BarData barData );
+}
diff --git a/tests/src/main/etch/Baz.etch b/tests/src/main/etch/Baz.etch
new file mode 100644
index 0000000..f9f08f6
--- /dev/null
+++ b/tests/src/main/etch/Baz.etch
@@ -0,0 +1,42 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+
+service Baz
+{
+	@Extern( java, "org.apache.etch.bindings.java.util.StrStrHashMap", "",
+		"org.apache.etch.bindings.java.util.StrStrHashMapSerializer", "" )
+		@Extern(csharp, "StrStrHashMap", "Org.Apache.Etch.Bindings.Csharp.Util",
+		"StrStrHashMapSerializer", "")
+	extern BazTable
+	
+	struct BazData( int code, BazTable bazTable )
+	
+	/** Method Baz1 **/
+	@Direction( Both )
+	boolean baz1( BazData bazData )
+	
+	/** Method Baz2 **/
+	@Direction( Server )
+	boolean baz2( BazData bazData )
+	
+	/** Method Baz3 **/
+	@Direction( Client )
+	boolean baz3( BazData bazData )
+	
+}
diff --git a/tests/src/main/etch/BigIdl.etch b/tests/src/main/etch/BigIdl.etch
new file mode 100644
index 0000000..ac2ae14
--- /dev/null
+++ b/tests/src/main/etch/BigIdl.etch
@@ -0,0 +1,1021 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+service BigIdl
+{
+	int add0( int x, int y )
+	int add1( int x, int y )
+	int add2( int x, int y )
+	int add3( int x, int y )
+	int add4( int x, int y )
+	int add5( int x, int y )
+	int add6( int x, int y )
+	int add7( int x, int y )
+	int add8( int x, int y )
+	int add9( int x, int y )
+	int add10( int x, int y )
+	int add11( int x, int y )
+	int add12( int x, int y )
+	int add13( int x, int y )
+	int add14( int x, int y )
+	int add15( int x, int y )
+	int add16( int x, int y )
+	int add17( int x, int y )
+	int add18( int x, int y )
+	int add19( int x, int y )
+	int add20( int x, int y )
+	int add21( int x, int y )
+	int add22( int x, int y )
+	int add23( int x, int y )
+	int add24( int x, int y )
+	int add25( int x, int y )
+	int add26( int x, int y )
+	int add27( int x, int y )
+	int add28( int x, int y )
+	int add29( int x, int y )
+	int add30( int x, int y )
+	int add31( int x, int y )
+	int add32( int x, int y )
+	int add33( int x, int y )
+	int add34( int x, int y )
+	int add35( int x, int y )
+	int add36( int x, int y )
+	int add37( int x, int y )
+	int add38( int x, int y )
+	int add39( int x, int y )
+	int add40( int x, int y )
+	int add41( int x, int y )
+	int add42( int x, int y )
+	int add43( int x, int y )
+	int add44( int x, int y )
+	int add45( int x, int y )
+	int add46( int x, int y )
+	int add47( int x, int y )
+	int add48( int x, int y )
+	int add49( int x, int y )
+	int add50( int x, int y )
+	int add51( int x, int y )
+	int add52( int x, int y )
+	int add53( int x, int y )
+	int add54( int x, int y )
+	int add55( int x, int y )
+	int add56( int x, int y )
+	int add57( int x, int y )
+	int add58( int x, int y )
+	int add59( int x, int y )
+	int add60( int x, int y )
+	int add61( int x, int y )
+	int add62( int x, int y )
+	int add63( int x, int y )
+	int add64( int x, int y )
+	int add65( int x, int y )
+	int add66( int x, int y )
+	int add67( int x, int y )
+	int add68( int x, int y )
+	int add69( int x, int y )
+	int add70( int x, int y )
+	int add71( int x, int y )
+	int add72( int x, int y )
+	int add73( int x, int y )
+	int add74( int x, int y )
+	int add75( int x, int y )
+	int add76( int x, int y )
+	int add77( int x, int y )
+	int add78( int x, int y )
+	int add79( int x, int y )
+	int add80( int x, int y )
+	int add81( int x, int y )
+	int add82( int x, int y )
+	int add83( int x, int y )
+	int add84( int x, int y )
+	int add85( int x, int y )
+	int add86( int x, int y )
+	int add87( int x, int y )
+	int add88( int x, int y )
+	int add89( int x, int y )
+	int add90( int x, int y )
+	int add91( int x, int y )
+	int add92( int x, int y )
+	int add93( int x, int y )
+	int add94( int x, int y )
+	int add95( int x, int y )
+	int add96( int x, int y )
+	int add97( int x, int y )
+	int add98( int x, int y )
+	int add99( int x, int y )
+	int add100( int x, int y )
+	int add101( int x, int y )
+	int add102( int x, int y )
+	int add103( int x, int y )
+	int add104( int x, int y )
+	int add105( int x, int y )
+	int add106( int x, int y )
+	int add107( int x, int y )
+	int add108( int x, int y )
+	int add109( int x, int y )
+	int add110( int x, int y )
+	int add111( int x, int y )
+	int add112( int x, int y )
+	int add113( int x, int y )
+	int add114( int x, int y )
+	int add115( int x, int y )
+	int add116( int x, int y )
+	int add117( int x, int y )
+	int add118( int x, int y )
+	int add119( int x, int y )
+	int add120( int x, int y )
+	int add121( int x, int y )
+	int add122( int x, int y )
+	int add123( int x, int y )
+	int add124( int x, int y )
+	int add125( int x, int y )
+	int add126( int x, int y )
+	int add127( int x, int y )
+	int add128( int x, int y )
+	int add129( int x, int y )
+	int add130( int x, int y )
+	int add131( int x, int y )
+	int add132( int x, int y )
+	int add133( int x, int y )
+	int add134( int x, int y )
+	int add135( int x, int y )
+	int add136( int x, int y )
+	int add137( int x, int y )
+	int add138( int x, int y )
+	int add139( int x, int y )
+	int add140( int x, int y )
+	int add141( int x, int y )
+	int add142( int x, int y )
+	int add143( int x, int y )
+	int add144( int x, int y )
+	int add145( int x, int y )
+	int add146( int x, int y )
+	int add147( int x, int y )
+	int add148( int x, int y )
+	int add149( int x, int y )
+	int add150( int x, int y )
+	int add151( int x, int y )
+	int add152( int x, int y )
+	int add153( int x, int y )
+	int add154( int x, int y )
+	int add155( int x, int y )
+	int add156( int x, int y )
+	int add157( int x, int y )
+	int add158( int x, int y )
+	int add159( int x, int y )
+	int add160( int x, int y )
+	int add161( int x, int y )
+	int add162( int x, int y )
+	int add163( int x, int y )
+	int add164( int x, int y )
+	int add165( int x, int y )
+	int add166( int x, int y )
+	int add167( int x, int y )
+	int add168( int x, int y )
+	int add169( int x, int y )
+	int add170( int x, int y )
+	int add171( int x, int y )
+	int add172( int x, int y )
+	int add173( int x, int y )
+	int add174( int x, int y )
+	int add175( int x, int y )
+	int add176( int x, int y )
+	int add177( int x, int y )
+	int add178( int x, int y )
+	int add179( int x, int y )
+	int add180( int x, int y )
+	int add181( int x, int y )
+	int add182( int x, int y )
+	int add183( int x, int y )
+	int add184( int x, int y )
+	int add185( int x, int y )
+	int add186( int x, int y )
+	int add187( int x, int y )
+	int add188( int x, int y )
+	int add189( int x, int y )
+	int add190( int x, int y )
+	int add191( int x, int y )
+	int add192( int x, int y )
+	int add193( int x, int y )
+	int add194( int x, int y )
+	int add195( int x, int y )
+	int add196( int x, int y )
+	int add197( int x, int y )
+	int add198( int x, int y )
+	int add199( int x, int y )
+	int add200( int x, int y )
+	int add201( int x, int y )
+	int add202( int x, int y )
+	int add203( int x, int y )
+	int add204( int x, int y )
+	int add205( int x, int y )
+	int add206( int x, int y )
+	int add207( int x, int y )
+	int add208( int x, int y )
+	int add209( int x, int y )
+	int add210( int x, int y )
+	int add211( int x, int y )
+	int add212( int x, int y )
+	int add213( int x, int y )
+	int add214( int x, int y )
+	int add215( int x, int y )
+	int add216( int x, int y )
+	int add217( int x, int y )
+	int add218( int x, int y )
+	int add219( int x, int y )
+	int add220( int x, int y )
+	int add221( int x, int y )
+	int add222( int x, int y )
+	int add223( int x, int y )
+	int add224( int x, int y )
+	int add225( int x, int y )
+	int add226( int x, int y )
+	int add227( int x, int y )
+	int add228( int x, int y )
+	int add229( int x, int y )
+	int add230( int x, int y )
+	int add231( int x, int y )
+	int add232( int x, int y )
+	int add233( int x, int y )
+	int add234( int x, int y )
+	int add235( int x, int y )
+	int add236( int x, int y )
+	int add237( int x, int y )
+	int add238( int x, int y )
+	int add239( int x, int y )
+	int add240( int x, int y )
+	int add241( int x, int y )
+	int add242( int x, int y )
+	int add243( int x, int y )
+	int add244( int x, int y )
+	int add245( int x, int y )
+	int add246( int x, int y )
+	int add247( int x, int y )
+	int add248( int x, int y )
+	int add249( int x, int y )
+	int add250( int x, int y )
+	int add251( int x, int y )
+	int add252( int x, int y )
+	int add253( int x, int y )
+	int add254( int x, int y )
+	int add255( int x, int y )
+	int add256( int x, int y )
+	int add257( int x, int y )
+	int add258( int x, int y )
+	int add259( int x, int y )
+	int add260( int x, int y )
+	int add261( int x, int y )
+	int add262( int x, int y )
+	int add263( int x, int y )
+	int add264( int x, int y )
+	int add265( int x, int y )
+	int add266( int x, int y )
+	int add267( int x, int y )
+	int add268( int x, int y )
+	int add269( int x, int y )
+	int add270( int x, int y )
+	int add271( int x, int y )
+	int add272( int x, int y )
+	int add273( int x, int y )
+	int add274( int x, int y )
+	int add275( int x, int y )
+	int add276( int x, int y )
+	int add277( int x, int y )
+	int add278( int x, int y )
+	int add279( int x, int y )
+	int add280( int x, int y )
+	int add281( int x, int y )
+	int add282( int x, int y )
+	int add283( int x, int y )
+	int add284( int x, int y )
+	int add285( int x, int y )
+	int add286( int x, int y )
+	int add287( int x, int y )
+	int add288( int x, int y )
+	int add289( int x, int y )
+	int add290( int x, int y )
+	int add291( int x, int y )
+	int add292( int x, int y )
+	int add293( int x, int y )
+	int add294( int x, int y )
+	int add295( int x, int y )
+	int add296( int x, int y )
+	int add297( int x, int y )
+	int add298( int x, int y )
+	int add299( int x, int y )
+	int add300( int x, int y )
+	int add301( int x, int y )
+	int add302( int x, int y )
+	int add303( int x, int y )
+	int add304( int x, int y )
+	int add305( int x, int y )
+	int add306( int x, int y )
+	int add307( int x, int y )
+	int add308( int x, int y )
+	int add309( int x, int y )
+	int add310( int x, int y )
+	int add311( int x, int y )
+	int add312( int x, int y )
+	int add313( int x, int y )
+	int add314( int x, int y )
+	int add315( int x, int y )
+	int add316( int x, int y )
+	int add317( int x, int y )
+	int add318( int x, int y )
+	int add319( int x, int y )
+	int add320( int x, int y )
+	int add321( int x, int y )
+	int add322( int x, int y )
+	int add323( int x, int y )
+	int add324( int x, int y )
+	int add325( int x, int y )
+	int add326( int x, int y )
+	int add327( int x, int y )
+	int add328( int x, int y )
+	int add329( int x, int y )
+	int add330( int x, int y )
+	int add331( int x, int y )
+	int add332( int x, int y )
+	int add333( int x, int y )
+	int add334( int x, int y )
+	int add335( int x, int y )
+	int add336( int x, int y )
+	int add337( int x, int y )
+	int add338( int x, int y )
+	int add339( int x, int y )
+	int add340( int x, int y )
+	int add341( int x, int y )
+	int add342( int x, int y )
+	int add343( int x, int y )
+	int add344( int x, int y )
+	int add345( int x, int y )
+	int add346( int x, int y )
+	int add347( int x, int y )
+	int add348( int x, int y )
+	int add349( int x, int y )
+	int add350( int x, int y )
+	int add351( int x, int y )
+	int add352( int x, int y )
+	int add353( int x, int y )
+	int add354( int x, int y )
+	int add355( int x, int y )
+	int add356( int x, int y )
+	int add357( int x, int y )
+	int add358( int x, int y )
+	int add359( int x, int y )
+	int add360( int x, int y )
+	int add361( int x, int y )
+	int add362( int x, int y )
+	int add363( int x, int y )
+	int add364( int x, int y )
+	int add365( int x, int y )
+	int add366( int x, int y )
+	int add367( int x, int y )
+	int add368( int x, int y )
+	int add369( int x, int y )
+	int add370( int x, int y )
+	int add371( int x, int y )
+	int add372( int x, int y )
+	int add373( int x, int y )
+	int add374( int x, int y )
+	int add375( int x, int y )
+	int add376( int x, int y )
+	int add377( int x, int y )
+	int add378( int x, int y )
+	int add379( int x, int y )
+	int add380( int x, int y )
+	int add381( int x, int y )
+	int add382( int x, int y )
+	int add383( int x, int y )
+	int add384( int x, int y )
+	int add385( int x, int y )
+	int add386( int x, int y )
+	int add387( int x, int y )
+	int add388( int x, int y )
+	int add389( int x, int y )
+	int add390( int x, int y )
+	int add391( int x, int y )
+	int add392( int x, int y )
+	int add393( int x, int y )
+	int add394( int x, int y )
+	int add395( int x, int y )
+	int add396( int x, int y )
+	int add397( int x, int y )
+	int add398( int x, int y )
+	int add399( int x, int y )
+	int add400( int x, int y )
+	int add401( int x, int y )
+	int add402( int x, int y )
+	int add403( int x, int y )
+	int add404( int x, int y )
+	int add405( int x, int y )
+	int add406( int x, int y )
+	int add407( int x, int y )
+	int add408( int x, int y )
+	int add409( int x, int y )
+	int add410( int x, int y )
+	int add411( int x, int y )
+	int add412( int x, int y )
+	int add413( int x, int y )
+	int add414( int x, int y )
+	int add415( int x, int y )
+	int add416( int x, int y )
+	int add417( int x, int y )
+	int add418( int x, int y )
+	int add419( int x, int y )
+	int add420( int x, int y )
+	int add421( int x, int y )
+	int add422( int x, int y )
+	int add423( int x, int y )
+	int add424( int x, int y )
+	int add425( int x, int y )
+	int add426( int x, int y )
+	int add427( int x, int y )
+	int add428( int x, int y )
+	int add429( int x, int y )
+	int add430( int x, int y )
+	int add431( int x, int y )
+	int add432( int x, int y )
+	int add433( int x, int y )
+	int add434( int x, int y )
+	int add435( int x, int y )
+	int add436( int x, int y )
+	int add437( int x, int y )
+	int add438( int x, int y )
+	int add439( int x, int y )
+	int add440( int x, int y )
+	int add441( int x, int y )
+	int add442( int x, int y )
+	int add443( int x, int y )
+	int add444( int x, int y )
+	int add445( int x, int y )
+	int add446( int x, int y )
+	int add447( int x, int y )
+	int add448( int x, int y )
+	int add449( int x, int y )
+	int add450( int x, int y )
+	int add451( int x, int y )
+	int add452( int x, int y )
+	int add453( int x, int y )
+	int add454( int x, int y )
+	int add455( int x, int y )
+	int add456( int x, int y )
+	int add457( int x, int y )
+	int add458( int x, int y )
+	int add459( int x, int y )
+	int add460( int x, int y )
+	int add461( int x, int y )
+	int add462( int x, int y )
+	int add463( int x, int y )
+	int add464( int x, int y )
+	int add465( int x, int y )
+	int add466( int x, int y )
+	int add467( int x, int y )
+	int add468( int x, int y )
+	int add469( int x, int y )
+	int add470( int x, int y )
+	int add471( int x, int y )
+	int add472( int x, int y )
+	int add473( int x, int y )
+	int add474( int x, int y )
+	int add475( int x, int y )
+	int add476( int x, int y )
+	int add477( int x, int y )
+	int add478( int x, int y )
+	int add479( int x, int y )
+	int add480( int x, int y )
+	int add481( int x, int y )
+	int add482( int x, int y )
+	int add483( int x, int y )
+	int add484( int x, int y )
+	int add485( int x, int y )
+	int add486( int x, int y )
+	int add487( int x, int y )
+	int add488( int x, int y )
+	int add489( int x, int y )
+	int add490( int x, int y )
+	int add491( int x, int y )
+	int add492( int x, int y )
+	int add493( int x, int y )
+	int add494( int x, int y )
+	int add495( int x, int y )
+	int add496( int x, int y )
+	int add497( int x, int y )
+	int add498( int x, int y )
+	int add499( int x, int y )
+	int add500( int x, int y )
+	int add501( int x, int y )
+	int add502( int x, int y )
+	int add503( int x, int y )
+	int add504( int x, int y )
+	int add505( int x, int y )
+	int add506( int x, int y )
+	int add507( int x, int y )
+	int add508( int x, int y )
+	int add509( int x, int y )
+	int add510( int x, int y )
+	int add511( int x, int y )
+	int add512( int x, int y )
+	int add513( int x, int y )
+	int add514( int x, int y )
+	int add515( int x, int y )
+	int add516( int x, int y )
+	int add517( int x, int y )
+	int add518( int x, int y )
+	int add519( int x, int y )
+	int add520( int x, int y )
+	int add521( int x, int y )
+	int add522( int x, int y )
+	int add523( int x, int y )
+	int add524( int x, int y )
+	int add525( int x, int y )
+	int add526( int x, int y )
+	int add527( int x, int y )
+	int add528( int x, int y )
+	int add529( int x, int y )
+	int add530( int x, int y )
+	int add531( int x, int y )
+	int add532( int x, int y )
+	int add533( int x, int y )
+	int add534( int x, int y )
+	int add535( int x, int y )
+	int add536( int x, int y )
+	int add537( int x, int y )
+	int add538( int x, int y )
+	int add539( int x, int y )
+	int add540( int x, int y )
+	int add541( int x, int y )
+	int add542( int x, int y )
+	int add543( int x, int y )
+	int add544( int x, int y )
+	int add545( int x, int y )
+	int add546( int x, int y )
+	int add547( int x, int y )
+	int add548( int x, int y )
+	int add549( int x, int y )
+	int add550( int x, int y )
+	int add551( int x, int y )
+	int add552( int x, int y )
+	int add553( int x, int y )
+	int add554( int x, int y )
+	int add555( int x, int y )
+	int add556( int x, int y )
+	int add557( int x, int y )
+	int add558( int x, int y )
+	int add559( int x, int y )
+	int add560( int x, int y )
+	int add561( int x, int y )
+	int add562( int x, int y )
+	int add563( int x, int y )
+	int add564( int x, int y )
+	int add565( int x, int y )
+	int add566( int x, int y )
+	int add567( int x, int y )
+	int add568( int x, int y )
+	int add569( int x, int y )
+	int add570( int x, int y )
+	int add571( int x, int y )
+	int add572( int x, int y )
+	int add573( int x, int y )
+	int add574( int x, int y )
+	int add575( int x, int y )
+	int add576( int x, int y )
+	int add577( int x, int y )
+	int add578( int x, int y )
+	int add579( int x, int y )
+	int add580( int x, int y )
+	int add581( int x, int y )
+	int add582( int x, int y )
+	int add583( int x, int y )
+	int add584( int x, int y )
+	int add585( int x, int y )
+	int add586( int x, int y )
+	int add587( int x, int y )
+	int add588( int x, int y )
+	int add589( int x, int y )
+	int add590( int x, int y )
+	int add591( int x, int y )
+	int add592( int x, int y )
+	int add593( int x, int y )
+	int add594( int x, int y )
+	int add595( int x, int y )
+	int add596( int x, int y )
+	int add597( int x, int y )
+	int add598( int x, int y )
+	int add599( int x, int y )
+	int add600( int x, int y )
+	int add601( int x, int y )
+	int add602( int x, int y )
+	int add603( int x, int y )
+	int add604( int x, int y )
+	int add605( int x, int y )
+	int add606( int x, int y )
+	int add607( int x, int y )
+	int add608( int x, int y )
+	int add609( int x, int y )
+	int add610( int x, int y )
+	int add611( int x, int y )
+	int add612( int x, int y )
+	int add613( int x, int y )
+	int add614( int x, int y )
+	int add615( int x, int y )
+	int add616( int x, int y )
+	int add617( int x, int y )
+	int add618( int x, int y )
+	int add619( int x, int y )
+	int add620( int x, int y )
+	int add621( int x, int y )
+	int add622( int x, int y )
+	int add623( int x, int y )
+	int add624( int x, int y )
+	int add625( int x, int y )
+	int add626( int x, int y )
+	int add627( int x, int y )
+	int add628( int x, int y )
+	int add629( int x, int y )
+	int add630( int x, int y )
+	int add631( int x, int y )
+	int add632( int x, int y )
+	int add633( int x, int y )
+	int add634( int x, int y )
+	int add635( int x, int y )
+	int add636( int x, int y )
+	int add637( int x, int y )
+	int add638( int x, int y )
+	int add639( int x, int y )
+	int add640( int x, int y )
+	int add641( int x, int y )
+	int add642( int x, int y )
+	int add643( int x, int y )
+	int add644( int x, int y )
+	int add645( int x, int y )
+	int add646( int x, int y )
+	int add647( int x, int y )
+	int add648( int x, int y )
+	int add649( int x, int y )
+	int add650( int x, int y )
+	int add651( int x, int y )
+	int add652( int x, int y )
+	int add653( int x, int y )
+	int add654( int x, int y )
+	int add655( int x, int y )
+	int add656( int x, int y )
+	int add657( int x, int y )
+	int add658( int x, int y )
+	int add659( int x, int y )
+	int add660( int x, int y )
+	int add661( int x, int y )
+	int add662( int x, int y )
+	int add663( int x, int y )
+	int add664( int x, int y )
+	int add665( int x, int y )
+	int add666( int x, int y )
+	int add667( int x, int y )
+	int add668( int x, int y )
+	int add669( int x, int y )
+	int add670( int x, int y )
+	int add671( int x, int y )
+	int add672( int x, int y )
+	int add673( int x, int y )
+	int add674( int x, int y )
+	int add675( int x, int y )
+	int add676( int x, int y )
+	int add677( int x, int y )
+	int add678( int x, int y )
+	int add679( int x, int y )
+	int add680( int x, int y )
+	int add681( int x, int y )
+	int add682( int x, int y )
+	int add683( int x, int y )
+	int add684( int x, int y )
+	int add685( int x, int y )
+	int add686( int x, int y )
+	int add687( int x, int y )
+	int add688( int x, int y )
+	int add689( int x, int y )
+	int add690( int x, int y )
+	int add691( int x, int y )
+	int add692( int x, int y )
+	int add693( int x, int y )
+	int add694( int x, int y )
+	int add695( int x, int y )
+	int add696( int x, int y )
+	int add697( int x, int y )
+	int add698( int x, int y )
+	int add699( int x, int y )
+	int add700( int x, int y )
+	int add701( int x, int y )
+	int add702( int x, int y )
+	int add703( int x, int y )
+	int add704( int x, int y )
+	int add705( int x, int y )
+	int add706( int x, int y )
+	int add707( int x, int y )
+	int add708( int x, int y )
+	int add709( int x, int y )
+	int add710( int x, int y )
+	int add711( int x, int y )
+	int add712( int x, int y )
+	int add713( int x, int y )
+	int add714( int x, int y )
+	int add715( int x, int y )
+	int add716( int x, int y )
+	int add717( int x, int y )
+	int add718( int x, int y )
+	int add719( int x, int y )
+	int add720( int x, int y )
+	int add721( int x, int y )
+	int add722( int x, int y )
+	int add723( int x, int y )
+	int add724( int x, int y )
+	int add725( int x, int y )
+	int add726( int x, int y )
+	int add727( int x, int y )
+	int add728( int x, int y )
+	int add729( int x, int y )
+	int add730( int x, int y )
+	int add731( int x, int y )
+	int add732( int x, int y )
+	int add733( int x, int y )
+	int add734( int x, int y )
+	int add735( int x, int y )
+	int add736( int x, int y )
+	int add737( int x, int y )
+	int add738( int x, int y )
+	int add739( int x, int y )
+	int add740( int x, int y )
+	int add741( int x, int y )
+	int add742( int x, int y )
+	int add743( int x, int y )
+	int add744( int x, int y )
+	int add745( int x, int y )
+	int add746( int x, int y )
+	int add747( int x, int y )
+	int add748( int x, int y )
+	int add749( int x, int y )
+	int add750( int x, int y )
+	int add751( int x, int y )
+	int add752( int x, int y )
+	int add753( int x, int y )
+	int add754( int x, int y )
+	int add755( int x, int y )
+	int add756( int x, int y )
+	int add757( int x, int y )
+	int add758( int x, int y )
+	int add759( int x, int y )
+	int add760( int x, int y )
+	int add761( int x, int y )
+	int add762( int x, int y )
+	int add763( int x, int y )
+	int add764( int x, int y )
+	int add765( int x, int y )
+	int add766( int x, int y )
+	int add767( int x, int y )
+	int add768( int x, int y )
+	int add769( int x, int y )
+	int add770( int x, int y )
+	int add771( int x, int y )
+	int add772( int x, int y )
+	int add773( int x, int y )
+	int add774( int x, int y )
+	int add775( int x, int y )
+	int add776( int x, int y )
+	int add777( int x, int y )
+	int add778( int x, int y )
+	int add779( int x, int y )
+	int add780( int x, int y )
+	int add781( int x, int y )
+	int add782( int x, int y )
+	int add783( int x, int y )
+	int add784( int x, int y )
+	int add785( int x, int y )
+	int add786( int x, int y )
+	int add787( int x, int y )
+	int add788( int x, int y )
+	int add789( int x, int y )
+	int add790( int x, int y )
+	int add791( int x, int y )
+	int add792( int x, int y )
+	int add793( int x, int y )
+	int add794( int x, int y )
+	int add795( int x, int y )
+	int add796( int x, int y )
+	int add797( int x, int y )
+	int add798( int x, int y )
+	int add799( int x, int y )
+	int add800( int x, int y )
+	int add801( int x, int y )
+	int add802( int x, int y )
+	int add803( int x, int y )
+	int add804( int x, int y )
+	int add805( int x, int y )
+	int add806( int x, int y )
+	int add807( int x, int y )
+	int add808( int x, int y )
+	int add809( int x, int y )
+	int add810( int x, int y )
+	int add811( int x, int y )
+	int add812( int x, int y )
+	int add813( int x, int y )
+	int add814( int x, int y )
+	int add815( int x, int y )
+	int add816( int x, int y )
+	int add817( int x, int y )
+	int add818( int x, int y )
+	int add819( int x, int y )
+	int add820( int x, int y )
+	int add821( int x, int y )
+	int add822( int x, int y )
+	int add823( int x, int y )
+	int add824( int x, int y )
+	int add825( int x, int y )
+	int add826( int x, int y )
+	int add827( int x, int y )
+	int add828( int x, int y )
+	int add829( int x, int y )
+	int add830( int x, int y )
+	int add831( int x, int y )
+	int add832( int x, int y )
+	int add833( int x, int y )
+	int add834( int x, int y )
+	int add835( int x, int y )
+	int add836( int x, int y )
+	int add837( int x, int y )
+	int add838( int x, int y )
+	int add839( int x, int y )
+	int add840( int x, int y )
+	int add841( int x, int y )
+	int add842( int x, int y )
+	int add843( int x, int y )
+	int add844( int x, int y )
+	int add845( int x, int y )
+	int add846( int x, int y )
+	int add847( int x, int y )
+	int add848( int x, int y )
+	int add849( int x, int y )
+	int add850( int x, int y )
+	int add851( int x, int y )
+	int add852( int x, int y )
+	int add853( int x, int y )
+	int add854( int x, int y )
+	int add855( int x, int y )
+	int add856( int x, int y )
+	int add857( int x, int y )
+	int add858( int x, int y )
+	int add859( int x, int y )
+	int add860( int x, int y )
+	int add861( int x, int y )
+	int add862( int x, int y )
+	int add863( int x, int y )
+	int add864( int x, int y )
+	int add865( int x, int y )
+	int add866( int x, int y )
+	int add867( int x, int y )
+	int add868( int x, int y )
+	int add869( int x, int y )
+	int add870( int x, int y )
+	int add871( int x, int y )
+	int add872( int x, int y )
+	int add873( int x, int y )
+	int add874( int x, int y )
+	int add875( int x, int y )
+	int add876( int x, int y )
+	int add877( int x, int y )
+	int add878( int x, int y )
+	int add879( int x, int y )
+	int add880( int x, int y )
+	int add881( int x, int y )
+	int add882( int x, int y )
+	int add883( int x, int y )
+	int add884( int x, int y )
+	int add885( int x, int y )
+	int add886( int x, int y )
+	int add887( int x, int y )
+	int add888( int x, int y )
+	int add889( int x, int y )
+	int add890( int x, int y )
+	int add891( int x, int y )
+	int add892( int x, int y )
+	int add893( int x, int y )
+	int add894( int x, int y )
+	int add895( int x, int y )
+	int add896( int x, int y )
+	int add897( int x, int y )
+	int add898( int x, int y )
+	int add899( int x, int y )
+	int add900( int x, int y )
+	int add901( int x, int y )
+	int add902( int x, int y )
+	int add903( int x, int y )
+	int add904( int x, int y )
+	int add905( int x, int y )
+	int add906( int x, int y )
+	int add907( int x, int y )
+	int add908( int x, int y )
+	int add909( int x, int y )
+	int add910( int x, int y )
+	int add911( int x, int y )
+	int add912( int x, int y )
+	int add913( int x, int y )
+	int add914( int x, int y )
+	int add915( int x, int y )
+	int add916( int x, int y )
+	int add917( int x, int y )
+	int add918( int x, int y )
+	int add919( int x, int y )
+	int add920( int x, int y )
+	int add921( int x, int y )
+	int add922( int x, int y )
+	int add923( int x, int y )
+	int add924( int x, int y )
+	int add925( int x, int y )
+	int add926( int x, int y )
+	int add927( int x, int y )
+	int add928( int x, int y )
+	int add929( int x, int y )
+	int add930( int x, int y )
+	int add931( int x, int y )
+	int add932( int x, int y )
+	int add933( int x, int y )
+	int add934( int x, int y )
+	int add935( int x, int y )
+	int add936( int x, int y )
+	int add937( int x, int y )
+	int add938( int x, int y )
+	int add939( int x, int y )
+	int add940( int x, int y )
+	int add941( int x, int y )
+	int add942( int x, int y )
+	int add943( int x, int y )
+	int add944( int x, int y )
+	int add945( int x, int y )
+	int add946( int x, int y )
+	int add947( int x, int y )
+	int add948( int x, int y )
+	int add949( int x, int y )
+	int add950( int x, int y )
+	int add951( int x, int y )
+	int add952( int x, int y )
+	int add953( int x, int y )
+	int add954( int x, int y )
+	int add955( int x, int y )
+	int add956( int x, int y )
+	int add957( int x, int y )
+	int add958( int x, int y )
+	int add959( int x, int y )
+	int add960( int x, int y )
+	int add961( int x, int y )
+	int add962( int x, int y )
+	int add963( int x, int y )
+	int add964( int x, int y )
+	int add965( int x, int y )
+	int add966( int x, int y )
+	int add967( int x, int y )
+	int add968( int x, int y )
+	int add969( int x, int y )
+	int add970( int x, int y )
+	int add971( int x, int y )
+	int add972( int x, int y )
+	int add973( int x, int y )
+	int add974( int x, int y )
+	int add975( int x, int y )
+	int add976( int x, int y )
+	int add977( int x, int y )
+	int add978( int x, int y )
+	int add979( int x, int y )
+	int add980( int x, int y )
+	int add981( int x, int y )
+	int add982( int x, int y )
+	int add983( int x, int y )
+	int add984( int x, int y )
+	int add985( int x, int y )
+	int add986( int x, int y )
+	int add987( int x, int y )
+	int add988( int x, int y )
+	int add989( int x, int y )
+	int add990( int x, int y )
+	int add991( int x, int y )
+	int add992( int x, int y )
+	int add993( int x, int y )
+	int add994( int x, int y )
+	int add995( int x, int y )
+	int add996( int x, int y )
+	int add997( int x, int y )
+	int add998( int x, int y )
+	int add999( int x, int y )
+}
diff --git a/tests/src/main/etch/Closing.etch b/tests/src/main/etch/Closing.etch
new file mode 100644
index 0000000..4192242
--- /dev/null
+++ b/tests/src/main/etch/Closing.etch
@@ -0,0 +1,24 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+
+service Closing
+{
+	@Oneway
+	void close()
+}
diff --git a/tests/src/main/etch/Cuae.etch b/tests/src/main/etch/Cuae.etch
new file mode 100644
index 0000000..aa5097a
--- /dev/null
+++ b/tests/src/main/etch/Cuae.etch
@@ -0,0 +1,93 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+
+/** Examples of cuae-like server stub. */
+@Timeout( 497 )
+service Cuae
+{
+	/**
+	 * @param code
+	 */
+	struct Request( int code )
+
+	/**
+	 * @param msg
+	 */
+	struct ReqWithMessage( string msg ) extends Request
+	
+	/**
+	 * @param msg
+	 */
+	struct Response( string msg )
+
+	/**
+	 * @param code
+	 */
+	struct RespWithCode ( int code ) extends Response
+	
+	/**
+	 * @param req
+	 * @return response
+	 */
+	@Direction(Server)
+	@AsyncReceiver( Queued )
+	Response doit1( Request req )
+	
+	/**
+	 * @param req
+	 * @return response
+	 */
+	@Direction(Client)
+	@AsyncReceiver( Free )
+	Response doit2( Request req )
+	
+	/**
+	 * @param req
+	 * @return responses
+	 */
+	@Direction(Both)
+	Response[] doit3( Request[] req )
+	
+	/**
+	 * 
+	 */
+	@Direction(Both)
+	void doit4()
+	
+	/**
+	 * 
+	 */
+	@Direction(Server)
+	@Oneway
+	void test1()
+	
+	/**
+	 * 
+	 */
+	@Direction(Client)
+	@Oneway
+	void test2()
+	
+	/**
+	 * 
+	 */
+	@Direction(Both)
+	@Oneway
+	void test3()
+}
diff --git a/tests/src/main/etch/Foo.etch b/tests/src/main/etch/Foo.etch
new file mode 100644
index 0000000..229c184
--- /dev/null
+++ b/tests/src/main/etch/Foo.etch
@@ -0,0 +1,40 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+
+service Foo
+{
+	mixin Bar
+	
+	@Extern( java, "org.apache.etch.bindings.java.util.StrStrHashMap", "",
+		"org.apache.etch.bindings.java.util.StrStrHashMapSerializer", "" )
+	@Extern(csharp, "StrStrHashMap", "Org.Apache.Etch.Bindings.Csharp.Util",
+		"StrStrHashMapSerializer", "")
+	extern FooTable
+
+	struct FooData( int code, FooTable fooTable, BarData barData, BazData bazData )
+	
+	@Direction( Both )
+	boolean foo1( FooData fooData );
+	
+	@Direction( Server )
+	boolean foo2( FooData fooData );
+	
+	@Direction( Client )
+	boolean foo3( FooData fooData );
+}
diff --git a/tests/src/main/etch/Inheritance.etch b/tests/src/main/etch/Inheritance.etch
new file mode 100644
index 0000000..47c1361
--- /dev/null
+++ b/tests/src/main/etch/Inheritance.etch
@@ -0,0 +1,120 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+
+/** Inheritance example */
+service Inheritance
+{
+	/**
+	 * E1 descr.
+	 * @param a blah about a.
+	 * @param b blah about b.
+	 */
+	exception E1 ( int a, int b )
+	
+	/**
+	 * E2 descr.
+	 * @param c blah about c.
+	 * @param d blah about d.
+	 */
+	exception E2 ( int c, int d ) extends E1
+	
+	/**
+	 * E3 descr.
+	 * @param e blah about e.
+	 * @param f blah about f.
+	 */
+	exception E3 ( int e, int f ) extends E2
+	
+	/**
+	 * S1 descr.
+	 * @param a blah about a.
+	 * @param b blah about b.
+	 */
+	struct S1 ( int a, int b )
+	
+	/**
+	 * S2 descr.
+	 * @param c blah about c.
+	 * @param d blah about d.
+	 */
+	struct S2 ( int c, int d ) extends S1
+	
+	/**
+	 * S3 descr.
+	 * @param e blah about e.
+	 * @param f blah about f.
+	 */
+	struct S3 ( int e, int f ) extends S2
+	
+	/**
+	 * Blah about f1.
+	 * @param v a value.
+	 * @return the same value.
+	 */
+	object f1( object v )
+	
+	/**
+	 * Blah about f2.
+	 * @param v a value.
+	 * @return the same value.
+	 */
+	S1 f2( S1 v )
+	
+	/**
+	 * Blah about f3.
+	 * @param v a value.
+	 * @return the same value.
+	 */
+	S2 f3( S2 v )
+	
+	/**
+	 * Blah about f4.
+	 * @param v a value.
+	 * @return the same value.
+	 */
+	S3 f4( S3 v )
+	
+	/**
+	 * Blah about f5.
+	 * @param v a value.
+	 * @return the same value.
+	 */
+	object[] f5( object[] v )
+	
+	/**
+	 * Blah about f6.
+	 * @param v a value.
+	 * @return the same value.
+	 */
+	S1[] f6( S1[] v )
+	
+	/**
+	 * Blah about f7.
+	 * @param v a value.
+	 * @return the same value.
+	 */
+	S2[] f7( S2[] v )
+	
+	/**
+	 * Blah about f8.
+	 * @param v a value.
+	 * @return the same value.
+	 */
+	S3[] f8( S3[] v )
+}
diff --git a/tests/src/main/etch/Test1.etch b/tests/src/main/etch/Test1.etch
new file mode 100644
index 0000000..a5a6616
--- /dev/null
+++ b/tests/src/main/etch/Test1.etch
@@ -0,0 +1,612 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+
+/** The first big test */
+@Direction(Both)
+@Timeout(4000)
+service Test1
+{
+	/** blah */
+	const boolean BOOL1 = false
+	
+	/** blah */
+	const boolean BOOL2 = true
+	
+	/** blah */
+	const byte BYTE1 = -128
+	
+	/** blah */
+	const byte BYTE2 = -1
+	
+	/** blah */
+	const byte BYTE3 = 0
+	
+	/** blah */
+	const byte BYTE4 = 1
+	
+	/** blah */
+	const byte BYTE5 = 127
+	
+	/** blah */
+	const short SHORT1 = -32768
+	
+	/** blah */
+	const short SHORT2 = -1
+	
+	/** blah */
+	const short SHORT3 = 0
+	
+	/** blah */
+	const short SHORT4 = 1
+	
+	/** blah */
+	const short SHORT5 = 32767
+	
+	/** blah */
+	const int INT1 = -2147483648
+	
+	/** blah */
+	const int INT2 = -1
+	
+	/** blah */
+	const int INT3 = 0
+	
+	/** blah */
+	const int INT4 = 1
+	
+	/** blah */
+	const int INT5 = 2147483647
+	
+	/** blah */
+	const long LONG1 = -9223372036854775808
+	
+	/** blah */
+	const long LONG2 = -1
+	
+	/** blah */
+	const long LONG3 = 0
+	/** blah */
+	const long LONG4 = 1
+	/** blah */
+	const long LONG5 = 9223372036854775807
+	
+	/** blah */
+	const float FLOAT1 = 1.4e-45
+	/** blah */
+	const float FLOAT2 = -1
+	/** blah */
+	const float FLOAT3 = 0
+	/** blah */
+	const float FLOAT4 = 1
+	/** blah */
+	const float FLOAT5 = 3.4028235e38
+	
+	/** blah */
+	const double DOUBLE1 = 4.9e-324
+	/** blah */
+	const double DOUBLE2 = -1
+	/** blah */
+	const double DOUBLE3 = 0
+	/** blah */
+	const double DOUBLE4 = 1
+	/** blah */
+	const double DOUBLE5 = 1.7976931348623157e308
+	
+	/** blah */
+	const string STRING1 = ""
+	/** blah */
+	const string STRING2 = "a"
+	/** blah */
+	const string STRING3 = "abc"
+	/** blah */
+	const string STRING4 = "a\tb\tc\r\n"
+	/** blah */
+	const string STRING5 = "x\u0020x" // space
+	/** blah */
+	const string STRING6 = "x\u00bfx" // inverted question mark
+	/** blah */
+	const string STRING7 = "x\u03a9x" // greek omega
+	/** blah */
+	const string STRING8 = "x\\x" // backslash
+	/** blah */
+	const string STRING9 = "x'x" // apostrophe
+	/** blah */
+	const string STRING10 = "x\"x" // double quote
+	
+	/** blah */
+	enum E1( /** value */ A, /** value */ B, /** value */ C )
+	
+	/** blah */
+	struct S1( /** value */ int x, /** value */ int y, /** value */ int z )
+	
+	/** blah */
+	struct S2( /** value */ S1 a, /** value */ S1 b, /** value */ E1 c )
+	
+	/** struct with object as param */
+	struct S3 ( /** value */ string tipe, /** value */ object x )
+	
+	/** struct with array of object as param */
+	struct S4 ( /** value */ string tipe, /** value */ object[] x )
+	
+	/** blah */
+	@Extern(java, "StrIntHashMap", "org.apache.etch.bindings.java.util.StrIntHashMap",
+		"StrIntHashMapSerializer", "org.apache.etch.bindings.java.util.StrIntHashMapSerializer")
+	@Extern(csharp, "StrIntHashMap", "Org.Apache.Etch.Bindings.Csharp.Util",
+		"StrIntHashMapSerializer", "Org.Apache.Etch.Bindings.Csharp.Util")
+	extern Blob
+	
+	/** blah */
+	exception Excp1( /** value */ string msg, /** value */ int code )
+	
+	/** blah */
+	@Unchecked
+	exception Excp2()
+	
+	/** blah */
+	@Unchecked(true)
+	exception Excp3()
+	
+	/** blah */
+	@Unchecked(false)
+	exception Excp4()
+	
+	/** Exception with object as param */
+	exception Excp5( /** value */ string msg, /** value */ int code, /** value */ object x )
+	
+	/** Exception with array of object as param */
+	exception Excp6( /** value */ string msg, /** value */ int code, /** value */ object[] x )	
+	
+	/** do absolutely nothing */
+	@AsyncReceiver(Free)
+	void nothing()
+	
+	/**
+	 * Increments a value by one.
+	 * @param x a value
+	 * @return a value one larger.
+	 */
+	@AsyncReceiver(Queued)
+	int incr( int x )
+
+	/**
+	 * @param x a value
+	 * @param y a value
+	 * @return a value
+	 */
+	int add(int x, int y )
+	
+	/**
+	 * @param x a value
+	 * @param y a value
+	 * @return a value
+	 */
+	int sub( int x, int y )
+	
+	/**
+	 * @param x a value
+	 * @return a value
+	 */
+	int sum( int[] x )
+	
+	/**
+	 * @param e a value
+	 * @param x a value
+	 * @return a value
+	 */
+	int trans( E1 e, int x )
+	
+	/**
+	 * @param a a value
+	 * @param b a value
+	 * @return a value
+	 */
+	double dist( S1 a, S1 b )
+	
+	/**
+	 * @param n a value
+	 * @param x a value
+	 * @return a value
+	 */
+	int[] fill( int n, int x )
+	
+	/**
+	 * @param n a value
+	 * @param o a value
+	 * @return a value
+	 */
+	object[] fillObject( int n, object o)
+	
+	/**
+	 * @param msg a value
+	 * @param code a value
+	 * @throws Excp1
+	 */
+	void blow( string msg, int code ) throws Excp1
+	
+	/**
+	 * @param e a value
+	 * @return a value
+	 * @throws Excp3
+	 * @throws Excp4
+	 */
+	int beets( E1 e ) throws Excp3, Excp4
+	
+	/**
+	 * @param msg
+	 * @param code
+	 * @param value
+	 * @throws Excp5
+	 */
+	void throwExcp5 ( string msg, int code, object value ) throws Excp5
+	
+	/**
+	 * @param msg
+	 * @param code
+	 * @param value
+	 * @throws Excp6
+	 */
+	void throwExcp6 ( string msg, int code, object[] value ) throws Excp6
+			
+	// try one of every type of parameter and result...
+	
+	/**
+	 * @param a
+	 * @return a
+	 */
+	boolean p_boolean( boolean a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	boolean[] p_boolean_array( boolean[] a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	byte p_byte( byte a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	byte[] p_byte_array( byte[] a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	short p_short( short a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	short[] p_short_array( short[] a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	int p_int( int a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	int[] p_int_array( int[] a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	long p_long( long a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	long[] p_long_array( long[] a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	float p_float( float a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	float[] p_float_array( float[] a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	double p_double( double a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	double[] p_double_array( double[] a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	string p_string( string a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	string[] p_string_array( string[] a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	E1 p_E1( E1 a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	E1[] p_E1_array( E1[] a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	S1 p_S1( S1 a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	S1[] p_S1_array( S1[] a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	S2 p_S2( S2 a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	S2[] p_S2_array( S2[] a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	Blob p_Blob( Blob a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	Blob[] p_Blob_array( Blob[] a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	object p_object( object a )
+		
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	object[] p_object_array( object[] a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	S3 p_object_struct( S3 a )
+	
+	/** 
+	 * @param a
+	 * @return a
+	 */
+	S4 p_object_struct_array( S4 a )
+	
+	/**
+	 * @return a value
+	 */
+	@Authorize( isTrue )
+	int alwaysWorks()
+	
+	/**
+	 * @return a value
+	 */
+	boolean isTrue()
+	
+	/** blah */
+	@Authorize( isFalse )
+	void alwaysFails()
+	
+	/**
+	 * @return a value
+	 */
+	boolean isFalse()
+	
+	// null
+	
+	/** blah */
+	@Authorize( can_m1 )
+	void m1()
+	
+	/**
+	 * @return a value
+	 */
+	boolean can_m1()
+	
+	// literal constants
+	
+	/** blah */
+	@Authorize( can_m2, null )
+	void m2()
+	
+	/**
+	 * @param x a value
+	 * @return a value
+	 */
+	boolean can_m2( boolean x )
+	
+	/** blah */
+	@Authorize( can_m3, false )
+	void m3()
+	
+	/**
+	 * @param x a value
+	 * @return a value
+	 */
+	boolean can_m3( boolean x )
+	
+	/** blah */
+	@Authorize( can_m4, true )
+	void m4()
+	
+	/**
+	 * @param x a value
+	 * @return a value
+	 */
+	boolean can_m4( boolean x )
+	
+	/** blah */
+	@Authorize( can_m5, 23 )
+	void m5()
+	
+	/**
+	 * @param x a value
+	 * @return a value
+	 */
+	boolean can_m5( byte x )
+	
+	/** blah */
+	@Authorize( can_m6, 2323 )
+	void m6()
+	
+	/**
+	 * @param x a value
+	 * @return a value
+	 */
+	boolean can_m6( short x )
+	
+	/** blah */
+	@Authorize( can_m7, 23232323 )
+	void m7()
+	
+	/**
+	 * @param x a value
+	 * @return a value
+	 */
+	boolean can_m7( int x )
+	
+	/** blah */
+	@Authorize( can_m8, 2323232323232323 )
+	void m8()
+	
+	/**
+	 * @param x a value
+	 * @return a value
+	 */
+	boolean can_m8( long x )
+	
+	/** blah */
+	@Authorize( can_m9, 3.1415926535897932384626433832795 )
+	void m9()
+	
+	/**
+	 * @param x a value
+	 * @return a value
+	 */
+	boolean can_m9( float x )
+	
+	/** blah */
+	@Authorize( can_m10, 3.1415926535897932384626433832795 )
+	void m10()
+	
+	/**
+	 * @param x a value
+	 * @return a value
+	 */
+	boolean can_m10( double x )
+	
+	/** blah */
+	@Authorize( can_m11, "abc" )
+	void m11()
+	
+	/**
+	 * @param x a value
+	 * @return a value
+	 */
+	boolean can_m11( string x )
+	
+	/** blah */
+	@Authorize( can_m12, INT1 )
+	void m12()
+	
+	/**
+	 * @param x a value
+	 * @return a value
+	 */
+	boolean can_m12( int x )
+	
+	/**
+	 * @param k a value
+	 */
+	@Authorize( can_m13, k )
+	void m13( int k )
+	
+	/**
+	 * @param x a value
+	 * @return a value
+	 */
+	boolean can_m13( int x )
+	
+	/**
+	 * @param k a value
+	 */
+	@Authorize( can_m14, k.x )
+	void m14( S1 k )
+	
+	/**
+	 * @param x a value
+	 * @return a value
+	 */
+	boolean can_m14( int x )
+	
+	/** blah */
+	@Authorize( can_m15, E1.A )
+	void m15()
+	
+	/**
+	 * @param x a value
+	 * @return a value
+	 */
+	boolean can_m15( E1 x )
+}
diff --git a/tests/src/main/etch/Test2.etch b/tests/src/main/etch/Test2.etch
new file mode 100644
index 0000000..d7aa0ff
--- /dev/null
+++ b/tests/src/main/etch/Test2.etch
@@ -0,0 +1,28 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+
+/**
+ * Test case for problem where there is a missing declaration for
+ * _mf_result if there are only oneway messages in the service.
+ */
+service Test2
+{
+	@Oneway
+	void foo()
+}
diff --git a/tests/src/main/etch/Test3.etch b/tests/src/main/etch/Test3.etch
new file mode 100644
index 0000000..8c6d8a8
--- /dev/null
+++ b/tests/src/main/etch/Test3.etch
@@ -0,0 +1,27 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+
+/** test case for defined types conflicting with standard types. */
+service Test3
+{
+	struct Message()
+	struct Mailbox()
+	struct DeliveryService()
+	Message foo( Message a, Mailbox b, DeliveryService c )
+}
diff --git a/tests/src/main/etch/Test4.etch b/tests/src/main/etch/Test4.etch
new file mode 100644
index 0000000..cc48c47
--- /dev/null
+++ b/tests/src/main/etch/Test4.etch
@@ -0,0 +1,35 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+
+/**
+ * Test blank auth and true and false.
+ */
+service Test4
+{
+	void always_call_method1()
+	
+	@Authorize
+	void always_call_method2()
+	
+	@Authorize( true )
+	void always_call_method3()
+	
+	@Authorize( false )
+	void never_call_method()
+}
diff --git a/tests/src/main/etch/Test5.etch b/tests/src/main/etch/Test5.etch
new file mode 100644
index 0000000..9eb714f
--- /dev/null
+++ b/tests/src/main/etch/Test5.etch
@@ -0,0 +1,31 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+// Test various uses of reserved words.
+
+module org.apache.etch.tests.res1
+
+service res2
+{
+	const boolean res3 = true
+	enum res4 ( res5 )
+	struct res6 ( int res7 )
+	@Extern( java, "res8", "foo", "bar", "baz" )
+	extern res8
+	exception res9 ( int res10 )
+	void res11( int res12 )
+}
diff --git a/tests/src/main/etch/Test6.etch b/tests/src/main/etch/Test6.etch
new file mode 100644
index 0000000..fee00f2
--- /dev/null
+++ b/tests/src/main/etch/Test6.etch
@@ -0,0 +1,30 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+
+service Test6
+{
+	@Direction(Both)
+	void m1()
+	
+	@Direction(Client)
+	void m2()
+	
+	@Direction(Server)
+	void m3()
+}
diff --git a/tests/src/main/etch/TestIncludes.etch b/tests/src/main/etch/TestIncludes.etch
new file mode 100644
index 0000000..5872538
--- /dev/null
+++ b/tests/src/main/etch/TestIncludes.etch
@@ -0,0 +1,78 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+
+service TestIncludes
+{
+	/* inlude some constants */
+	include "const1.etchinc" 
+	/* const1.etchinc also includes const2.etchinc */
+/*	
+	const boolean BOOL1 = false
+	const boolean BOOL2 = true
+	const int INT1 = 1
+	
+	const int INT2 = 2;
+	const int INT3 = 8
+	const string STR = "TEST";
+*/	
+	
+
+	include "enums.etchinc"  
+	
+	/* include some enums and structs */ 
+	/*
+	enum E1( A, B, C )
+	enum E2 (D, E, F);
+	enum E3 (G, H, I)
+	struct S1( int x, int y, int z )
+	struct S2 (string a, int b)
+	*/
+	/* Leave the following inline */
+	struct S5( S1 a, S2 b, E1 c );
+
+	
+	int incr( int x )	
+	
+	/* include a couple of messages */
+
+	@Direction (Client)
+	int testConst1(int x, int y )
+	
+	/* include a message */
+	include "message.etchinc" 
+	/*
+	@Direction (Both)	
+	int testConst2()
+	*/
+	int testConst3()
+
+	/*	Couple more messages to include */
+	/* include file "messages2" */
+	@Direction (Client)
+	int testEnum1();
+
+	int testEnum2();
+	
+	/* Leave the rest inline */	
+	@Direction (Both)
+	int doNothing( )
+
+
+	
+}
\ No newline at end of file
diff --git a/tests/src/main/etch/TestReservedWords.etch b/tests/src/main/etch/TestReservedWords.etch
new file mode 100644
index 0000000..efb6510
--- /dev/null
+++ b/tests/src/main/etch/TestReservedWords.etch
@@ -0,0 +1,31 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+
+@Direction(Both)
+@Timeout(4000)
+service Test
+{
+	enum E1( goto, abstract, interface )
+
+	struct S1( int if, int else, int new )
+
+	extern new
+
+	exception Excp1( string try, int catch )
+}
diff --git a/tests/src/main/etch/Types.etch b/tests/src/main/etch/Types.etch
new file mode 100644
index 0000000..c802bee
--- /dev/null
+++ b/tests/src/main/etch/Types.etch
@@ -0,0 +1,29 @@
+/* $Id$
+ *
+ * Copyright 2007-2008 Cisco Systems Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+module org.apache.etch.tests
+
+service Types
+{
+	Map test1( Map map )
+	
+	Set test2( Set set )
+	
+	List test3( List list )
+	
+	Datetime test4( Datetime datetime )
+}
diff --git a/tests/src/main/etch/const1.etchinc b/tests/src/main/etch/const1.etchinc
new file mode 100644
index 0000000..e996c10
--- /dev/null
+++ b/tests/src/main/etch/const1.etchinc
@@ -0,0 +1,4 @@
+	const boolean BOOL1 = false
+	const boolean BOOL2 = true
+	const int INT1 = 1
+	include "const2.etchinc" 
\ No newline at end of file
diff --git a/tests/src/main/etch/const2.etchinc b/tests/src/main/etch/const2.etchinc
new file mode 100644
index 0000000..49a0c91
--- /dev/null
+++ b/tests/src/main/etch/const2.etchinc
@@ -0,0 +1,3 @@
+	const int INT2 = 2;
+	const int INT3 = 8
+	const string STR = "TEST";
\ No newline at end of file
diff --git a/tests/src/main/etch/enums.etchinc b/tests/src/main/etch/enums.etchinc
new file mode 100644
index 0000000..52e463e
--- /dev/null
+++ b/tests/src/main/etch/enums.etchinc
@@ -0,0 +1,7 @@
+	/* include some enums and structs */ 
+	
+	enum E1( A, B, C )
+	enum E2 (D, E, F);
+	enum E3 (G, H, I)
+	struct S1( int x, int y, int z )
+	struct S2 (string a, int b);	
\ No newline at end of file
diff --git a/tests/src/main/etch/message.etchinc b/tests/src/main/etch/message.etchinc
new file mode 100644
index 0000000..8745e96
--- /dev/null
+++ b/tests/src/main/etch/message.etchinc
@@ -0,0 +1,2 @@
+	@Direction (Both)	
+	int testConst2()
\ No newline at end of file
diff --git a/tests/src/main/java/org/apache/etch/tests/ImplAsyncClient.java b/tests/src/main/java/org/apache/etch/tests/ImplAsyncClient.java
new file mode 100644
index 0000000..27d824d
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/ImplAsyncClient.java
@@ -0,0 +1,60 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+
+/**
+ * Your custom implementation of BaseAsyncClient. Add methods here to provide
+ * implementations of messages from the server.
+ */
+public class ImplAsyncClient extends BaseAsyncClient
+{
+	/**
+	 * Constructs the ImplAsyncClient.
+	 *
+	 * @param server a connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	public ImplAsyncClient( RemoteAsyncServer server )
+	{
+		this.server = server;
+	}
+	
+	private final RemoteAsyncServer server;
+
+	@Override
+	public Integer sync( Integer count )
+	{
+		return count > 0 ? server.sync( count - 1 ) + 1 : 0;
+	}
+
+	@Override
+	public Integer async_queued( Integer count )
+	{
+		return count > 0 ? server.async_queued( count - 1 ) + 1 : 0;
+	}
+
+	@Override
+	public Integer async_free( Integer count )
+	{
+		return count > 0 ? server.async_free( count - 1 ) + 1 : 0;
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/java/org/apache/etch/tests/ImplAsyncServer.java b/tests/src/main/java/org/apache/etch/tests/ImplAsyncServer.java
new file mode 100644
index 0000000..1449388
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/ImplAsyncServer.java
@@ -0,0 +1,69 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+
+/**
+ * Your custom implementation of BaseAsyncServer. Add methods here to provide
+ * implementations of messages from the client.
+ */
+public class ImplAsyncServer extends BaseAsyncServer
+{
+	/**
+	 * Constructs the ImplAsyncServer.
+	 *
+	 * @param client a connection to the client session. Use this to send a
+	 * message to the client.
+	 */
+	public ImplAsyncServer( RemoteAsyncClient client )
+	{
+		this.client = client;
+	}
+	
+	private final RemoteAsyncClient client;
+	
+	@Override
+	public void _sessionNotify( Object event ) throws Exception
+	{
+		if (event instanceof Throwable)
+			((Throwable) event).printStackTrace();
+		else
+			System.out.println( event );
+	}
+
+	@Override
+	public Integer sync( Integer count )
+	{
+		return count > 0 ? client.sync( count - 1 ) + 1 : 0;
+	}
+
+	@Override
+	public Integer async_queued( Integer count )
+	{
+		return count > 0 ? client.async_queued( count - 1 ) + 1 : 0;
+	}
+
+	@Override
+	public Integer async_free( Integer count )
+	{
+		return count > 0 ? client.async_free( count - 1 ) + 1 : 0;
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/java/org/apache/etch/tests/ImplClosingClient.java b/tests/src/main/java/org/apache/etch/tests/ImplClosingClient.java
new file mode 100644
index 0000000..ee22e29
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/ImplClosingClient.java
@@ -0,0 +1,48 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import org.apache.etch.util.Log;
+
+
+/**
+ * Call to message translator for ClosingClient.
+ */
+public class ImplClosingClient extends BaseClosingClient
+{
+	/**
+	 * Constructs the ImplClosingClient.
+	 * @param server 
+ 	 */
+	public ImplClosingClient( RemoteClosingServer server )
+	{
+		this.server = server;
+	}
+	
+	@SuppressWarnings( "unused" )
+	private final RemoteClosingServer server;
+
+	@Override
+	public void _sessionNotify( Object event ) throws Exception
+	{
+		Log.report( "ImplClosingClient._sessionNotify", "event", event );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/ImplClosingServer.java b/tests/src/main/java/org/apache/etch/tests/ImplClosingServer.java
new file mode 100644
index 0000000..756cded
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/ImplClosingServer.java
@@ -0,0 +1,64 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import org.apache.etch.util.Log;
+import org.apache.etch.util.core.io.TcpTransport;
+
+
+/**
+ * Call to message translator for ClosingServer.
+ */
+public class ImplClosingServer extends BaseClosingServer
+{
+	/**
+	 * Constructs the ImplClosingServer.
+	 *
+	 * @param client
+	 */
+	public ImplClosingServer( RemoteClosingClient client )
+	{
+		this.client = client;
+	}
+	
+	private final RemoteClosingClient client;
+
+	@Override
+	public void close()
+	{
+		try
+		{
+			Log.report( "ImplClosingServer.sayingStopToClient" );
+			client._transportControl( TcpTransport.STOP, null );
+			Log.report( "ImplClosingServer.saidStopToClient" );
+		}
+		catch ( Exception e )
+		{
+			throw new RuntimeException( "caught exception", e );
+		}
+	}
+
+	@Override
+	public void _sessionNotify( Object event ) throws Exception
+	{
+		Log.report( "ImplClosingServer._sessionNotify", "event", event );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/ImplCuaeClient.java b/tests/src/main/java/org/apache/etch/tests/ImplCuaeClient.java
new file mode 100644
index 0000000..9ae80b0
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/ImplCuaeClient.java
@@ -0,0 +1,55 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+
+/**
+ * Your custom implementation of BaseCuaeClient. Add methods here to provide
+ * implementations of messages from the server.
+ */
+public class ImplCuaeClient extends BaseCuaeClient
+{
+	/**
+	 * Constructs the ImplCuaeClient.
+	 *
+	 * @param server a connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	public ImplCuaeClient( RemoteCuaeServer server )
+	{
+		this.server = server;
+	}
+	
+	@SuppressWarnings("unused")
+	private final RemoteCuaeServer server;
+
+	@Override
+	public Response doit2( Request req )
+	{
+		switch (req.code)
+		{
+			case 7: return new Response( "apple" );
+			case 11: return new RespWithCode( "banana", 37 );
+			case 99: return new Response( "prune" );
+			default: return new RespWithCode( "me putz "+req.code+" in teh bukkit", 101 );
+		}
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/java/org/apache/etch/tests/ImplCuaeServer.java b/tests/src/main/java/org/apache/etch/tests/ImplCuaeServer.java
new file mode 100644
index 0000000..647ddc3
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/ImplCuaeServer.java
@@ -0,0 +1,46 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+
+/**
+ * Your custom implementation of BaseCuaeServer. Add methods here to provide
+ * implementations of messages from the client.
+ */
+public class ImplCuaeServer extends BaseCuaeServer
+{
+	/**
+	 * Constructs the ImplCuaeServer.
+	 *
+	 * @param client a connection to the client session. Use this to send a
+	 * message to the client.
+	 */
+	public ImplCuaeServer( RemoteCuaeClient client )
+	{
+		this.client = client;
+	}
+	
+	@SuppressWarnings("unused")
+	private final RemoteCuaeClient client;
+
+	// TODO insert methods here to provide implementations of CuaeServer
+	// messages from the client.
+}
\ No newline at end of file
diff --git a/tests/src/main/java/org/apache/etch/tests/ImplFooClient.java b/tests/src/main/java/org/apache/etch/tests/ImplFooClient.java
new file mode 100644
index 0000000..621d219
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/ImplFooClient.java
@@ -0,0 +1,70 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+
+/**
+ * Implementation of methods for FooClient.
+ */
+public class ImplFooClient implements FooClient
+{
+	/**
+	 * Constructs the ImplFooClient.
+	 * @param server
+	 */
+	public ImplFooClient( RemoteFooServer server )
+	{
+		this.server = server;
+	}
+	
+	@SuppressWarnings("unused")
+	protected FooServer server;
+
+	public Boolean foo1( Foo.FooData fooData )
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Boolean foo3( Foo.FooData fooData )
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Boolean bar1( BarData barData )
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Boolean bar3( BarData barData )
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Boolean baz1( BazData bazData )
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public Boolean baz3( BazData bazData )
+	{
+		throw new UnsupportedOperationException();
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/ImplFooServer.java b/tests/src/main/java/org/apache/etch/tests/ImplFooServer.java
new file mode 100644
index 0000000..839b993
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/ImplFooServer.java
@@ -0,0 +1,89 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+
+/**
+ * Implementation of methods for FooServer.
+ */
+public class ImplFooServer extends BaseFooServer
+{
+	/**
+	 * Constructs the ImplFooServer.
+	 *
+	 * @param client the connection to our client.
+	 */
+	public ImplFooServer( RemoteFooClient client )
+	{
+		this.client = client;
+	}
+	
+	@SuppressWarnings("unused")
+	private final RemoteFooClient client;
+
+	@Override
+	public Boolean foo1( Foo.FooData fooData )
+	{
+		System.out.println( "foo1 called with "+fooData );
+		return true;
+	}
+
+	@Override
+	public Boolean foo2( Foo.FooData fooData )
+	{
+		System.out.println( "foo2 called with "+fooData );
+		return false;
+	}
+
+	@Override
+	public Boolean bar1( BarData barData )
+	{
+		System.out.println( "bar1 called with "+barData );
+		return true;
+	}
+
+	@Override
+	public Boolean bar2( BarData barData )
+	{
+		System.out.println( "bar2 called with "+barData );
+		return false;
+	}
+
+	@Override
+	public Boolean baz1( BazData bazData )
+	{
+		System.out.println( "baz1 called with "+bazData );
+		return true;
+	}
+
+	@Override
+	public Boolean baz2( BazData bazData )
+	{
+		System.out.println( "baz2 called with "+bazData );
+		return false;
+	}
+
+	@Override
+	public void _sessionNotify( Object event ) throws Exception
+	{
+		System.out.println( event );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/ImplInheritanceClient.java b/tests/src/main/java/org/apache/etch/tests/ImplInheritanceClient.java
new file mode 100644
index 0000000..1b72ab2
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/ImplInheritanceClient.java
@@ -0,0 +1,46 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+
+/**
+ * Your custom implementation of BaseInheritanceClient. Add methods here to provide
+ * implementations of messages from the server.
+ */
+public class ImplInheritanceClient extends BaseInheritanceClient
+{
+	/**
+	 * Constructs the ImplInheritanceClient.
+	 *
+	 * @param server a connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	public ImplInheritanceClient( RemoteInheritanceServer server )
+	{
+		this.server = server;
+	}
+	
+	@SuppressWarnings("unused")
+	private final RemoteInheritanceServer server;
+
+	// TODO insert methods here to provide implementations of InheritanceClient
+	// messages from the server.
+}
\ No newline at end of file
diff --git a/tests/src/main/java/org/apache/etch/tests/ImplInheritanceServer.java b/tests/src/main/java/org/apache/etch/tests/ImplInheritanceServer.java
new file mode 100644
index 0000000..7a6c8c7
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/ImplInheritanceServer.java
@@ -0,0 +1,91 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+
+/**
+ * Your custom implementation of BaseInheritanceServer. Add methods here to provide
+ * implementations of messages from the client.
+ */
+public class ImplInheritanceServer extends BaseInheritanceServer
+{
+	/**
+	 * Constructs the ImplInheritanceServer.
+	 *
+	 * @param client a connection to the client session. Use this to send a
+	 * message to the client.
+	 */
+	public ImplInheritanceServer( RemoteInheritanceClient client )
+	{
+		this.client = client;
+	}
+	
+	@SuppressWarnings("unused")
+	private final RemoteInheritanceClient client;
+
+	@Override
+	public Object f1( Object v )
+	{
+		return v;
+	}
+
+	@Override
+	public S1 f2( S1 v )
+	{
+		return v;
+	}
+
+	@Override
+	public S2 f3( S2 v )
+	{
+		return v;
+	}
+
+	@Override
+	public S3 f4( S3 v )
+	{
+		return v;
+	}
+
+	@Override
+	public Object[] f5( Object[] v )
+	{
+		return v;
+	}
+
+	@Override
+	public S1[] f6( S1[] v )
+	{
+		return v;
+	}
+
+	@Override
+	public S2[] f7( S2[] v )
+	{
+		return v;
+	}
+
+	@Override
+	public S3[] f8( S3[] v )
+	{
+		return v;
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/java/org/apache/etch/tests/ImplTypesClient.java b/tests/src/main/java/org/apache/etch/tests/ImplTypesClient.java
new file mode 100644
index 0000000..3a4369f
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/ImplTypesClient.java
@@ -0,0 +1,46 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+
+/**
+ * Your custom implementation of BaseTypesClient. Add methods here to provide
+ * implementations of messages from the server.
+ */
+public class ImplTypesClient extends BaseTypesClient
+{
+	/**
+	 * Constructs the ImplTypesClient.
+	 *
+	 * @param server a connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	public ImplTypesClient( RemoteTypesServer server )
+	{
+		this.server = server;
+	}
+	
+	@SuppressWarnings("unused")
+	private final RemoteTypesServer server;
+
+	// TODO insert methods here to provide implementations of TypesClient
+	// messages from the server.
+}
\ No newline at end of file
diff --git a/tests/src/main/java/org/apache/etch/tests/ImplTypesServer.java b/tests/src/main/java/org/apache/etch/tests/ImplTypesServer.java
new file mode 100644
index 0000000..b87304e
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/ImplTypesServer.java
@@ -0,0 +1,77 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * Your custom implementation of BaseTypesServer. Add methods here to provide
+ * implementations of messages from the client.
+ */
+@SuppressWarnings("unchecked")
+public class ImplTypesServer extends BaseTypesServer
+{
+	/**
+	 * Constructs the ImplTypesServer.
+	 *
+	 * @param client a connection to the client session. Use this to send a
+	 * message to the client.
+	 */
+	public ImplTypesServer( RemoteTypesClient client )
+	{
+		this.client = client;
+	}
+	
+	@SuppressWarnings("unused")
+	private final RemoteTypesClient client;
+
+	@Override
+	public Map test1( Map map )
+	{
+		System.out.println( "map = "+map );
+		return map;
+	}
+	
+	@Override
+	public Set test2( Set set )
+	{
+		System.out.println( "set = "+set );
+		return set;
+	}
+	
+	@Override
+	public List test3( List list )
+	{
+		System.out.println( "list = "+list );
+		return list;
+	}
+	
+	@Override
+	public Date test4( Date datetime )
+	{
+		System.out.println( "datetime = "+datetime );
+		return datetime;
+	}
+}
\ No newline at end of file
diff --git a/tests/src/main/java/org/apache/etch/tests/MainAsyncClient.java b/tests/src/main/java/org/apache/etch/tests/MainAsyncClient.java
new file mode 100644
index 0000000..fca35e1
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MainAsyncClient.java
@@ -0,0 +1,61 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+
+/**
+ * Main program for AsyncClient. This program makes a connection to the
+ * listener created by MainAsyncListener.
+ */
+public class MainAsyncClient implements AsyncHelper.AsyncClientFactory
+{
+	/**
+	 * Main program for AsyncClient.
+	 * 
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		String uri = "tcp://localhost:4003";
+		if (args.length > 0)
+			uri = args[0];
+
+		MainAsyncClient implFactory = new MainAsyncClient();
+		
+		RemoteAsyncServer server = AsyncHelper.newServer( uri, null,
+			implFactory );
+
+		server._startAndWaitUp( 4000 );
+
+		// -------------------------------------------------------------
+		// Insert Your Code Here
+		// -------------------------------------------------------------
+
+		server._stopAndWaitDown( 4000 );
+	}
+
+	public AsyncClient newAsyncClient( RemoteAsyncServer server )
+		throws Exception
+	{
+		return new ImplAsyncClient( server );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/MainAsyncListener.java b/tests/src/main/java/org/apache/etch/tests/MainAsyncListener.java
new file mode 100644
index 0000000..fc3e740
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MainAsyncListener.java
@@ -0,0 +1,58 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.core.io.Transport;
+
+
+
+/**
+ * Main program for AsyncServer. This program makes a listener to accept
+ * connections from MainAsyncClient.
+ */
+public class MainAsyncListener implements AsyncHelper.AsyncServerFactory
+{
+	/**
+	 * Main program for AsyncServer.
+	 * 
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		Log.addSink( null );
+		Log.report( "MainAsyncListener" );
+		
+		String uri = "tcp://0.0.0.0:4003";
+
+		ServerFactory listener = AsyncHelper.newListener( uri, null,
+			new MainAsyncListener() );
+
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+	}
+
+	public AsyncServer newAsyncServer( RemoteAsyncClient client )
+	{
+		return new ImplAsyncServer( client );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/MainClosingClient.java b/tests/src/main/java/org/apache/etch/tests/MainClosingClient.java
new file mode 100644
index 0000000..7523773
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MainClosingClient.java
@@ -0,0 +1,74 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import org.apache.etch.util.Log;
+
+
+/**
+ * Main implementation for ClosingClient.
+ */
+public class MainClosingClient implements ClosingHelper.ClosingClientFactory
+{
+	/**
+	 * Main for ClosingClient
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main(String[] args)
+		throws Exception
+	{
+		Log.addSink( null );
+		
+		Log.report( "MainClosingClient.startingListener" );
+		MainClosingListener.main( new String[] { "tcp://localhost:0" } );
+		String uri = MainClosingListener.getLocalUri();
+		Log.report( "MainClosingClient.listenerUp", "uri", uri );
+		
+		RemoteClosingServer server = ClosingHelper.newServer( uri, null, new MainClosingClient() );
+		
+		Log.report( "MainClosingClient.startingServer" );
+		server._startAndWaitUp( 4000 );
+		Log.report( "MainClosingClient.serverUp" );
+		
+		Thread.sleep( 100 );
+		
+		// this sends a message to the server which then closes the connection.
+		
+		Log.report( "MainClosingClient.sayingCloseToServer" );
+		server.close();
+		Log.report( "MainClosingClient.saidCloseToServer" );
+		
+		Thread.sleep( 100 );
+		
+		// waiting for server to close.
+		
+		Log.report( "MainClosingClient.waitingServerDown" );
+		server._waitDown( 4000 );
+		Log.report( "MainClosingClient.serverDown" );
+	}
+
+	public ClosingClient newClosingClient( RemoteClosingServer server )
+		throws Exception
+	{
+		return new ImplClosingClient( server );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/MainClosingListener.java b/tests/src/main/java/org/apache/etch/tests/MainClosingListener.java
new file mode 100644
index 0000000..335a1fe
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MainClosingListener.java
@@ -0,0 +1,85 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import java.net.InetSocketAddress;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.io.TcpListener;
+import org.apache.etch.util.core.io.Transport;
+
+
+
+/**
+ * Main implementation for ClosingListener.
+ */
+public class MainClosingListener implements ClosingHelper.ClosingServerFactory
+{
+	/**
+ 	 * Main for ClosingListener.
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main(String[] args)
+		throws Exception
+	{
+		String uri = "tcp://0.0.0.0:4006";
+		
+		ServerFactory listener = ClosingHelper.newListener( uri, null, new MainClosingListener() );
+
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+		
+		InetSocketAddress localAddr = (InetSocketAddress) listener.transportQuery( TcpListener.LOCAL_ADDRESS );
+		URL u = new URL( "tcp:" );
+		u.setHost( localAddr.getHostName() );
+		u.setPort( localAddr.getPort() );
+		localUri = u.toString();
+	}
+
+	/**
+	 * @return the uri of our listener.
+	 */
+	public static String getLocalUri()
+	{
+		return localUri;
+	}
+	
+	private static String localUri;
+
+	/**
+	 * Constructs the MainClosingListener.
+	 */
+	public MainClosingListener()
+	{
+		// Nothing to do.
+	}
+
+	/**
+	 * Return a new instance of ClosingServer.
+	 * @param client
+	 * @return the constructed server.
+	 */
+	public ClosingServer newClosingServer( RemoteClosingClient client )
+	{
+		return new ImplClosingServer( client );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/MainCuaeClient.java b/tests/src/main/java/org/apache/etch/tests/MainCuaeClient.java
new file mode 100644
index 0000000..9dd7c5b
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MainCuaeClient.java
@@ -0,0 +1,79 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+
+/**
+ * Main program for CuaeClient. This program makes a connection to the
+ * listener created by MainCuaeListener.
+ */
+public class MainCuaeClient implements CuaeHelper.CuaeClientFactory
+{
+	/**
+	 * Main program for CuaeClient.
+	 * 
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		String uri = "tcp://localhost:4006";
+		if (args.length > 0)
+			uri = args[0];
+
+		MainCuaeClient implFactory = new MainCuaeClient();
+		
+		RemoteCuaeServer server = CuaeHelper.newServer( uri, null,
+			implFactory );
+
+		server._startAndWaitUp( 4000 );
+
+		System.out.println( "--- doit1( 23 ) -------------------------------------------" );
+		System.out.printf( "doit1( 23 ) => %s\n",
+			server.doit1( new Cuae.Request( 23 ) ) );
+
+		System.out.println( "--- doit1( 23, \"skiddoo\" ) -------------------------------------------" );
+		System.out.printf( "doit1( 23, \"skiddoo\" ) => %s\n",
+			server.doit1( new Cuae.ReqWithMessage( 23, "skiddoo" ) ) );
+
+		System.out.println( "--- doit1( 19 ) -------------------------------------------" );
+		System.out.printf( "doit1( 19 ) => %s\n",
+			server.doit1( new Cuae.Request( 19 ) ) );
+
+		System.out.println( "--- doit1( 13, \"unlucky friday\" ) -------------------------------------------" );
+		System.out.printf( "doit1( 13, \"unlucky friday\" ) => %s\n",
+			server.doit1( new Cuae.ReqWithMessage( 13, "unlucky friday" ) ) );
+		
+		System.out.println( "--- doit( [23] ) -------------------------------------------" );
+		System.out.printf( "doit3( [23] ) => [%s]\n",
+			server.doit3( new Cuae.Request[] { new Cuae.Request( 23 ) } )[0] );
+
+		Thread.sleep( 60*1000 );
+		
+		server._stopAndWaitDown( 4000 );
+	}
+
+	public CuaeClient newCuaeClient( RemoteCuaeServer server )
+		throws Exception
+	{
+		return new ImplCuaeClient( server );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/MainCuaeListener.java b/tests/src/main/java/org/apache/etch/tests/MainCuaeListener.java
new file mode 100644
index 0000000..5a5a834
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MainCuaeListener.java
@@ -0,0 +1,56 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import org.apache.etch.bindings.java.support.DeliveryService;
+import org.apache.etch.bindings.java.support.Pool;
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.bindings.java.transport.SessionMessage;
+import org.apache.etch.util.core.io.Transport;
+
+
+/**
+ * Main program for CuaeServer. This program makes a listener to accept
+ * connections from MainCuaeClient.
+ */
+public class MainCuaeListener implements MyCuaeHelper.MyCuaeServerFactory
+{
+	/**
+	 * Main program for CuaeServer.
+	 * 
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		String uri = "tcp://0.0.0.0:4006";
+
+		ServerFactory listener = MyCuaeHelper.newListener( uri, null, new MainCuaeListener() );
+
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+	}
+
+	public SessionMessage newMyCuaeServer( DeliveryService d, Pool queued, Pool free,
+		MyValueFactoryCuae vf )
+	{
+		return new MyCuaeServerStub( d, queued, free, vf );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/MainFooClient.java b/tests/src/main/java/org/apache/etch/tests/MainFooClient.java
new file mode 100644
index 0000000..7db5a14
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MainFooClient.java
@@ -0,0 +1,89 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import org.apache.etch.bindings.java.util.StrStrHashMap;
+import org.apache.etch.tests.Bar.BarData;
+import org.apache.etch.tests.Baz.BazData;
+import org.apache.etch.tests.Foo.FooData;
+import org.apache.etch.tests.FooHelper.FooClientFactory;
+
+
+/**
+ * Main implementation for FooClient.
+ */
+public class MainFooClient implements FooClientFactory
+{
+	/**
+	 * Main for FooClient
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main(String[] args)
+		throws Exception
+	{
+		String uri = "tcp://localhost:4001";
+
+		RemoteFooServer server = FooHelper.newServer( uri, null, new MainFooClient() );
+		
+		server._startAndWaitUp( 4000 );
+		
+		StrStrHashMap bazTable = new StrStrHashMap();
+		bazTable.put( "def", "baz" );
+		
+		StrStrHashMap barTable = new StrStrHashMap();
+		barTable.put( "def", "bar" );
+		
+		StrStrHashMap fooTable = new StrStrHashMap();
+		fooTable.put( "def", "foo" );
+		
+		BazData bazData = new BazData( 1, bazTable );
+		BarData barData = new BarData( 2, barTable, bazData );
+		FooData fooData = new FooData( 3, fooTable, barData, bazData );
+
+		boolean ok;
+		
+		ok = server.baz1( bazData );
+		System.out.println( "baz1 => "+ok );
+		
+		ok = server.baz2( bazData );
+		System.out.println( "baz2 => "+ok );
+
+		ok = server.bar1( barData );
+		System.out.println( "bar1 => "+ok );
+		
+		ok = server.bar2( barData );
+		System.out.println( "bar2 => "+ok );
+		
+		ok = server.foo1( fooData );
+		System.out.println( "foo1 => "+ok );
+		
+		ok = server.foo2( fooData );
+		System.out.println( "foo2 => "+ok );
+		
+		server._stopAndWaitDown( 4000 );
+	}
+
+	public FooClient newFooClient( RemoteFooServer server ) throws Exception
+	{
+		return new ImplFooClient( server );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/MainFooListener.java b/tests/src/main/java/org/apache/etch/tests/MainFooListener.java
new file mode 100644
index 0000000..39ddde5
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MainFooListener.java
@@ -0,0 +1,64 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.tests.FooHelper.FooServerFactory;
+import org.apache.etch.util.core.io.Transport;
+
+
+/**
+ * Main implementation for FooListener.
+ */
+public class MainFooListener implements FooServerFactory
+{
+	/**
+ 	 * Main for FooListener.
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main(String[] args)
+		throws Exception
+	{
+		String uri = "tcp://0.0.0.0:4001";
+
+		ServerFactory listener = FooHelper.newListener( uri, null, new MainFooListener() );
+
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+	}
+
+	/**
+	 * Constructs the MainFooListener.
+	 */
+	public MainFooListener()
+	{
+		// Nothing to do.
+	}
+
+	/**
+	 * Return a new instance of FooServer.
+	 * @param client
+	 */
+	public FooServer newFooServer( RemoteFooClient client )
+	{
+		return new ImplFooServer( client );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/MainInheritanceClient.java b/tests/src/main/java/org/apache/etch/tests/MainInheritanceClient.java
new file mode 100644
index 0000000..cbf9127
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MainInheritanceClient.java
@@ -0,0 +1,61 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+
+/**
+ * Main program for InheritanceClient. This program makes a connection to the
+ * listener created by MainInheritanceListener.
+ */
+public class MainInheritanceClient implements InheritanceHelper.InheritanceClientFactory
+{
+	/**
+	 * Main program for InheritanceClient.
+	 * 
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		String uri = "tcp://localhost:4001";
+		if (args.length > 0)
+			uri = args[0];
+
+		MainInheritanceClient implFactory = new MainInheritanceClient();
+		
+		RemoteInheritanceServer server = InheritanceHelper.newServer( uri, null,
+			implFactory );
+
+		server._startAndWaitUp( 4000 );
+
+		// -------------------------------------------------------------
+		// Insert Your Code Here
+		// -------------------------------------------------------------
+
+		server._stopAndWaitDown( 4000 );
+	}
+
+	public InheritanceClient newInheritanceClient( RemoteInheritanceServer server )
+		throws Exception
+	{
+		return new ImplInheritanceClient( server );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/MainInheritanceListener.java b/tests/src/main/java/org/apache/etch/tests/MainInheritanceListener.java
new file mode 100644
index 0000000..5da70a9
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MainInheritanceListener.java
@@ -0,0 +1,69 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import java.net.InetSocketAddress;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.io.TcpListener;
+import org.apache.etch.util.core.io.Transport;
+
+
+
+/**
+ * Main program for InheritanceServer. This program makes a listener to accept
+ * connections from MainInheritanceClient.
+ */
+public class MainInheritanceListener implements InheritanceHelper.InheritanceServerFactory
+{
+	/**
+	 * Main program for InheritanceServer.
+	 * 
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		String uri = args.length > 0 ? args[0] : "tcp://0.0.0.0:4001";
+		
+		ServerFactory listener = InheritanceHelper.newListener( uri, null,
+			new MainInheritanceListener() );
+
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+		
+		InetSocketAddress localAddr = (InetSocketAddress) listener.transportQuery( TcpListener.LOCAL_ADDRESS );
+		URL u = new URL( "tcp:" );
+		u.setHost( localAddr.getHostName() );
+		u.setPort( localAddr.getPort() );
+		localUri = u.toString();
+	}
+	
+	/**
+	 * The local uri of the listener.
+	 */
+	public static String localUri;
+
+	public InheritanceServer newInheritanceServer( RemoteInheritanceClient client )
+	{
+		return new ImplInheritanceServer( client );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/MainTypesClient.java b/tests/src/main/java/org/apache/etch/tests/MainTypesClient.java
new file mode 100644
index 0000000..2d1fb5d
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MainTypesClient.java
@@ -0,0 +1,134 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.apache.etch.util.Assertion;
+
+
+
+/**
+ * Main program for TypesClient. This program makes a connection to the
+ * listener created by MainTypesListener.
+ */
+@SuppressWarnings("unchecked")
+public class MainTypesClient implements TypesHelper.TypesClientFactory
+{
+	/**
+	 * Main program for TypesClient.
+	 * 
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		String uri = "tcp://localhost:4001";
+		if (args.length > 0)
+			uri = args[0];
+
+		MainTypesClient implFactory = new MainTypesClient();
+		
+		RemoteTypesServer server = TypesHelper.newServer( uri, null,
+			implFactory );
+
+		server._startAndWaitUp( 4000 );
+
+		Map map1 = new HashMap();
+		map1.put( "a", 12345678 );
+		map1.put( "b", true );
+		map1.put( "c", 15.5 );
+		map1.put( "d", "xyz" );
+		System.out.println( "map1 = "+map1 );
+		Map map2 = server.test1( map1 );
+		System.out.println( "map2 = "+map2 );
+		Assertion.check( map1.equals( map2 ), "map1.equals( map2 )" );
+		map1 = null;
+		map2 = null;
+		
+		Map foo = new HashMap();
+		foo.put( "abc", 123 );
+		System.out.println( "foo1 = "+foo );
+		System.out.println( "foo2 = "+server.test1( foo ) );
+		foo = null;
+		
+		Map bar = new HashMap();
+		bar.put( 123, "abc" );
+		System.out.println( "bar1 = "+bar );
+		System.out.println( "bar2 = "+server.test1( bar ) );
+		bar = null;
+		
+		Map baz = new TreeMap();
+		baz.put( 789, "ghi" );
+		baz.put( 123, "abc" );
+		baz.put( 456, "def" );
+		System.out.println( "baz1 = "+baz );
+		System.out.println( "baz2 = "+server.test1( baz ) );
+		baz = null;
+		
+		Set set1 = new HashSet();
+		set1.add( 12345678 );
+		set1.add( true );
+		set1.add( 15.5 );
+		set1.add( "xyz" );
+		Set set2 = server.test2( set1 );
+		System.out.println( "set1 = "+set1 );
+		System.out.println( "set2 = "+set2 );
+		Assertion.check( set1.equals( set2 ), "set1.equals( set2 )" );
+		set1 = null;
+		set2 = null;
+		
+		List list1 = new ArrayList();
+		list1.add( 12345678 );
+		list1.add( true );
+		list1.add( 15.5 );
+		list1.add( "xyz" );
+		List list2 = server.test3( list1 );
+		System.out.println( "list1 = "+list1 );
+		System.out.println( "list2 = "+list2 );
+		Assertion.check( list1.equals( list2 ), "list1.equals( list2 )" );
+		list1 = null;
+		list2 = null;
+		
+		Date datetime1 = new Date();
+		Date datetime2 = server.test4( datetime1 );
+		System.out.println( "datetime1 = "+datetime1 );
+		System.out.println( "datetime2 = "+datetime2 );
+		Assertion.check( datetime1.equals( datetime2 ), "datetime1.equals( datetime2 )" );
+		datetime1 = null;
+		datetime2 = null;
+		
+		server._stopAndWaitDown( 4000 );
+	}
+
+	public TypesClient newTypesClient( RemoteTypesServer server )
+		throws Exception
+	{
+		return new ImplTypesClient( server );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/MainTypesListener.java b/tests/src/main/java/org/apache/etch/tests/MainTypesListener.java
new file mode 100644
index 0000000..d0c38c5
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MainTypesListener.java
@@ -0,0 +1,54 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.util.core.io.Transport;
+
+
+
+/**
+ * Main program for TypesServer. This program makes a listener to accept
+ * connections from MainTypesClient.
+ */
+public class MainTypesListener implements TypesHelper.TypesServerFactory
+{
+	/**
+	 * Main program for TypesServer.
+	 * 
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		String uri = "tcp://0.0.0.0:4001";
+		
+		ServerFactory listener = TypesHelper.newListener( uri, null,
+			new MainTypesListener() );
+
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+	}
+
+	public TypesServer newTypesServer( RemoteTypesClient client )
+	{
+		return new ImplTypesServer( client );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/MakeBigIdl.java b/tests/src/main/java/org/apache/etch/tests/MakeBigIdl.java
new file mode 100644
index 0000000..1845afd
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MakeBigIdl.java
@@ -0,0 +1,47 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * Program to construct a large idl file for testing limits.
+ */
+public class MakeBigIdl
+{
+	/**
+	 * @param args
+	 */
+	public static void main( String[] args ) throws IOException
+	{
+		int n = 1000;
+		PrintWriter pw = new PrintWriter( new FileWriter( "src/etch/examples/bigidl/BigIdl.etch" ) );
+		pw.println( "module etch.examples.bigidl" );
+		pw.println( "service BigIdl" );
+		pw.println( "{" );
+		for (int i = 0; i < n; i++)
+			pw.printf( "\tint add%d( int x, int y )\n", i );
+		pw.println( "}" );
+		pw.close();
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/MyCuaeHelper.java b/tests/src/main/java/org/apache/etch/tests/MyCuaeHelper.java
new file mode 100644
index 0000000..0a0bff4
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MyCuaeHelper.java
@@ -0,0 +1,105 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.DefaultServerFactory;
+import org.apache.etch.bindings.java.support.DeliveryService;
+import org.apache.etch.bindings.java.support.Pool;
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.bindings.java.support.TransportFactory;
+import org.apache.etch.bindings.java.transport.DefaultDeliveryService;
+import org.apache.etch.bindings.java.transport.MailboxManager;
+import org.apache.etch.bindings.java.transport.PlainMailboxManager;
+import org.apache.etch.bindings.java.transport.SessionMessage;
+import org.apache.etch.bindings.java.transport.TransportMessage;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.core.io.Transport;
+
+
+
+/**
+ * Transport helper for Cuae. All methods are static.
+ */
+abstract public class MyCuaeHelper extends CuaeHelper
+{
+	/**
+	 * Constructs a new server session listener per specifications in uri and
+	 * resources. This listener will accept requests from clients for new server
+	 * sessions.
+	 *
+	 * @param uri contains specifications for the server session listener and
+	 * for the server session transport stack.
+	 *
+	 * @param resources additional resources to aid in constructing new server
+	 * sessions.
+	 *
+	 * @param implFactory factory used to construct a new instance implementing
+	 * CuaeServer. The new instance will receive and process messages from
+	 * the client session.
+	 *
+	 * @return a server session listener.
+	 *
+	 * @throws Exception
+	 */
+	public static ServerFactory newListener( final String uri, Resources resources,
+		final MyCuaeServerFactory implFactory ) throws Exception
+	{
+		final Resources res = initResources( resources );
+
+		Transport<ServerFactory> listener =  TransportFactory.getListener( uri, res );
+		
+		return new DefaultServerFactory( listener, implFactory )
+		{
+			public void newServer( TransportMessage t, String uri, Resources r ) throws Exception
+			{
+				ValueFactory vf = (ValueFactory) r.get( Transport.VALUE_FACTORY );
+				MailboxManager x = new PlainMailboxManager( t, uri, r );
+				DeliveryService d = new DefaultDeliveryService( x, uri, r );
+				Pool qp = (Pool) r.get( QUEUED_POOL );
+				Pool fp = (Pool) r.get( FREE_POOL );
+				implFactory.newMyCuaeServer( d, qp, fp, (MyValueFactoryCuae) vf );
+				d.transportControl( START, null );
+			}
+
+			public ValueFactory newValueFactory( String uri )
+			{
+				return new MyValueFactoryCuae( uri );
+			}
+		};
+	}
+
+	/**
+	 * Factory for a Listener to use to create new instances of MyCuaeServer.
+	 */
+	public interface MyCuaeServerFactory
+	{
+		/**
+		 * @param svc
+		 * @param qp
+		 * @param fp
+		 * @param vf
+		 * @return a StubIntf that accepts and processes server messages.
+		 */
+		public SessionMessage newMyCuaeServer( DeliveryService svc, Pool qp,
+			Pool fp, MyValueFactoryCuae vf );
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/MyCuaeServerStub.java b/tests/src/main/java/org/apache/etch/tests/MyCuaeServerStub.java
new file mode 100644
index 0000000..66f99b6
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MyCuaeServerStub.java
@@ -0,0 +1,305 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.support.DeliveryService;
+import org.apache.etch.bindings.java.support.Mailbox;
+import org.apache.etch.bindings.java.support.ObjSession;
+import org.apache.etch.bindings.java.support.Pool;
+import org.apache.etch.bindings.java.support.StubBase;
+import org.apache.etch.bindings.java.support.StubHelper;
+import org.apache.etch.util.Todo;
+import org.apache.etch.util.TodoManager;
+import org.apache.etch.util.core.Who;
+
+
+/**
+ * Hand-built CuaeServerStub which dispatches to our raw impl.
+ */
+public class MyCuaeServerStub extends StubBase<Object>
+{
+	static
+	{
+		StubHelper<MyCuaeServerImpl> syncHelper = new StubHelper<MyCuaeServerImpl>()
+		{
+			@Override
+			public void run( DeliveryService svc, MyCuaeServerImpl obj, Who sender, Message msg ) throws Exception
+			{
+				obj.dispatch( sender, msg );
+			}
+		};
+		
+		MyValueFactoryCuae._mt_etch_examples_cuae_CuaeServer_doit1
+			.setStubHelper( syncHelper );
+		
+		MyValueFactoryCuae._mt_etch_examples_cuae_CuaeServer_test1
+			.setStubHelper( syncHelper );
+		
+		MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_doit3
+			.setStubHelper( syncHelper );
+		
+		MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_doit4
+			.setStubHelper( syncHelper );
+		
+		MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_test3
+			.setStubHelper( syncHelper );
+	}
+	
+	/**
+	 * Constructs MyCuaeServerStub.
+	 * @param svc
+	 * @param queued
+	 * @param free
+	 * @param vf 
+	 */
+	public MyCuaeServerStub( DeliveryService svc, Pool queued, Pool free,
+		MyValueFactoryCuae vf )
+	{
+		super( svc, new MyCuaeServerImpl( svc, vf ), queued, free );
+	}
+
+	/**
+	 * Hand-build CuaeServerImpl which is sent messages from CuaeServerStub.
+	 */
+	public static class MyCuaeServerImpl implements ObjSession
+	{
+		/**
+		 * @param svc
+		 * @param vf 
+		 */
+		public MyCuaeServerImpl( DeliveryService svc, MyValueFactoryCuae vf )
+		{
+			this.svc = svc;
+			this.vf = vf;
+		}
+		
+		/** */
+		final DeliveryService svc;
+		
+		/** */
+		final MyValueFactoryCuae vf;
+		
+		/**
+		 * Handle messages from peer.
+		 * @param sender
+		 * @param msg
+		 * @throws Exception
+		 */
+		public void dispatch( Who sender, Message msg ) throws Exception
+		{
+			System.out.println( "msg = "+msg );
+			if (msg.isType( MyValueFactoryCuae._mt_etch_examples_cuae_CuaeServer_doit1 ))
+			{
+				StructValue req = (StructValue) msg.get( MyValueFactoryCuae._mf_req );
+				MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_Request.checkIsAssignableFrom( req.type() );
+				int code = (Integer) req.get( MyValueFactoryCuae._mf_code );
+				
+				StructValue resp;
+				switch (code)
+				{
+					case 23:
+						resp = new StructValue( MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_Response, vf );
+						resp.put( MyValueFactoryCuae._mf_msg, "foo" );
+						delayDoit2a( 7 );
+						break;
+					
+					case 19:
+						resp = new StructValue( MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_RespWithCode, vf );
+						resp.put( MyValueFactoryCuae._mf_msg, "bar" );
+						resp.put( MyValueFactoryCuae._mf_code, 54 );
+						delayDoit2b( 11, "heaven" );
+						break;
+					
+					case 13:
+						resp = new StructValue( MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_Response, vf );
+						resp.put( MyValueFactoryCuae._mf_msg, "baz" );
+						delayDoit2a( 99 );
+						break;
+					
+					default:
+						resp = new StructValue( MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_RespWithCode, vf );
+						resp.put( MyValueFactoryCuae._mf_msg, "unknown code " + code );
+						resp.put( MyValueFactoryCuae._mf_code, 63 );
+						delayDoit2b( 23, "killer bee" );
+						break;
+				}
+				
+				
+				Message rmsg = msg.reply();
+				System.out.println( "rmsg = "+rmsg );
+				System.out.println( "resp = "+resp );
+				rmsg.put( MyValueFactoryCuae._mf_result, resp );
+				svc.transportMessage( sender, rmsg );
+				return;
+			}
+			
+			if (msg.isType( MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_doit3 ))
+			{
+				StructValue[] reqs = (StructValue[]) msg.get( MyValueFactoryCuae._mf_req );
+				StructValue req = reqs[0];
+				MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_Request.checkIsAssignableFrom( req.type() );
+				int code = (Integer) req.get( MyValueFactoryCuae._mf_code );
+				
+				StructValue resp;
+				switch (code)
+				{
+					case 23:
+						resp = new StructValue( MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_Response, vf );
+						resp.put( MyValueFactoryCuae._mf_msg, "foo" );
+						delayDoit2a( 7 );
+						break;
+					
+					case 19:
+						resp = new StructValue( MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_RespWithCode, vf );
+						resp.put( MyValueFactoryCuae._mf_msg, "bar" );
+						resp.put( MyValueFactoryCuae._mf_code, 54 );
+						delayDoit2b( 11, "heaven" );
+						break;
+					
+					case 13:
+						resp = new StructValue( MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_Response, vf );
+						resp.put( MyValueFactoryCuae._mf_msg, "baz" );
+						delayDoit2a( 99 );
+						break;
+					
+					default:
+						resp = new StructValue( MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_RespWithCode, vf );
+						resp.put( MyValueFactoryCuae._mf_msg, "unknown code " + code );
+						resp.put( MyValueFactoryCuae._mf_code, 63 );
+						delayDoit2b( 23, "killer bee" );
+						break;
+				}
+				
+				
+				Message rmsg = msg.reply();
+				System.out.println( "rmsg = "+rmsg );
+				System.out.println( "resp = "+resp );
+				rmsg.put( MyValueFactoryCuae._mf_result, new StructValue[] { resp } );
+				svc.transportMessage( sender, rmsg );
+				return;
+			}
+			
+			throw new IllegalArgumentException( "unknown msg type "+msg );
+		}
+
+		private void delayDoit2a( final int code )
+		{
+			try
+			{
+				TodoManager.addTodo( new Todo()
+				{
+					public void doit( TodoManager mgr ) throws Exception
+					{
+						StructValue req = new StructValue( MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_Request, vf );
+						req.put( MyValueFactoryCuae._mf_code, code );
+						
+						Message msg = new Message( MyValueFactoryCuae._mt_etch_examples_cuae_CuaeClient_doit2, vf );
+						msg.put( MyValueFactoryCuae._mf_req, req );
+						
+						Mailbox mb = svc.begincall( msg );
+						Object value = svc.endcall( mb, MyValueFactoryCuae._mt_etch_examples_cuae_CuaeServer__result_doit2 );
+						
+						if (value instanceof Exception)
+						{
+							Exception e = (Exception) value;
+							e.fillInStackTrace();
+							throw e;
+						}
+						
+						StructValue resp = (StructValue) value;
+						MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_Response.checkIsAssignableFrom( resp.type() );
+						System.out.printf( "**** delayDoit2a: req %d response %s\n", code, resp );
+					}
+
+					public void exception( TodoManager mgr, Exception e )
+					{
+						e.printStackTrace();
+					}
+				} );
+			}
+			catch ( Exception e )
+			{
+				e.printStackTrace();
+			}
+		}
+
+		private void delayDoit2b( final int code, final String message )
+		{
+			try
+			{
+				TodoManager.addTodo( new Todo()
+				{
+					public void doit( TodoManager mgr ) throws Exception
+					{
+						StructValue req = new StructValue( MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_ReqWithMessage, vf );
+						req.put( MyValueFactoryCuae._mf_code, code );
+						req.put( MyValueFactoryCuae._mf_msg, message );
+						
+						Message msg = new Message( MyValueFactoryCuae._mt_etch_examples_cuae_CuaeClient_doit2, vf );
+						msg.put( MyValueFactoryCuae._mf_req, req );
+						
+						Mailbox mb = svc.begincall( msg );
+						Object value = svc.endcall( mb, MyValueFactoryCuae._mt_etch_examples_cuae_CuaeServer__result_doit2 );
+						
+						if (value instanceof Exception)
+						{
+							Exception e = (Exception) value;
+							e.fillInStackTrace();
+							throw e;
+						}
+						
+						StructValue resp = (StructValue) value;
+						MyValueFactoryCuae._mt_etch_examples_cuae_Cuae_Response.checkIsAssignableFrom( resp.type() );
+						System.out.printf( "**** delayDoit2b: req %d response %s\n", code, resp );
+					}
+
+					public void exception( TodoManager mgr, Exception e )
+					{
+						e.printStackTrace();
+					}
+				} );
+			}
+			catch ( Exception e )
+			{
+				e.printStackTrace();
+			}
+		}
+
+		public Object _sessionQuery( Object query ) throws Exception
+		{
+			throw new UnsupportedOperationException( "unknown query "+query );
+		}
+
+		public void _sessionControl( Object control, Object value )
+			throws Exception
+		{
+			throw new UnsupportedOperationException( "unknown control "+control );
+		}
+
+		public void _sessionNotify( Object event ) throws Exception
+		{
+			if (event instanceof Throwable)
+				((Throwable) event).printStackTrace();
+		}
+	}
+}
diff --git a/tests/src/main/java/org/apache/etch/tests/MyValueFactoryCuae.java b/tests/src/main/java/org/apache/etch/tests/MyValueFactoryCuae.java
new file mode 100644
index 0000000..88956e9
--- /dev/null
+++ b/tests/src/main/java/org/apache/etch/tests/MyValueFactoryCuae.java
@@ -0,0 +1,262 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.ImportExportHelper;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.TypeMap;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.Class2TypeMap;
+import org.apache.etch.bindings.java.support.DefaultValueFactory;
+
+/**
+ * ValueFactory for Cuae.
+ */
+@SuppressWarnings("unused")
+public final class MyValueFactoryCuae extends DefaultValueFactory
+{
+	/**
+	 * Constructs ValueFactoryTest1.
+	 */
+	public MyValueFactoryCuae( String uri )
+	{
+		super( uri, types, class2type );
+	}
+	
+	private final static TypeMap types = new TypeMap();
+	
+	private final static Class2TypeMap class2type = new Class2TypeMap();
+
+	static
+	{
+		DefaultValueFactory.init( types, class2type );
+		initTypes();
+		initResults();
+		initFields();
+		initParams();
+	}
+
+	/** Type for etch.examples.cuae.Cuae.Request */
+	public static Type _mt_etch_examples_cuae_Cuae_Request;
+
+	/** Type for etch.examples.cuae.Cuae.ReqWithMessage */
+	public static Type _mt_etch_examples_cuae_Cuae_ReqWithMessage;
+
+	/** Type for etch.examples.cuae.Cuae.Response */
+	public static Type _mt_etch_examples_cuae_Cuae_Response;
+
+	/** Type for etch.examples.cuae.Cuae.RespWithCode */
+	public static Type _mt_etch_examples_cuae_Cuae_RespWithCode;
+
+	/** Type for etch.examples.cuae.CuaeServer.doit1 */
+	public static Type _mt_etch_examples_cuae_CuaeServer_doit1;
+
+	/** Type for etch.examples.cuae.CuaeClient._result_doit1 */
+	public static Type _mt_etch_examples_cuae_CuaeClient__result_doit1;
+
+	/** Type for etch.examples.cuae.CuaeClient.doit2 */
+	public static Type _mt_etch_examples_cuae_CuaeClient_doit2;
+
+	/** Type for etch.examples.cuae.CuaeServer._result_doit2 */
+	public static Type _mt_etch_examples_cuae_CuaeServer__result_doit2;
+
+	/** Type for etch.examples.cuae.Cuae.doit3 */
+	public static Type _mt_etch_examples_cuae_Cuae_doit3;
+
+	/** Type for etch.examples.cuae.Cuae._result_doit3 */
+	public static Type _mt_etch_examples_cuae_Cuae__result_doit3;
+
+	/** Type for etch.examples.cuae.Cuae.doit4 */
+	public static Type _mt_etch_examples_cuae_Cuae_doit4;
+
+	/** Type for etch.examples.cuae.Cuae._result_doit4 */
+	public static Type _mt_etch_examples_cuae_Cuae__result_doit4;
+
+	/** Type for etch.examples.cuae.CuaeServer.test1 */
+	public static Type _mt_etch_examples_cuae_CuaeServer_test1;
+
+	/** Type for etch.examples.cuae.CuaeClient.test2 */
+	public static Type _mt_etch_examples_cuae_CuaeClient_test2;
+
+	/** Type for etch.examples.cuae.Cuae.test3 */
+	public static Type _mt_etch_examples_cuae_Cuae_test3;
+
+	private static void initTypes()
+	{
+		_mt_etch_examples_cuae_Cuae_Request = types.get( "etch.examples.cuae.Cuae.Request" );
+		_mt_etch_examples_cuae_Cuae_ReqWithMessage = types.get( "etch.examples.cuae.Cuae.ReqWithMessage" );
+		_mt_etch_examples_cuae_Cuae_Response = types.get( "etch.examples.cuae.Cuae.Response" );
+		_mt_etch_examples_cuae_Cuae_RespWithCode = types.get( "etch.examples.cuae.Cuae.RespWithCode" );
+		_mt_etch_examples_cuae_CuaeServer_doit1 = types.get( "etch.examples.cuae.CuaeServer.doit1" );
+		_mt_etch_examples_cuae_CuaeClient__result_doit1 = types.get( "etch.examples.cuae.CuaeClient._result_doit1" );
+		_mt_etch_examples_cuae_CuaeClient_doit2 = types.get( "etch.examples.cuae.CuaeClient.doit2" );
+		_mt_etch_examples_cuae_CuaeServer__result_doit2 = types.get( "etch.examples.cuae.CuaeServer._result_doit2" );
+		_mt_etch_examples_cuae_Cuae_doit3 = types.get( "etch.examples.cuae.Cuae.doit3" );
+		_mt_etch_examples_cuae_Cuae__result_doit3 = types.get( "etch.examples.cuae.Cuae._result_doit3" );
+		_mt_etch_examples_cuae_Cuae_doit4 = types.get( "etch.examples.cuae.Cuae.doit4" );
+		_mt_etch_examples_cuae_Cuae__result_doit4 = types.get( "etch.examples.cuae.Cuae._result_doit4" );
+		_mt_etch_examples_cuae_CuaeServer_test1 = types.get( "etch.examples.cuae.CuaeServer.test1" );
+		_mt_etch_examples_cuae_CuaeClient_test2 = types.get( "etch.examples.cuae.CuaeClient.test2" );
+		_mt_etch_examples_cuae_Cuae_test3 = types.get( "etch.examples.cuae.Cuae.test3" );
+	}
+
+	private static void initResults()
+	{
+		_mt_etch_examples_cuae_CuaeServer_doit1.setResult( _mt_etch_examples_cuae_CuaeClient__result_doit1 );
+		_mt_etch_examples_cuae_CuaeClient__result_doit1.setTimeout( 497 );
+		_mt_etch_examples_cuae_CuaeClient_doit2.setResult( _mt_etch_examples_cuae_CuaeServer__result_doit2 );
+		_mt_etch_examples_cuae_CuaeServer__result_doit2.setTimeout( 497 );
+		_mt_etch_examples_cuae_Cuae_doit3.setResult( _mt_etch_examples_cuae_Cuae__result_doit3 );
+		_mt_etch_examples_cuae_Cuae__result_doit3.setTimeout( 497 );
+		_mt_etch_examples_cuae_Cuae_doit4.setResult( _mt_etch_examples_cuae_Cuae__result_doit4 );
+		_mt_etch_examples_cuae_Cuae__result_doit4.setTimeout( 497 );
+	}
+
+	private final static ImportExportHelper IMPORT_EXPORT_HELPER = new ImportExportHelper()
+	{
+		public final StructValue exportValue( ValueFactory vf, Object value )
+		{
+			return (StructValue) value;
+		}
+
+		public final Object importValue( StructValue struct )
+		{
+			return struct;
+		}
+	};
+	
+	static
+	{
+		_mt_etch_examples_cuae_Cuae_Request.setImportExportHelper( IMPORT_EXPORT_HELPER );
+		_mt_etch_examples_cuae_Cuae_ReqWithMessage.setImportExportHelper( IMPORT_EXPORT_HELPER );
+		_mt_etch_examples_cuae_Cuae_ReqWithMessage.setSuperType( _mt_etch_examples_cuae_Cuae_Request );
+		_mt_etch_examples_cuae_Cuae_Response.setImportExportHelper( IMPORT_EXPORT_HELPER );
+		_mt_etch_examples_cuae_Cuae_RespWithCode.setImportExportHelper( IMPORT_EXPORT_HELPER );
+		_mt_etch_examples_cuae_Cuae_RespWithCode.setSuperType( _mt_etch_examples_cuae_Cuae_Response );
+	}
+
+	/** Field for code */
+	public static Field _mf_code;
+
+	/** Field for msg */
+	public static Field _mf_msg;
+
+	/** Field for req */
+	public static Field _mf_req;
+
+	/** Field for result */
+	public static Field _mf_result;
+
+	private static void initFields()
+	{
+		_mf_code = new Field( "code" );
+		_mf_msg = new Field( "msg" );
+		_mf_req = new Field( "req" );
+		_mf_result = new Field( "result" );
+
+		_mt_etch_examples_cuae_CuaeClient__result_doit1.setResponseField( _mf_result );
+		_mt_etch_examples_cuae_CuaeServer__result_doit2.setResponseField( _mf_result );
+		_mt_etch_examples_cuae_Cuae__result_doit3.setResponseField( _mf_result );
+		_mt_etch_examples_cuae_Cuae__result_doit4.setResponseField( _mf_result );
+	}
+	
+	static
+	{
+		// initialize the extern serializers:
+	}
+
+	private static void initParams()
+	{
+
+		// params for Request
+		_mt_etch_examples_cuae_Cuae_Request.putValidator( _mf_code, org.apache.etch.bindings.java.support.Validator_int.get( 0 ) );
+
+		// params for ReqWithMessage
+		_mt_etch_examples_cuae_Cuae_ReqWithMessage.putValidator( _mf_code, org.apache.etch.bindings.java.support.Validator_int.get( 0 ) );
+		_mt_etch_examples_cuae_Cuae_ReqWithMessage.putValidator( _mf_msg, org.apache.etch.bindings.java.support.Validator_string.get( 0 ) );
+
+		// params for Response
+		_mt_etch_examples_cuae_Cuae_Response.putValidator( _mf_msg, org.apache.etch.bindings.java.support.Validator_string.get( 0 ) );
+
+		// params for RespWithCode
+		_mt_etch_examples_cuae_Cuae_RespWithCode.putValidator( _mf_msg, org.apache.etch.bindings.java.support.Validator_string.get( 0 ) );
+		_mt_etch_examples_cuae_Cuae_RespWithCode.putValidator( _mf_code, org.apache.etch.bindings.java.support.Validator_int.get( 0 ) );
+
+		// params for doit1
+		_mt_etch_examples_cuae_CuaeServer_doit1.putValidator( _mf_req, org.apache.etch.bindings.java.support.Validator_StructValue.get( _mt_etch_examples_cuae_Cuae_Request, 0 ) );
+		_mt_etch_examples_cuae_CuaeServer_doit1.putValidator( _mf__messageId, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+
+		// params for _result_doit1
+		_mt_etch_examples_cuae_CuaeClient__result_doit1.putValidator( _mf_result, org.apache.etch.bindings.java.support.Validator_StructValue.get( _mt_etch_examples_cuae_Cuae_Response, 0 ) );
+		_mt_etch_examples_cuae_CuaeClient__result_doit1.putValidator( _mf__messageId, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+		_mt_etch_examples_cuae_CuaeClient__result_doit1.putValidator( _mf_result, org.apache.etch.bindings.java.support.Validator_RuntimeException.get() ); // thrown RuntimeException
+		_mt_etch_examples_cuae_CuaeClient__result_doit1.putValidator( _mf__inReplyTo, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+
+		// params for doit2
+		_mt_etch_examples_cuae_CuaeClient_doit2.putValidator( _mf_req, org.apache.etch.bindings.java.support.Validator_StructValue.get( _mt_etch_examples_cuae_Cuae_Request, 0 ) );
+		_mt_etch_examples_cuae_CuaeClient_doit2.putValidator( _mf__messageId, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+
+		// params for _result_doit2
+		_mt_etch_examples_cuae_CuaeServer__result_doit2.putValidator( _mf_result, org.apache.etch.bindings.java.support.Validator_StructValue.get( _mt_etch_examples_cuae_Cuae_Response, 0 ) );
+		_mt_etch_examples_cuae_CuaeServer__result_doit2.putValidator( _mf__messageId, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+		_mt_etch_examples_cuae_CuaeServer__result_doit2.putValidator( _mf_result, org.apache.etch.bindings.java.support.Validator_RuntimeException.get() ); // thrown RuntimeException
+		_mt_etch_examples_cuae_CuaeServer__result_doit2.putValidator( _mf__inReplyTo, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+
+		// params for doit3
+		_mt_etch_examples_cuae_Cuae_doit3.putValidator( _mf_req, org.apache.etch.bindings.java.support.Validator_StructValue.get( _mt_etch_examples_cuae_Cuae_Request, 1 ) );
+		_mt_etch_examples_cuae_Cuae_doit3.putValidator( _mf__messageId, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+
+		// params for _result_doit3
+		_mt_etch_examples_cuae_Cuae__result_doit3.putValidator( _mf_result, org.apache.etch.bindings.java.support.Validator_StructValue.get( _mt_etch_examples_cuae_Cuae_Response, 1 ) );
+		_mt_etch_examples_cuae_Cuae__result_doit3.putValidator( _mf__messageId, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+		_mt_etch_examples_cuae_Cuae__result_doit3.putValidator( _mf_result, org.apache.etch.bindings.java.support.Validator_RuntimeException.get() ); // thrown RuntimeException
+		_mt_etch_examples_cuae_Cuae__result_doit3.putValidator( _mf__inReplyTo, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+
+		// params for doit4
+		_mt_etch_examples_cuae_Cuae_doit4.putValidator( _mf__messageId, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+
+		// params for _result_doit4
+		_mt_etch_examples_cuae_Cuae__result_doit4.putValidator( _mf_result, org.apache.etch.bindings.java.support.Validator_void.get( 0 ) );
+		_mt_etch_examples_cuae_Cuae__result_doit4.putValidator( _mf__messageId, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+		_mt_etch_examples_cuae_Cuae__result_doit4.putValidator( _mf_result, org.apache.etch.bindings.java.support.Validator_RuntimeException.get() ); // thrown RuntimeException
+		_mt_etch_examples_cuae_Cuae__result_doit4.putValidator( _mf__inReplyTo, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+
+		// params for test1
+		_mt_etch_examples_cuae_CuaeServer_test1.putValidator( _mf__messageId, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+
+		// params for test2
+		_mt_etch_examples_cuae_CuaeClient_test2.putValidator( _mf__messageId, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+
+		// params for test3
+		_mt_etch_examples_cuae_Cuae_test3.putValidator( _mf__messageId, org.apache.etch.bindings.java.support.Validator_long.get( 0 ) );
+	}
+	
+	static
+	{
+		// done updating types, and class2type: lock them.
+		types.lock();
+		for (Type t: types.values())
+			t.lock();
+		class2type.lock();
+	}
+}
diff --git a/tests/src/main/resources/org/apache/etch/tests/Test5WordsList.kwd b/tests/src/main/resources/org/apache/etch/tests/Test5WordsList.kwd
new file mode 100644
index 0000000..51d4562
--- /dev/null
+++ b/tests/src/main/resources/org/apache/etch/tests/Test5WordsList.kwd
@@ -0,0 +1,28 @@
+# $Id$
+# 
+# Copyright 2007-2008 Cisco Systems Inc.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy
+# of the License at
+#  
+#     http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+res1
+res2
+res3
+res4
+res5
+res6
+res7
+res8
+res9
+res10
+res11
+res12
\ No newline at end of file
diff --git a/tests/src/test/csharp/TestsProj/Properties/AssemblyInfo.cs b/tests/src/test/csharp/TestsProj/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..14d4165
--- /dev/null
+++ b/tests/src/test/csharp/TestsProj/Properties/AssemblyInfo.cs
@@ -0,0 +1,51 @@
+// Licensed to the Apache Software Foundation (ASF) under one   *
+// or more contributor license agreements.  See the NOTICE file *
+// distributed with this work for additional information        *
+// regarding copyright ownership.  The ASF licenses this file   *
+// to you under the Apache License, Version 2.0 (the            *
+// "License"); you may not use this file except in compliance   *
+// with the License.  You may obtain a copy of the License at   *
+//                                                              *
+//   http://www.apache.org/licenses/LICENSE-2.0                 *
+//                                                              *
+// Unless required by applicable law or agreed to in writing,   *
+// software distributed under the License is distributed on an  *
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+// KIND, either express or implied.  See the License for the    *
+// specific language governing permissions and limitations      *
+// under the License.                                           *
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Tests")]
+[assembly: AssemblyDescription("Etch Based Compiler Tests")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Cisco Systems, Inc")]
+[assembly: AssemblyProduct("Etch")]
+[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("35367139-9fb3-441f-9160-cbbc66eafbde")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.0.0.1")]
+[assembly: AssemblyFileVersion("0.0.0.1")]
diff --git a/tests/src/test/csharp/TestsProj/TestsProj.csproj b/tests/src/test/csharp/TestsProj/TestsProj.csproj
new file mode 100644
index 0000000..dd5c4eb
--- /dev/null
+++ b/tests/src/test/csharp/TestsProj/TestsProj.csproj
@@ -0,0 +1,799 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{70701740-652A-4E07-9B85-59DDCC9D43D4}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>etch.tests</RootNamespace>
+    <AssemblyName>Tests</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="nunit.framework, Version=2.4.7.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>$(NUNIT_HOME)\bin\nunit.framework.dll</HintPath>
+      <SpecificVersion>False</SpecificVersion>
+    </Reference>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Async.cs">
+      <Link>org.apache.etch.tests\Async.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\AsyncClient.cs">
+      <Link>org.apache.etch.tests\AsyncClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\AsyncHelper.cs">
+      <Link>org.apache.etch.tests\AsyncHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\AsyncServer.cs">
+      <Link>org.apache.etch.tests\AsyncServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Bar.cs">
+      <Link>org.apache.etch.tests\Bar.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BarClient.cs">
+      <Link>org.apache.etch.tests\BarClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BarHelper.cs">
+      <Link>org.apache.etch.tests\BarHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BarServer.cs">
+      <Link>org.apache.etch.tests\BarServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseAsyncClient.cs">
+      <Link>org.apache.etch.tests\BaseAsyncClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseAsyncServer.cs">
+      <Link>org.apache.etch.tests\BaseAsyncServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseBarClient.cs">
+      <Link>org.apache.etch.tests\BaseBarClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseBarServer.cs">
+      <Link>org.apache.etch.tests\BaseBarServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseBazClient.cs">
+      <Link>org.apache.etch.tests\BaseBazClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseBazServer.cs">
+      <Link>org.apache.etch.tests\BaseBazServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseBigIdlClient.cs">
+      <Link>org.apache.etch.tests\BaseBigIdlClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseBigIdlServer.cs">
+      <Link>org.apache.etch.tests\BaseBigIdlServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseClosingClient.cs">
+      <Link>org.apache.etch.tests\BaseClosingClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseClosingServer.cs">
+      <Link>org.apache.etch.tests\BaseClosingServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseCuaeClient.cs">
+      <Link>org.apache.etch.tests\BaseCuaeClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseCuaeServer.cs">
+      <Link>org.apache.etch.tests\BaseCuaeServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseFooClient.cs">
+      <Link>org.apache.etch.tests\BaseFooClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseFooServer.cs">
+      <Link>org.apache.etch.tests\BaseFooServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseInheritanceClient.cs">
+      <Link>org.apache.etch.tests\BaseInheritanceClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseInheritanceServer.cs">
+      <Link>org.apache.etch.tests\BaseInheritanceServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseTest1Client.cs">
+      <Link>org.apache.etch.tests\BaseTest1Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseTest1Server.cs">
+      <Link>org.apache.etch.tests\BaseTest1Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseTest2Client.cs">
+      <Link>org.apache.etch.tests\BaseTest2Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseTest2Server.cs">
+      <Link>org.apache.etch.tests\BaseTest2Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseTest3Client.cs">
+      <Link>org.apache.etch.tests\BaseTest3Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseTest3Server.cs">
+      <Link>org.apache.etch.tests\BaseTest3Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseTest4Client.cs">
+      <Link>org.apache.etch.tests\BaseTest4Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseTest4Server.cs">
+      <Link>org.apache.etch.tests\BaseTest4Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseTest6Client.cs">
+      <Link>org.apache.etch.tests\BaseTest6Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseTest6Server.cs">
+      <Link>org.apache.etch.tests\BaseTest6Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseTestIncludesClient.cs">
+      <Link>org.apache.etch.tests\BaseTestIncludesClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseTestIncludesServer.cs">
+      <Link>org.apache.etch.tests\BaseTestIncludesServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseTypesClient.cs">
+      <Link>org.apache.etch.tests\BaseTypesClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BaseTypesServer.cs">
+      <Link>org.apache.etch.tests\BaseTypesServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Baz.cs">
+      <Link>org.apache.etch.tests\Baz.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BazClient.cs">
+      <Link>org.apache.etch.tests\BazClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BazHelper.cs">
+      <Link>org.apache.etch.tests\BazHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BazServer.cs">
+      <Link>org.apache.etch.tests\BazServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BigIdl.cs">
+      <Link>org.apache.etch.tests\BigIdl.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BigIdlClient.cs">
+      <Link>org.apache.etch.tests\BigIdlClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BigIdlHelper.cs">
+      <Link>org.apache.etch.tests\BigIdlHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\BigIdlServer.cs">
+      <Link>org.apache.etch.tests\BigIdlServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Closing.cs">
+      <Link>org.apache.etch.tests\Closing.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ClosingClient.cs">
+      <Link>org.apache.etch.tests\ClosingClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ClosingHelper.cs">
+      <Link>org.apache.etch.tests\ClosingHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ClosingServer.cs">
+      <Link>org.apache.etch.tests\ClosingServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Cuae.cs">
+      <Link>org.apache.etch.tests\Cuae.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\CuaeClient.cs">
+      <Link>org.apache.etch.tests\CuaeClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\CuaeHelper.cs">
+      <Link>org.apache.etch.tests\CuaeHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\CuaeServer.cs">
+      <Link>org.apache.etch.tests\CuaeServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Foo.cs">
+      <Link>org.apache.etch.tests\Foo.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\FooClient.cs">
+      <Link>org.apache.etch.tests\FooClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\FooHelper.cs">
+      <Link>org.apache.etch.tests\FooHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\FooServer.cs">
+      <Link>org.apache.etch.tests\FooServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ImplTest1Client.cs">
+      <Link>org.apache.etch.tests\ImplTest1Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ImplTest1Server.cs">
+      <Link>org.apache.etch.tests\ImplTest1Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ImplTestIncludesClient.cs">
+      <Link>org.apache.etch.tests\ImplTestIncludesClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ImplTestIncludesServer.cs">
+      <Link>org.apache.etch.tests\ImplTestIncludesServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Inheritance.cs">
+      <Link>org.apache.etch.tests\Inheritance.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\InheritanceClient.cs">
+      <Link>org.apache.etch.tests\InheritanceClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\InheritanceHelper.cs">
+      <Link>org.apache.etch.tests\InheritanceHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\InheritanceServer.cs">
+      <Link>org.apache.etch.tests\InheritanceServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\MainTest1Client.cs">
+      <Link>org.apache.etch.tests\MainTest1Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\MainTest1Listener.cs">
+      <Link>org.apache.etch.tests\MainTest1Listener.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\MainTestIncludesClient.cs">
+      <Link>org.apache.etch.tests\MainTestIncludesClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\MainTestIncludesListener.cs">
+      <Link>org.apache.etch.tests\MainTestIncludesListener.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteAsync.cs">
+      <Link>org.apache.etch.tests\RemoteAsync.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteAsyncClient.cs">
+      <Link>org.apache.etch.tests\RemoteAsyncClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteAsyncServer.cs">
+      <Link>org.apache.etch.tests\RemoteAsyncServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteBar.cs">
+      <Link>org.apache.etch.tests\RemoteBar.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteBarClient.cs">
+      <Link>org.apache.etch.tests\RemoteBarClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteBarServer.cs">
+      <Link>org.apache.etch.tests\RemoteBarServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteBaz.cs">
+      <Link>org.apache.etch.tests\RemoteBaz.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteBazClient.cs">
+      <Link>org.apache.etch.tests\RemoteBazClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteBazServer.cs">
+      <Link>org.apache.etch.tests\RemoteBazServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteBigIdl.cs">
+      <Link>org.apache.etch.tests\RemoteBigIdl.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteBigIdlClient.cs">
+      <Link>org.apache.etch.tests\RemoteBigIdlClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteBigIdlServer.cs">
+      <Link>org.apache.etch.tests\RemoteBigIdlServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteClosing.cs">
+      <Link>org.apache.etch.tests\RemoteClosing.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteClosingClient.cs">
+      <Link>org.apache.etch.tests\RemoteClosingClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteClosingServer.cs">
+      <Link>org.apache.etch.tests\RemoteClosingServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteCuae.cs">
+      <Link>org.apache.etch.tests\RemoteCuae.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteCuaeClient.cs">
+      <Link>org.apache.etch.tests\RemoteCuaeClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteCuaeServer.cs">
+      <Link>org.apache.etch.tests\RemoteCuaeServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteFoo.cs">
+      <Link>org.apache.etch.tests\RemoteFoo.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteFooClient.cs">
+      <Link>org.apache.etch.tests\RemoteFooClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteFooServer.cs">
+      <Link>org.apache.etch.tests\RemoteFooServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteInheritance.cs">
+      <Link>org.apache.etch.tests\RemoteInheritance.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteInheritanceClient.cs">
+      <Link>org.apache.etch.tests\RemoteInheritanceClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteInheritanceServer.cs">
+      <Link>org.apache.etch.tests\RemoteInheritanceServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTest1.cs">
+      <Link>org.apache.etch.tests\RemoteTest1.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTest1Client.cs">
+      <Link>org.apache.etch.tests\RemoteTest1Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTest1Server.cs">
+      <Link>org.apache.etch.tests\RemoteTest1Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTest2.cs">
+      <Link>org.apache.etch.tests\RemoteTest2.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTest2Client.cs">
+      <Link>org.apache.etch.tests\RemoteTest2Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTest2Server.cs">
+      <Link>org.apache.etch.tests\RemoteTest2Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTest3.cs">
+      <Link>org.apache.etch.tests\RemoteTest3.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTest3Client.cs">
+      <Link>org.apache.etch.tests\RemoteTest3Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTest3Server.cs">
+      <Link>org.apache.etch.tests\RemoteTest3Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTest4.cs">
+      <Link>org.apache.etch.tests\RemoteTest4.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTest4Client.cs">
+      <Link>org.apache.etch.tests\RemoteTest4Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTest4Server.cs">
+      <Link>org.apache.etch.tests\RemoteTest4Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTest6.cs">
+      <Link>org.apache.etch.tests\RemoteTest6.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTest6Client.cs">
+      <Link>org.apache.etch.tests\RemoteTest6Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTest6Server.cs">
+      <Link>org.apache.etch.tests\RemoteTest6Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTestIncludes.cs">
+      <Link>org.apache.etch.tests\RemoteTestIncludes.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTestIncludesClient.cs">
+      <Link>org.apache.etch.tests\RemoteTestIncludesClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTestIncludesServer.cs">
+      <Link>org.apache.etch.tests\RemoteTestIncludesServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTypes.cs">
+      <Link>org.apache.etch.tests\RemoteTypes.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTypesClient.cs">
+      <Link>org.apache.etch.tests\RemoteTypesClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\RemoteTypesServer.cs">
+      <Link>org.apache.etch.tests\RemoteTypesServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubAsync.cs">
+      <Link>org.apache.etch.tests\StubAsync.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubAsyncClient.cs">
+      <Link>org.apache.etch.tests\StubAsyncClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubAsyncServer.cs">
+      <Link>org.apache.etch.tests\StubAsyncServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubBar.cs">
+      <Link>org.apache.etch.tests\StubBar.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubBarClient.cs">
+      <Link>org.apache.etch.tests\StubBarClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubBarServer.cs">
+      <Link>org.apache.etch.tests\StubBarServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubBaz.cs">
+      <Link>org.apache.etch.tests\StubBaz.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubBazClient.cs">
+      <Link>org.apache.etch.tests\StubBazClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubBazServer.cs">
+      <Link>org.apache.etch.tests\StubBazServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubBigIdl.cs">
+      <Link>org.apache.etch.tests\StubBigIdl.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubBigIdlClient.cs">
+      <Link>org.apache.etch.tests\StubBigIdlClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubBigIdlServer.cs">
+      <Link>org.apache.etch.tests\StubBigIdlServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubClosing.cs">
+      <Link>org.apache.etch.tests\StubClosing.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubClosingClient.cs">
+      <Link>org.apache.etch.tests\StubClosingClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubClosingServer.cs">
+      <Link>org.apache.etch.tests\StubClosingServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubCuae.cs">
+      <Link>org.apache.etch.tests\StubCuae.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubCuaeClient.cs">
+      <Link>org.apache.etch.tests\StubCuaeClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubCuaeServer.cs">
+      <Link>org.apache.etch.tests\StubCuaeServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubFoo.cs">
+      <Link>org.apache.etch.tests\StubFoo.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubFooClient.cs">
+      <Link>org.apache.etch.tests\StubFooClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubFooServer.cs">
+      <Link>org.apache.etch.tests\StubFooServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubInheritance.cs">
+      <Link>org.apache.etch.tests\StubInheritance.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubInheritanceClient.cs">
+      <Link>org.apache.etch.tests\StubInheritanceClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubInheritanceServer.cs">
+      <Link>org.apache.etch.tests\StubInheritanceServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTest1.cs">
+      <Link>org.apache.etch.tests\StubTest1.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTest1Client.cs">
+      <Link>org.apache.etch.tests\StubTest1Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTest1Server.cs">
+      <Link>org.apache.etch.tests\StubTest1Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTest2.cs">
+      <Link>org.apache.etch.tests\StubTest2.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTest2Client.cs">
+      <Link>org.apache.etch.tests\StubTest2Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTest2Server.cs">
+      <Link>org.apache.etch.tests\StubTest2Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTest3.cs">
+      <Link>org.apache.etch.tests\StubTest3.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTest3Client.cs">
+      <Link>org.apache.etch.tests\StubTest3Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTest3Server.cs">
+      <Link>org.apache.etch.tests\StubTest3Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTest4.cs">
+      <Link>org.apache.etch.tests\StubTest4.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTest4Client.cs">
+      <Link>org.apache.etch.tests\StubTest4Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTest4Server.cs">
+      <Link>org.apache.etch.tests\StubTest4Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTest6.cs">
+      <Link>org.apache.etch.tests\StubTest6.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTest6Client.cs">
+      <Link>org.apache.etch.tests\StubTest6Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTest6Server.cs">
+      <Link>org.apache.etch.tests\StubTest6Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTestIncludes.cs">
+      <Link>org.apache.etch.tests\StubTestIncludes.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTestIncludesClient.cs">
+      <Link>org.apache.etch.tests\StubTestIncludesClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTestIncludesServer.cs">
+      <Link>org.apache.etch.tests\StubTestIncludesServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTypes.cs">
+      <Link>org.apache.etch.tests\StubTypes.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTypesClient.cs">
+      <Link>org.apache.etch.tests\StubTypesClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\StubTypesServer.cs">
+      <Link>org.apache.etch.tests\StubTypesServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test1.cs">
+      <Link>org.apache.etch.tests\Test1.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test1Client.cs">
+      <Link>org.apache.etch.tests\Test1Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test1Helper.cs">
+      <Link>org.apache.etch.tests\Test1Helper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test1Server.cs">
+      <Link>org.apache.etch.tests\Test1Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test2.cs">
+      <Link>org.apache.etch.tests\Test2.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test2Client.cs">
+      <Link>org.apache.etch.tests\Test2Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test2Helper.cs">
+      <Link>org.apache.etch.tests\Test2Helper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test2Server.cs">
+      <Link>org.apache.etch.tests\Test2Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test3.cs">
+      <Link>org.apache.etch.tests\Test3.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test3Client.cs">
+      <Link>org.apache.etch.tests\Test3Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test3Helper.cs">
+      <Link>org.apache.etch.tests\Test3Helper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test3Server.cs">
+      <Link>org.apache.etch.tests\Test3Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test4.cs">
+      <Link>org.apache.etch.tests\Test4.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test4Client.cs">
+      <Link>org.apache.etch.tests\Test4Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test4Helper.cs">
+      <Link>org.apache.etch.tests\Test4Helper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test4Server.cs">
+      <Link>org.apache.etch.tests\Test4Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test6.cs">
+      <Link>org.apache.etch.tests\Test6.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test6Client.cs">
+      <Link>org.apache.etch.tests\Test6Client.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test6Helper.cs">
+      <Link>org.apache.etch.tests\Test6Helper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Test6Server.cs">
+      <Link>org.apache.etch.tests\Test6Server.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\TestIncludes.cs">
+      <Link>org.apache.etch.tests\TestIncludes.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\TestIncludesClient.cs">
+      <Link>org.apache.etch.tests\TestIncludesClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\TestIncludesHelper.cs">
+      <Link>org.apache.etch.tests\TestIncludesHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\TestIncludesServer.cs">
+      <Link>org.apache.etch.tests\TestIncludesServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\Types.cs">
+      <Link>org.apache.etch.tests\Types.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\TypesClient.cs">
+      <Link>org.apache.etch.tests\TypesClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\TypesHelper.cs">
+      <Link>org.apache.etch.tests\TypesHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\TypesServer.cs">
+      <Link>org.apache.etch.tests\TypesServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ValueFactoryAsync.cs">
+      <Link>org.apache.etch.tests\ValueFactoryAsync.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ValueFactoryBar.cs">
+      <Link>org.apache.etch.tests\ValueFactoryBar.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ValueFactoryBaz.cs">
+      <Link>org.apache.etch.tests\ValueFactoryBaz.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ValueFactoryBigIdl.cs">
+      <Link>org.apache.etch.tests\ValueFactoryBigIdl.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ValueFactoryClosing.cs">
+      <Link>org.apache.etch.tests\ValueFactoryClosing.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ValueFactoryCuae.cs">
+      <Link>org.apache.etch.tests\ValueFactoryCuae.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ValueFactoryFoo.cs">
+      <Link>org.apache.etch.tests\ValueFactoryFoo.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ValueFactoryInheritance.cs">
+      <Link>org.apache.etch.tests\ValueFactoryInheritance.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ValueFactoryTest1.cs">
+      <Link>org.apache.etch.tests\ValueFactoryTest1.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ValueFactoryTest2.cs">
+      <Link>org.apache.etch.tests\ValueFactoryTest2.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ValueFactoryTest3.cs">
+      <Link>org.apache.etch.tests\ValueFactoryTest3.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ValueFactoryTest4.cs">
+      <Link>org.apache.etch.tests\ValueFactoryTest4.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ValueFactoryTest6.cs">
+      <Link>org.apache.etch.tests\ValueFactoryTest6.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ValueFactoryTestIncludes.cs">
+      <Link>org.apache.etch.tests\ValueFactoryTestIncludes.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\target\generated-sources\main\etch\csharp\org.apache.etch.tests\ValueFactoryTypes.cs">
+      <Link>org.apache.etch.tests\ValueFactoryTypes.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\ImplAsyncClient.cs">
+      <Link>etch.tests\ImplAsyncClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\ImplAsyncServer.cs">
+      <Link>etch.tests\ImplAsyncServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\ImplClosingClient.cs">
+      <Link>etch.tests\ImplClosingClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\ImplClosingServer.cs">
+      <Link>etch.tests\ImplClosingServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\ImplCuaeClient.cs">
+      <Link>etch.tests\ImplCuaeClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\ImplCuaeServer.cs">
+      <Link>etch.tests\ImplCuaeServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\ImplFooClient.cs">
+      <Link>etch.tests\ImplFooClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\ImplFooServer.cs">
+      <Link>etch.tests\ImplFooServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\ImplInheritanceClient.cs">
+      <Link>etch.tests\ImplInheritanceClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\ImplInheritanceServer.cs">
+      <Link>etch.tests\ImplInheritanceServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\ImplTypesClient.cs">
+      <Link>etch.tests\ImplTypesClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\ImplTypesServer.cs">
+      <Link>etch.tests\ImplTypesServer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\MainAsyncClient.cs">
+      <Link>etch.tests\MainAsyncClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\MainAsyncListener.cs">
+      <Link>etch.tests\MainAsyncListener.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\MainClosingClient.cs">
+      <Link>etch.tests\MainClosingClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\MainClosingListener.cs">
+      <Link>etch.tests\MainClosingListener.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\MainCuaeClient.cs">
+      <Link>etch.tests\MainCuaeClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\MainCuaeListener.cs">
+      <Link>etch.tests\MainCuaeListener.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\MainFooClient.cs">
+      <Link>etch.tests\MainFooClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\MainFooListener.cs">
+      <Link>etch.tests\MainFooListener.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\MainInheritanceClient.cs">
+      <Link>etch.tests\MainInheritanceClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\MainInheritanceListener.cs">
+      <Link>etch.tests\MainInheritanceListener.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\MainTypesClient.cs">
+      <Link>etch.tests\MainTypesClient.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\MainTypesListener.cs">
+      <Link>etch.tests\MainTypesListener.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\MyCuaeHelper.cs">
+      <Link>etch.tests\MyCuaeHelper.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\MyCuaeServerStub.cs">
+      <Link>etch.tests\MyCuaeServerStub.cs</Link>
+    </Compile>
+    <Compile Include="..\..\..\main\csharp\etch.tests\MyValueFactoryCuae.cs">
+      <Link>etch.tests\MyValueFactoryCuae.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.tests\FakeTest1.cs">
+      <Link>FakeTest1.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.tests\TestAsyncClient.cs">
+      <Link>TestAsyncClient.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.tests\TestImplTest1.cs">
+      <Link>TestImplTest1.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.tests\TestInheritance.cs">
+      <Link>TestInheritance.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.tests\TestMainTest1Client.cs">
+      <Link>TestMainTest1Client.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.tests\TestMainTest1Listener.cs">
+      <Link>TestMainTest1Listener.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.tests\TestMixin.cs">
+      <Link>TestMixin.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.tests\TestRemoteTest1DotCsharp.cs">
+      <Link>TestRemoteTest1DotCsharp.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.tests\TestStubTest1DotCsharp.cs">
+      <Link>TestStubTest1DotCsharp.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.tests\TestTest1DotCsharp.cs">
+      <Link>TestTest1DotCsharp.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.tests\TestTest1Helper.cs">
+      <Link>TestTest1Helper.cs</Link>
+    </Compile>
+    <Compile Include="..\etch.tests\TestValueFactoryTest1DotCsharp.cs">
+      <Link>TestValueFactoryTest1DotCsharp.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\..\binding-csharp\runtime\src\main\csharp\EtchProj.csproj">
+      <Project>{0E518F2A-3016-4C2F-A21B-9BD52B2DC846}</Project>
+      <Name>EtchProj</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/tests/src/test/csharp/etch.tests/FakeTest1.cs b/tests/src/test/csharp/etch.tests/FakeTest1.cs
new file mode 100644
index 0000000..2dc780b
--- /dev/null
+++ b/tests/src/test/csharp/etch.tests/FakeTest1.cs
@@ -0,0 +1,562 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using org.apache.etch.tests;
+using org.apache.etch.tests.types.Test1;
+
+namespace etch.tests
+{
+    class FakeTest1 : Test1
+    {
+        public int? beets( E1? e ) 
+	    {
+		    
+    		
+		    switch (e)
+		    {
+                case E1.A:
+                    return 5;
+                case E1.B:
+                    throw new Excp3();
+                case E1.C:
+                    throw new Excp4();
+			    default: return null;
+		    }
+	    }
+
+	    public void blow( String msg, int? code )  
+	    {
+		    throw new Excp1( msg, code );
+	    }
+
+	    public double? dist( S1 a, S1 b )
+	    {
+		    S1 c = new S1( a.x-b.x, a.y-b.y, a.z-b.z );
+		    return Math.Sqrt( (double)(c.x*c.x + c.y*c.y + c.z*c.z) );
+	    }
+
+	    public int? incr( int? x )
+	    {
+		    return x+1;
+	    }
+
+	    public void nothing()
+	    {
+		    // nothing.
+	    }
+
+	    public int? sub( int? x, int? y )
+	    {
+		    return x-y;
+	    }
+
+	    public int? sum( int[] x )
+	    {
+		    int sum = 0;
+		    foreach (int i in x)
+			    sum += i;
+		    return sum;
+	    }
+
+	    public int? trans( E1? e, int? x )
+	    {
+		    switch (e)
+		    {
+                case E1.A:
+                    return x / 2;
+                case E1.B:
+                    return x * 2;
+                case E1.C:
+                    return x + 7;
+			    default: return null;
+		    }
+	    }
+
+	    public int[] fill( int? n, int? x )
+	    {
+		    int[] y = new int[(int)n];
+		    for (int i = 0; i < n; i++)
+			    y[i] = (int)x;
+		    return y;
+	    }
+
+        public E1? p_E1( E1? a )
+	    {
+		    return a;
+	    }
+
+        public E1[] p_E1_array( E1[] a )
+	    {
+		    return a;
+	    }
+
+        public S1 p_S1( S1 a )
+	    {
+		    return a;
+	    }
+
+        public S1[] p_S1_array( S1[] a )
+	    {
+		    return a;
+	    }
+
+        public S2 p_S2( S2 a )
+	    {
+		    return a;
+	    }
+
+        public S2[] p_S2_array( S2[] a )
+	    {
+		    return a;
+	    }
+
+	    public bool? p_boolean( bool? a )
+	    {
+		    return a;
+	    }
+
+	    public bool[] p_boolean_array( bool[] a )
+	    {
+		    return a;
+	    }
+
+	    public sbyte? p_byte( sbyte? a )
+	    {
+		    return a;
+	    }
+
+	    public sbyte[] p_byte_array( sbyte[] a )
+	    {
+		    return a;
+	    }
+
+        public double? p_double( double? a )
+	    {
+		    return a;
+	    }
+
+	    public double[] p_double_array( double[] a )
+	    {
+		    return a;
+	    }
+
+	    public float? p_float( float? a )
+	    {
+		    return a;
+	    }
+
+	    public float[] p_float_array( float[] a )
+	    {
+		    return a;
+	    }
+
+	    public int? p_int( int? a )
+	    {
+		    return a;
+	    }
+
+	    public int[] p_int_array( int[] a )
+	    {
+		    return a;
+	    }
+
+	    public long? p_long( long? a )
+	    {
+		    return a;
+	    }
+
+	    public long[] p_long_array( long[] a )
+	    {
+		    return a;
+	    }
+
+	    public short? p_short( short? a )
+	    {
+		    return a;
+	    }
+
+	    public short[] p_short_array( short[] a )
+	    {
+		    return a;
+	    }
+
+	    public string p_string( string a )
+	    {
+		    return a;
+	    }
+
+	    public string[] p_string_array( string[] a )
+	    {
+		    return a;
+	    }
+
+	    public StrIntHashMap p_Blob( StrIntHashMap a )
+	    {
+		    return a;
+	    }
+
+	    public StrIntHashMap[] p_Blob_array( StrIntHashMap[] a )
+	    {
+		    return a;
+	    }
+
+	    public void alwaysFails()
+	    {
+		    // i'm never called.
+		    throw new Exception( "alwaysFails" );
+	    }
+
+	    public int? alwaysWorks()
+	    {
+		    // i'm always called.
+		    return 23;
+	    }
+
+	    public bool? isFalse()
+	    {
+		    return false;
+	    }
+
+	    public bool? isTrue()
+	    {
+		    return true;
+	    }
+
+	    public int? add( int? a, int? b )
+	    {
+		    return a + b;
+	    }
+
+	    public bool? canAdd( bool flag, int? x )
+	    {
+		    // TODO Auto-generated method stub
+		    return null;
+	    }
+
+	    public bool? canM1()
+	    {
+		    // TODO Auto-generated method stub
+		    return null;
+	    }
+
+	    public bool? canM10( double? x )
+	    {
+		    // TODO Auto-generated method stub
+		    return null;
+	    }
+
+	    public bool? canM2( bool? x )
+	    {
+		    // TODO Auto-generated method stub
+		    return null;
+	    }
+
+	    public bool? canM3( bool? x )
+	    {
+		    // TODO Auto-generated method stub
+		    return null;
+	    }
+
+	    public bool? canM4( bool? x )
+	    {
+		    // TODO Auto-generated method stub
+		    return null;
+	    }
+
+	    public bool? can_m7( int? x )
+	    {
+		    // TODO Auto-generated method stub
+		    return null;
+	    }
+       
+
+	    public void m1()
+	    {
+		    // TODO Auto-generated method stub
+    		
+	    }
+
+	    public void m10()
+	    {
+		    // TODO Auto-generated method stub
+    		
+	    }
+
+	    public void m2()
+	    {
+		    // TODO Auto-generated method stub
+    		
+	    }
+
+	    public void m3()
+	    {
+		    // TODO Auto-generated method stub
+    		
+	    }
+
+	    public void m4()
+	    {
+		    // TODO Auto-generated method stub
+    		
+	    }
+
+	    public void m7()
+	    {
+		    // TODO Auto-generated method stub
+    		
+	    }
+
+       
+
+       
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#m11()
+         */
+        public void m11()
+        {
+            // TODO Auto-generated method stub
+
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#m5()
+         */
+        public void m5()
+        {
+            // TODO Auto-generated method stub
+
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#m6()
+         */
+        public void m6()
+        {
+            // TODO Auto-generated method stub
+
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#m8()
+         */
+        public void m8()
+        {
+            // TODO Auto-generated method stub
+
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#m9()
+         */
+        public void m9()
+        {
+            // TODO Auto-generated method stub
+
+        }
+
+        public bool? can_m1()
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        public bool? can_m2(bool? x)
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        public bool? can_m3(bool? x)
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        public bool? can_m4(bool? x)
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#can_m11(java.lang.String)
+         */
+        public bool? can_m11( string x )
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#can_m5(java.lang.Byte)
+         */
+        public bool? can_m5( sbyte? x )
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#can_m6(java.lang.Short)
+         */
+        public bool? can_m6( short? x )
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#can_m8(java.lang.Long)
+         */
+        public bool? can_m8( long? x )
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#can_m9(java.lang.Float)
+         */
+        public bool? can_m9( float? x )
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        public bool? can_m10( double? x)
+        {
+            return null;
+        }
+
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#can_m12(java.lang.Integer)
+         */
+        public bool? can_m12( int? x )
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#can_m13(java.lang.Integer)
+         */
+        public bool? can_m13( int? x )
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#can_m14(java.lang.Integer)
+         */
+        public bool? can_m14( int? x )
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#can_m15(etch.bindings.java.compiler.test.Test.E1)
+         */
+        public bool? can_m15( E1? x )
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#m12()
+         */
+        public void m12()
+        {
+            // TODO Auto-generated method stub
+
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#m13(java.lang.Integer)
+         */
+        public void m13( int? k )
+        {
+            // TODO Auto-generated method stub
+
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#m14(etch.bindings.java.compiler.test.Test.S1)
+         */
+        public void m14( S1 k )
+        {
+            // TODO Auto-generated method stub
+
+        }
+
+        /* (non-Javadoc)
+         * @see etch.bindings.java.compiler.test.Test#m15()
+         */
+        public void m15()
+        {
+            // TODO Auto-generated method stub
+
+        }
+
+        // fill numElements of array with value o
+        public object[] fillObject( int? numElements, object o )
+        {
+            object[] y = new object[ (int) numElements ];
+            for ( int i = 0; i < numElements; i++ )
+                y[ i ] = o;
+            return y;
+        }
+
+        public object p_object( object a ) 
+        {
+		    return a;
+	    }
+
+	    public object[] p_object_array( object[] a ) 
+        {
+		    return a;
+	    }
+
+	    public S3 p_object_struct( S3 a ) 
+        {
+		    return a;
+	    }
+
+	    public S4 p_object_struct_array( S4 a ) 
+        {
+		    return a;
+	    }
+
+	    public void throwExcp5( String msg, int? code, object value ) 
+        {
+		    throw new Excp5( msg, code, value );
+	    }
+
+	    public void throwExcp6(String msg, int? code, object[] value ) 
+        {
+		   throw new Excp6( msg, code, value );		
+	    }
+    }
+}
diff --git a/tests/src/test/csharp/etch.tests/TestAsyncClient.cs b/tests/src/test/csharp/etch.tests/TestAsyncClient.cs
new file mode 100644
index 0000000..9cd3907
--- /dev/null
+++ b/tests/src/test/csharp/etch.tests/TestAsyncClient.cs
@@ -0,0 +1,92 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+using org.apache.etch.tests;
+
+namespace etch.tests
+{
+    [TestFixture]
+    public class TestAsyncClient
+    {
+
+        private static RemoteAsyncServer server;
+        private static ServerFactory listener;
+
+        [TestFixtureSetUp]
+        public void Setup()
+        {
+      //      MainAsyncListener.Main(new String[] { });
+  
+            String uri = "tcp://localhost:4010";         
+
+            MainAsyncListener implFactory = new MainAsyncListener();
+            listener = AsyncHelper.NewListener(uri, null, implFactory);
+
+            listener.TransportControl(TransportConsts.START_AND_WAIT_UP, 4000);
+
+            MainAsyncClient client = new MainAsyncClient();
+            server = AsyncHelper.NewServer(uri, null, client);
+          
+
+            server._StartAndWaitUp(4000);
+        }
+
+
+        [Test]
+        public void sync1()
+        {
+
+            Assert.AreEqual(0, server.sync(0));
+
+        }
+
+       
+
+        [Test]
+        public void async_queued1()
+        {
+            for (int i = 0; i < 5; i++)
+                Assert.AreEqual(i, server.async_queued(i));
+        }
+        
+        
+        
+
+        
+        [Test]
+	    public void async_free() 
+	    {
+		    for (int i = 0; i < 10; i++)
+                Assert.AreEqual(i, server.async_free(i));
+	    }
+
+        [TestFixtureTearDown]
+        public void Method_CloseNewTestListener()
+        {
+           
+                server._StopAndWaitDown(4000);
+                listener.TransportControl(TransportConsts.STOP_AND_WAIT_DOWN,4000);
+        }
+ 
+    } 
+}
diff --git a/tests/src/test/csharp/etch.tests/TestImplTest1.cs b/tests/src/test/csharp/etch.tests/TestImplTest1.cs
new file mode 100644
index 0000000..100f3ac
--- /dev/null
+++ b/tests/src/test/csharp/etch.tests/TestImplTest1.cs
@@ -0,0 +1,1239 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+using org.apache.etch.tests;
+using org.apache.etch.tests.types.Test1;
+
+namespace etch.tests
+{
+    [TestFixture]
+    public class TestImplTest1
+    {
+     
+    //    private Test1Server ts = null;
+        private ImplTest1Server testServer = null;
+        private ImplTest1Client testClient = null;
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestImpl" );
+        }
+
+        [SetUp]
+        public void Setup()
+        {
+            RemoteTest1Client tc = null;
+            RemoteTest1Server ts = null;
+            testServer = new ImplTest1Server( tc );
+            testClient = new ImplTest1Client( ts);
+        }
+
+        [Test]
+        public void TestIncr()
+        {
+            try
+            {
+                int? i = 5;
+                testServer.incr( i );
+                testClient.incr( i );
+            }
+            catch ( Exception )
+            { }
+        }
+
+        [Test] 
+        public void TestNothing() 
+        {
+		
+		    try
+		    {			
+			    testServer.nothing();		
+			    testClient.nothing();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    		
+		    }
+	    }
+	
+	    [Test] 
+        public void TestAdd() 
+        {
+		    try
+		    {
+                int? i = 5;
+                int? j = 3;
+                testServer.add( i, j );
+                testClient.add( i, j );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void TestSub() 
+        {
+		    try
+		    {
+                int? i = 5;
+                int? j = 3;
+                testServer.sub( i, j );
+                testClient.sub( i, j );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void TestSum() 
+        {
+		    try
+		    {
+                int[] x = { 1, 2, 3 };
+			    testServer.sum( x );
+			    testClient.sum( x );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }				
+	    }
+    	
+	    [Test] 
+        public void  TestFill() 
+        {
+		    try
+		    {
+                int? i = 5;
+                int? j = 3;
+			    testServer.fill( i, j );
+                testClient.fill( i, j );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }				
+	    }
+    	
+	    [Test] 
+        public void  TestFillObject() 
+        {
+		    try
+		    {
+                int? i = 5;
+			    Object j = null;
+			    testServer.fillObject( i, j );
+                testClient.fillObject( i, j );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }				
+	    }
+    	
+    	
+	    [Test] 
+        public void  TestTrans() 
+        {
+		    try
+		    {
+                int? i = 5;
+                E1 enumA = E1.A;
+                testServer.trans( enumA, i );
+                testClient.trans( enumA, i );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }				
+	    }
+    	
+	    [Test] public void  TestDist() 
+        {
+		    try
+		    {
+                //int? i = 5;
+			    S1 a = new S1();
+			    S1 b = new S1();
+                testServer.dist( a, b );
+			    testClient.dist( a, b );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }			
+	    }
+    	
+	    [Test] 
+        public void  TestBlow() 
+        {
+		    try
+		    {
+                int? i = 5;
+                testServer.blow( "", i );
+			    testClient.blow( "", i );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }			
+	    }
+    	
+	    [Test] 
+        public void  TestExcp5() 
+        {
+		    try
+		    {
+                int? i = 5;
+			    Object value = null;
+			    testServer.throwExcp5( "", i, value );
+			    testClient.throwExcp5( "", i, value );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }			
+	    }
+    	
+	    [Test] 
+        public void  TestExcp6() 
+        {
+		    try
+		    {
+			    int? i = 5;	
+			    Object[] value = null;
+			    testServer.throwExcp6( "", i, value );
+			    testClient.throwExcp6( "", i, value );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }			
+	    }
+    	
+	    [Test] 
+        public void  TestBoolean() 
+        {
+		    try
+		    {
+                bool? b = null;
+			    testServer.p_boolean( b );
+			    testClient.p_boolean( b );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }		
+	    }
+    	
+	    [Test] 
+        public void  TestBooleanArray() 
+        {
+		    try
+		    {
+			    Boolean[] b = null;	
+			    testServer.p_boolean_array( b );
+			    testClient.p_boolean_array( b )	;
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestByte() 
+        {
+		    try
+		    {
+                SByte? a = null;
+			    testServer.p_byte( a );
+			    testClient.p_byte( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestByteArray() 
+        {
+		    try
+		    {
+			    sbyte[] a = null;
+			    testServer.p_byte_array( a );
+			    testClient.p_byte_array( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestShort() 
+        {
+		    try
+		    {
+                short? a  = null;
+			    testServer.p_short( a );
+			    testClient.p_short( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestShortArray() 
+        {
+		    try
+		    {
+                short[] a = null;
+			    testServer.p_short_array( a );
+			    testClient.p_short_array( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    		
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestInt() 
+        {
+		    try
+		    {
+			    int? a  = null;
+			    testServer.p_int( a );
+			    testClient.p_int( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestIntArray() 
+        {
+		    try
+		    {
+			    int[] a  = null;
+			    testServer.p_int_array( a );
+			    testClient.p_int_array( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestLong() 
+        {
+		    try
+		    {
+                long? a  = null;
+			    testServer.p_long( a );
+			    testClient.p_long( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] public void  testLongArray() {
+		    try
+		    {
+			    long[] a  = null;
+			    testServer.p_long_array( a );
+			    testClient.p_long_array( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestFloat() 
+        {
+		    try
+		    {
+			    float? a  = null;
+			    testServer.p_float( a );
+			    testClient.p_float( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestFloatArray() 
+        {
+		    try
+		    {
+			    float[] a  = null;
+			    testServer.p_float_array( a );
+			    testClient.p_float_array( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+    	
+    	
+	    [Test] 
+        public void  TestDouble() 
+        {
+		    try
+		    {
+			    double? a  = null;
+			    testServer.p_double( a );
+			    testClient.p_double( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestDoubleArray() 
+        {
+		    try
+		    {
+			    double[] a  = null;
+			    testServer.p_double_array( a );
+			    testClient.p_double_array( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestString() 
+        {
+		    try
+		    {
+			    String a  = null;
+			    testServer.p_string( a );
+			    testClient.p_string( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestStringArray() 
+        {
+		    try
+		    {
+			    String[] a  = null;
+			    testServer.p_string_array( a );
+			    testClient.p_string_array( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestE1() 
+        {
+		    try
+		    {
+                E1 a  = default( E1 );
+			    testServer.p_E1( a );
+			    testClient.p_E1( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestE1Array() 
+        {
+		    try
+		    {
+			    E1[] a  = null;
+			    testServer.p_E1_array( a );
+			    testClient.p_E1_array( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestS1() 
+        {
+		    try
+		    {
+                S1 a  = default( S1 );
+			    testServer.p_S1( a );
+			    testClient.p_S1( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestS1Array() 
+        {
+		    try
+		    {
+                S1[] a  = null;
+			    testServer.p_S1_array( a );
+			    testClient.p_S1_array( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestS2() 
+        {
+		    try
+		    {
+                S2 a  = default( S2 );
+			    testServer.p_S2( a );
+			    testClient.p_S2( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestS2Array() 
+        {
+		    try
+		    {
+                S2[] a  = null;
+			    testServer.p_S2_array( a );
+			    testClient.p_S2_array( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestBlob() 
+        {
+		    try
+		    {
+			    StrIntHashMap a  = null;
+			    testServer.p_Blob( a );
+			    testClient.p_Blob( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestBlobArray() 
+        {
+		    try
+		    {
+			    StrIntHashMap[] a  = null;
+			    testServer.p_Blob_array( a );
+			    testClient.p_Blob_array( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestObject() 
+        {
+		    try
+		    {
+			    Object a  = null;
+			    testServer.p_object( a );
+			    testClient.p_object( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestObjectArray() 
+        {
+		    try
+		    {
+			    Object[] a  = null;
+			    testServer.p_object_array( a );
+			    testClient.p_object_array( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestObjectStruct() 
+        {
+		    try
+		    {
+                S3 a  = default( S3 );
+			    testServer.p_object_struct( a );
+			    testClient.p_object_struct( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestObjectStructArray() 
+        {
+		    try
+		    {
+                S4 a  = default( S4 );
+			    testServer.p_object_struct_array( a );
+			    testClient.p_object_struct_array( a );
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestAlwaysWork() 
+        {
+		    try
+		    {
+    			
+			    testServer.alwaysWorks();
+			    testClient.alwaysWorks();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestAlwaysFail() 
+        {
+		    try
+		    {
+    			
+			    testServer.alwaysFails();
+			    testClient.alwaysFails();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void TestIsTrue() 
+        {
+		    try
+		    {
+    			
+			    testServer.isTrue();
+			    testClient.isTrue();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestIsFalse() 
+        {
+		    try
+		    {
+    			
+			    testServer.isFalse();
+			    testClient.isFalse();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestM1() 
+        {
+		    try
+		    {
+    			
+			    testServer.m1();
+			    testClient.m1();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestCanM1() 
+        {
+		    try
+		    {
+    			
+			    testServer.can_m1();
+			    testClient.can_m1();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestM2() 
+        {
+		    try
+		    {
+    			
+			    testServer.m2();
+			    testClient.m2();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestCanM2() {
+		    try
+		    {
+			    bool? b = null;
+			    testServer.can_m2(b);
+			    testClient.can_m2(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestM3() 
+        {
+		    try
+		    {
+    			
+			    testServer.m3();
+			    testClient.m3();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  testCanM3() 
+        {
+		    try
+		    {
+			    bool? b = null;
+			    testServer.can_m3(b);
+			    testClient.can_m3(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestM4() 
+        {
+		    try
+		    {
+    			
+			    testServer.m4();
+			    testClient.m4();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestCanM4() 
+        {
+		    try
+		    {
+			    bool? b = null;
+			    testServer.can_m4(b);
+			    testClient.can_m4(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestM5() 
+        {
+		    try
+		    {
+    			
+			    testServer.m5();
+			    testClient.m5();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  testCanM5() {
+		    try
+		    {
+			    sbyte? b = null;
+			    testServer.can_m5(b);
+			    testClient.can_m5(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestM6() 
+        {
+		    try
+		    {
+    			
+			    testServer.m6();
+			    testClient.m6();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestCanM6() 
+        {
+		    try
+		    {
+			    short? b = null;
+			    testServer.can_m6(b);
+			    testClient.can_m6(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestM7() 
+        {
+		    try
+		    {
+    			
+			    testServer.m7();
+			    testClient.m7();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestCanM7() 
+        {
+		    try
+		    {
+			    int? b = null;
+			    testServer.can_m7(b);
+			    testClient.can_m7(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestM8() 
+        {
+		    try
+		    {
+    			
+			    testServer.m8();
+			    testClient.m8();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestCanM8() 
+        {
+		    try
+		    {
+			    long? b = null;
+			    testServer.can_m8(b);
+			    testClient.can_m8(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestM9() 
+        {
+		    try
+		    {
+    			
+			    testServer.m6();
+			    testClient.m6();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestCanM9() 
+        {
+		    try
+		    {
+			    float? b = null;
+			    testServer.can_m9(b);
+			    testClient.can_m9(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestM10() 
+        {
+		    try
+		    {
+    			
+			    testServer.m10();
+			    testClient.m10();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestCanM10() {
+		    try
+		    {
+			    double? b = null;
+			    testServer.can_m10(b);
+			    testClient.can_m10(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestM11() 
+        {
+		    try
+		    {
+    			
+			    testServer.m11();
+			    testClient.m11();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestCanM11() 
+        {
+		    try
+		    {
+			    String b = null;
+			    testServer.can_m11(b);
+			    testClient.can_m11(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestM12() 
+        {
+		    try
+		    {
+    			
+			    testServer.m12();
+			    testClient.m12();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestCanM12() 
+        {
+		    try
+		    {
+			    int? b = null;
+			    testServer.can_m12(b);
+			    testClient.can_m12(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestM13() 
+        {
+		    try
+		    {
+			    int? b = null;
+			    testServer.m13(b);
+			    testClient.m13(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestCanM13() 
+        {
+		    try
+		    {
+			    int? b = null;
+			    testServer.can_m13(b);
+			    testClient.can_m13(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestM14() 
+        {
+		    try
+		    {
+                S1 b = default( S1 );
+			    testServer.m14(b);
+			    testClient.m14(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestCanM14() 
+        {
+		    try
+		    {
+			    int? b = null;
+			    testServer.can_m14(b);
+			    testClient.can_m14(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestM15() 
+        {
+		    try
+		    {
+    		
+			    testServer.m15();
+			    testClient.m15();
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    	
+	    [Test] 
+        public void  TestCanM15() 
+        {
+		    try
+		    {
+                E1 b = default( E1 );
+			    testServer.can_m15(b);
+			    testClient.can_m15(b);
+		    }
+		    catch ( Exception)
+		    {
+			    // TODO Auto-generated catch block
+    			
+		    }
+	    }
+    }
+}
diff --git a/tests/src/test/csharp/etch.tests/TestInheritance.cs b/tests/src/test/csharp/etch.tests/TestInheritance.cs
new file mode 100644
index 0000000..59f44e0
--- /dev/null
+++ b/tests/src/test/csharp/etch.tests/TestInheritance.cs
@@ -0,0 +1,583 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+using org.apache.etch.tests;
+using org.apache.etch.tests.types.Inheritance;
+
+namespace etch.tests
+{
+    [TestFixture]
+    public class TestInheritance
+    {
+        private static RemoteInheritanceServer server;
+        private static ServerFactory listener;
+        
+        [TestFixtureSetUp]
+        public void Setup()
+        {
+            String uri = "tcp://localhost:4003";
+
+            MainInheritanceListener implFactory = new MainInheritanceListener();
+            listener = InheritanceHelper.NewListener(uri, null, implFactory);
+
+            listener.TransportControl(TransportConsts.START_AND_WAIT_UP, 4000);
+
+            MainInheritanceClient client = new MainInheritanceClient();
+            server = InheritanceHelper.NewServer(uri, null, client);
+
+        //    server._TransportControl(Etch.Transport.TransportConsts.START_AND_WAIT_UP, 4000);
+
+            server._StartAndWaitUp(4000);
+        }
+
+        [Test]
+	    public void types() 
+	    {
+		    Assert.AreEqual(true,typeof(S1).IsAssignableFrom(typeof(S1)));
+            Assert.AreEqual(true,typeof(S1).IsAssignableFrom(typeof(S2)));
+		    Assert.AreEqual(true,typeof(S1).IsAssignableFrom(typeof(S3)));
+
+            Assert.AreEqual(false,typeof(S2).IsAssignableFrom(typeof(S1)));
+            Assert.AreEqual(true,typeof(S2).IsAssignableFrom(typeof(S2)));
+		    Assert.AreEqual(true,typeof(S2).IsAssignableFrom(typeof(S3)));
+		
+            Assert.AreEqual(false,typeof(S3).IsAssignableFrom(typeof(S1)));
+            Assert.AreEqual(false,typeof(S3).IsAssignableFrom(typeof(S2)));
+		    Assert.AreEqual(true,typeof(S3).IsAssignableFrom(typeof(S3)));
+		   
+    		Assert.AreEqual(true,typeof(E1).IsAssignableFrom(typeof(E1)));
+            Assert.AreEqual(true,typeof(E1).IsAssignableFrom(typeof(E2)));
+		    Assert.AreEqual(true,typeof(E1).IsAssignableFrom(typeof(E3)));
+		    
+    		Assert.AreEqual(true,typeof(Exception).IsAssignableFrom(typeof(E1)));
+            Assert.AreEqual(true,typeof(Exception).IsAssignableFrom(typeof(E2)));
+            Assert.AreEqual(true,typeof(Exception).IsAssignableFrom(typeof(E3)));
+		 
+    		Assert.AreEqual(false,typeof(E2).IsAssignableFrom(typeof(E1)));
+            Assert.AreEqual(true,typeof(E2).IsAssignableFrom(typeof(E2)));
+		    Assert.AreEqual(true,typeof(E2).IsAssignableFrom(typeof(E3)));
+		    
+    		Assert.AreEqual(false,typeof(E3).IsAssignableFrom(typeof(E1)));
+            Assert.AreEqual(false,typeof(E3).IsAssignableFrom(typeof(E2)));
+		    Assert.AreEqual(true,typeof(E3).IsAssignableFrom(typeof(E3)));
+		   
+	    }
+	
+	
+	    [Test]
+	    public void Construct_S1() 
+	    {
+		    check_s1( new S1(), null, null );
+		
+		    check_s1( new S1( null, null ), null, null );
+		
+		    check_s1( new S1( 1, 2 ), 1, 2 );
+	    }
+	
+	
+	    [Test]
+	    public void construct_s2() 
+	    {
+		    check_s2( new S2(), null, null, null, null );
+    		
+		    check_s2( new S2( null, null, null, null ), null, null, null, null );
+    		
+		    check_s2( new S2( 1, 2, 3, 4 ), 1, 2, 3, 4 );
+	    }
+	
+	
+	    [Test]
+	    public void construct_s3() 
+	    {
+		    check_s3( new S3(), null, null, null, null, null, null );
+    		
+		    check_s3( new S3( null, null, null, null, null, null ),
+			    null, null, null, null, null, null );
+    		
+		    check_s3( new S3( 1, 2, 3, 4, 5, 6 ), 1, 2, 3, 4, 5, 6 );
+	    }
+	
+	
+	    [Test]
+	    public void construct_e1() 
+	    {
+		    check_e1( new E1(), null, null );
+    		
+		    check_e1( new E1( null, null ), null, null );
+    		
+		    check_e1( new E1( 1, 2 ), 1, 2 );
+	    }
+	
+	
+	    [Test]
+	    public void construct_e2() 
+	    {
+		    check_e2( new E2(), null, null, null, null );
+    		
+		    check_e2( new E2( null, null, null, null ), null, null, null, null );
+    		
+		    check_e2( new E2( 1, 2, 3, 4 ), 1, 2, 3, 4 );
+	    }
+	
+	
+	    [Test]
+	    public void construct_e3() 
+	    {
+		    check_e3( new E3(), null, null, null, null, null, null );
+    		
+		    check_e3( new E3( null, null, null, null, null, null ),
+			    null, null, null, null, null, null );
+    		
+		    check_e3( new E3( 1, 2, 3, 4, 5, 6 ), 1, 2, 3, 4, 5, 6 );
+	    }
+	
+	
+	    [Test]
+	    public void assign_s1() 
+	    {
+		    S1 v = new S1( 1, 2 ); 
+            
+            check_s1( v, 1, 2 );
+    		
+		    v.a = null;            check_s1( v, null, 2 );
+		    v.a = 3;               check_s1( v, 3, 2 );
+		    v.SetA( null );        check_s1( v, null, 2 );
+		    v.SetA( 4 );           check_s1( v, 4, 2 );
+    		
+		    v.b = null;            check_s1( v, 4, null );
+		    v.b = 5;               check_s1( v, 4, 5 );
+		    v.SetB( null );        check_s1( v, 4, null );
+		    v.SetB( 6 );           check_s1( v, 4, 6 );
+	    }
+	
+	
+	    [Test]
+	    public void assign_s2()
+	    {
+		    S2 v = new S2( 1, 2, 3, 4 ); 
+            
+            check_s2( v, 1, 2, 3, 4 );
+    		
+		    v.a = null;                  check_s2( v, null, 2, 3, 4 );
+		    v.a = 5;                     check_s2( v, 5, 2, 3, 4 );
+		    v.SetA( null );              check_s2( v, null, 2, 3, 4 );
+		    v.SetA( 6 );                 check_s2( v, 6, 2, 3, 4 );
+    		
+		    v.b = null;                  check_s2( v, 6, null, 3, 4 );
+		    v.b = 7;                     check_s2( v, 6, 7, 3, 4 );
+		    v.SetB( null );              check_s2( v, 6, null, 3, 4 );
+		    v.SetB( 8 );                 check_s2( v, 6, 8, 3, 4 );
+    		
+		    v.c = null;                  check_s2( v, 6, 8, null, 4 );
+		    v.c = 9;                     check_s2( v, 6, 8, 9, 4 );
+		    v.SetC( null );              check_s2( v, 6, 8, null, 4 );
+		    v.SetC( 10 );                check_s2( v, 6, 8, 10, 4 );
+    		
+		    v.d = null;                  check_s2( v, 6, 8, 10, null );
+		    v.d = 11;                    check_s2( v, 6, 8, 10, 11 );
+		    v.SetD( null );              check_s2( v, 6, 8, 10, null );
+		    v.SetD( 12 );                check_s2( v, 6, 8, 10, 12 );
+	    }
+	
+	
+	    [Test]
+	    public void assign_s3() 
+	    {
+		    S3 v = new S3( 1, 2, 3, 4, 5, 6 ); 
+            check_s3( v, 1, 2, 3, 4, 5, 6 );
+    		
+		    v.a = null;                        check_s3( v, null, 2, 3, 4, 5, 6 );
+		    v.a = 7;                           check_s3( v, 7, 2, 3, 4, 5, 6 );
+		    v.SetA( null );                    check_s3( v, null, 2, 3, 4, 5, 6 );
+		    v.SetA( 8 );                       check_s3( v, 8, 2, 3, 4, 5, 6 );
+    		
+		    v.b = null;                        check_s3( v, 8, null, 3, 4, 5, 6 );
+		    v.b = 9;                           check_s3( v, 8, 9, 3, 4, 5, 6 );
+		    v.SetB( null );                    check_s3( v, 8, null, 3, 4, 5, 6 );
+		    v.SetB( 10 );                      check_s3( v, 8, 10, 3, 4, 5, 6 );
+    		
+		    v.c = null;                        check_s3( v, 8, 10, null, 4, 5, 6 );
+		    v.c = 11;                          check_s3( v, 8, 10, 11, 4, 5, 6 );
+		    v.SetC( null );                    check_s3( v, 8, 10, null, 4, 5, 6 );
+		    v.SetC( 12 );                      check_s3( v, 8, 10, 12, 4, 5, 6 );
+    		
+		    v.d = null;                        check_s3( v, 8, 10, 12, null, 5, 6 );
+		    v.d = 13;                          check_s3( v, 8, 10, 12, 13, 5, 6 );
+		    v.SetD( null );                    check_s3( v, 8, 10, 12, null, 5, 6 );
+		    v.SetD( 14 );                      check_s3( v, 8, 10, 12, 14, 5, 6 );
+    		
+		    v.e = null;                        check_s3( v, 8, 10, 12, 14, null, 6 );
+		    v.e = 15;                          check_s3( v, 8, 10, 12, 14, 15, 6 );
+		    v.SetE( null );                    check_s3( v, 8, 10, 12, 14, null, 6 );
+		    v.SetE( 16 );                      check_s3( v, 8, 10, 12, 14, 16, 6 );
+    		
+		    v.f = null;                        check_s3( v, 8, 10, 12, 14, 16, null );
+		    v.f = 17;                          check_s3( v, 8, 10, 12, 14, 16, 17 );
+		    v.SetF( null );                    check_s3( v, 8, 10, 12, 14, 16, null );
+		    v.SetF( 18 );                      check_s3( v, 8, 10, 12, 14, 16, 18 );
+	    }
+	
+	
+	   [Test]
+	    public void tostring() 
+	    {
+		    Assert.AreEqual(
+			    "S1(a=1; b=2)",
+			    new S1( 1, 2 ).ToString() );
+    		
+		    Assert.AreEqual(
+			    "S2(S1(a=1; b=2); c=3; d=4)",
+			    new S2( 1, 2, 3, 4 ).ToString() );
+    		
+		    Assert.AreEqual(
+			    "S3(S2(S1(a=1; b=2); c=3; d=4); e=5; f=6)",
+			    new S3( 1, 2, 3, 4, 5, 6 ).ToString() );
+    		
+		    Assert.AreEqual(
+                "a=1; b=2",
+			    new E1( 1, 2 ).GetMessage() );
+    		
+		    Assert.AreEqual(
+                "a=1; b=2; c=3; d=4",
+			    new E2( 1, 2, 3, 4 ).GetMessage() );
+    		
+		    Assert.AreEqual(
+                "a=1; b=2; c=3; d=4; e=5; f=6",
+			    new E3( 1, 2, 3, 4, 5, 6 ).GetMessage() );
+	    }
+
+	    private void check_s1( S1 v, int? a, int? b )
+	    {
+    		
+            Assert.AreEqual( a, v.a );
+		    Assert.AreEqual( a, v.GetA() );
+    		
+		    Assert.AreEqual( b, v.b );
+		    Assert.AreEqual( b, v.GetB() );
+	    }
+
+	    private void check_s2( S2 v, int? a, int? b, int? c, int? d )
+	    {
+		    check_s1( v, a, b );
+    		
+		    Assert.AreEqual( c, v.c );
+		    Assert.AreEqual( c, v.GetC() );
+    		
+		    Assert.AreEqual( d, v.d );
+		    Assert.AreEqual( d, v.GetD() );
+	    }
+
+	    private void check_s3( S3 v, int? a, int? b, int? c, int? d,
+		    int? e, int? f )
+	    {
+		    check_s2( v, a, b, c, d );
+    		
+		    Assert.AreEqual( e, v.e );
+		    Assert.AreEqual( e, v.GetE() );
+    		
+		    Assert.AreEqual( f, v.f );
+		    Assert.AreEqual( f, v.GetF() );
+	    }
+
+	    private void check_e1( E1 v, int? a, int? b )
+	    {
+		    Assert.AreEqual( a, v.a );
+		    Assert.AreEqual( a, v.GetA() );
+    		
+		    Assert.AreEqual( b, v.b );
+		    Assert.AreEqual( b, v.GetB() );
+	    }
+
+	    private void check_e2( E2 v, int? a, int? b, int? c, int? d )
+	    {
+		    check_e1( v, a, b );
+    		
+		    Assert.AreEqual( c, v.c );
+		    Assert.AreEqual( c, v.GetC() );
+    		
+		    Assert.AreEqual( d, v.d );
+		    Assert.AreEqual( d, v.GetD() );
+	    }
+
+	    private void check_e3( E3 v, int? a, int? b, int? c, int? d,
+		    int? e, int? f )
+	    {
+		    check_e2( v, a, b, c, d );
+    		
+		    Assert.AreEqual( e, v.e );
+		    Assert.AreEqual( e, v.GetE() );
+    		
+		    Assert.AreEqual( f, v.f );
+		    Assert.AreEqual( f, v.GetF() );
+	    }
+
+	
+	    [Test]
+	    public void test_s1() 
+	    {
+		    do_s1( new S1( 1, 2 ), new S1Compare() );
+		    do_s1( new S1( 9, 8 ), new S1Compare() );
+	    }
+
+	
+	    [Test]
+	    public void test_s2() 
+	    {
+		    do_s2( new S2( 1, 2, 3, 4 ), new S2Compare() );
+		    do_s2( new S2( 9, 8, 7, 6 ), new S2Compare() );
+	    }
+
+
+	    [Test]
+	    public void test_s3() 
+	    {
+		    do_s3( new S3( 1, 2, 3, 4, 5, 6 ), new S3Compare() );
+		    do_s3( new S3( 9, 8, 7, 6, 5, 4 ), new S3Compare() );
+	    } 
+	
+	    interface CompareObj<T>
+	    {
+    		
+		    void compare( T a, T b );
+	    }
+	
+	
+	
+	/**
+	 * Class to compare one S2 to another.
+	 */
+	 class S2Compare : CompareObj<object>
+	{
+		public void compare( object a, object b )
+		{
+            Assert.AreEqual(typeof(S2), a.GetType());
+			Assert.AreEqual( typeof(S2), b.GetType() );
+            S2 a1 = (S2)a;
+            S2 b1 = (S2)b;
+			Assert.AreEqual( a1.a, b1.a );
+			Assert.AreEqual( a1.b, b1.b );
+			Assert.AreEqual( a1.c, b1.c );
+			Assert.AreEqual( a1.d, b1.d );
+		}
+	} 
+
+	/**
+	 * Class to compare one S3 to another.
+	 */
+	class S3Compare : CompareObj<object>
+	{
+		public void compare( object a, object b )
+		{
+			Assert.AreEqual( typeof(S3), a.GetType() );
+			Assert.AreEqual( typeof(S3), b.GetType() );
+            S3 a1 = (S3)a;
+            S3 b1 = (S3)b;
+			Assert.AreEqual( a1.a, b1.a );
+			Assert.AreEqual( a1.b, b1.b );
+			Assert.AreEqual( a1.c, b1.c );
+			Assert.AreEqual( a1.d, b1.d );
+			Assert.AreEqual( a1.e, b1.e );
+			Assert.AreEqual( a1.f, b1.f );
+		}
+	} 
+	
+	 
+	
+	 class AS2Compare : CompareObj<object[]>
+	{
+		
+		public AS2Compare( CompareObj<object> cmp )
+		{
+			this.cmp = cmp;
+		}
+		
+		private CompareObj<object> cmp;
+
+		
+		public void compare( object[] a, object[] b )
+		{
+            S2[] a1 = (S2[])a;
+            S2[] b1 = (S2[])b;
+			Assert.AreEqual( a1.Length, b1.Length );
+			for (int i = 0; i < a.Length; i++)
+				cmp.compare( a1[i], b1[i] );
+		}
+	}
+	
+	 class AS3Compare : CompareObj<object[]>
+	{
+		
+		public AS3Compare( CompareObj<object> cmp )
+		{
+			this.cmp = cmp;
+		}
+		
+		private  CompareObj<object> cmp;
+
+		
+		public void compare( object[] a, object[] b )
+		{
+			Assert.AreEqual( a.Length, b.Length );
+			for (int i = 0; i < a.Length; i++)
+				cmp.compare( a[i], b[i] );
+		}
+	} 
+
+	/////////////
+	// HELPERS //
+	/////////////
+
+
+        private void do_obj(object v, CompareObj<object> cmp)
+	    {
+		    // test an object both by itself and as an array.
+    		
+		    cmp.compare( v,server.f1( v ) );
+
+            object[] a = { v };
+	        CompareObj<object[]> acmp = new AObjectCompare( cmp );
+    		
+		    acmp.compare( a, server.f5( a ) );  
+	    }
+
+  
+	private void do_s1( S1 v, CompareObj<object> cmp )
+	{
+		// test an S1 both by itself and as an array.
+		// also test each of those as an object.
+		
+		cmp.compare( v, server.f2( v ) );
+		do_obj( v, cmp );
+		
+		S1[] a = { v };
+        CompareObj<object[]> acmp = new AS1Compare(cmp);
+
+		acmp.compare( a, server.f6( a ) );
+//		do_obj( a, acmp );  
+	}
+
+    /**
+ * Class to compare one S1 to another.
+ */
+    class S1Compare : CompareObj<object>
+    {
+        public void compare(object a, object b)
+        {
+            Assert.AreEqual(typeof(S1), a.GetType());
+            Assert.AreEqual(typeof(S1), b.GetType());
+            S1 a1 = (S1)a;
+            S1 b1 = (S1)b;
+            Assert.AreEqual(a1.a, b1.a);
+            Assert.AreEqual(a1.b, b1.b);
+        }
+    }
+
+    class AObjectCompare : CompareObj<Object[]>
+    {
+
+        public AObjectCompare(CompareObj<Object> cmp)
+        {
+            this.cmp = cmp;
+        }
+
+        private CompareObj<Object> cmp;
+
+
+        public void compare(Object[] a, Object[] b)
+        {
+            Assert.AreEqual(a.Length, b.Length);
+            for (int i = 0; i < a.Length; i++)
+                cmp.compare(a[i], b[i]);
+        }
+    }
+
+    class AS1Compare : CompareObj<object[]>
+    {
+
+        public AS1Compare(CompareObj<object> cmp)
+        {
+            this.cmp = cmp;
+        }
+
+        private CompareObj<object> cmp;
+
+
+        public void compare(object[] a, object[] b)
+        {
+            S1[] a1 = (S1[])a;
+            S1[] b1 = (S1[])b;
+            Assert.AreEqual(a1.Length, b1.Length);
+            for (int i = 0; i < a1.Length; i++)
+                cmp.compare(a1[i], b1[i]);
+        }
+    }
+
+
+	
+	 private void do_s2( S2 v, CompareObj<object> cmp )
+	{
+		// test an S2 both by itself and as an array.
+		// also test the S2 as an S1, and the S2 array
+		// as an object.
+		
+		cmp.compare( v, server.f3( v ) );
+		do_s1( v, cmp );
+		
+		S2[] a = { v };
+		CompareObj<object[]> acmp = new AS2Compare( cmp );
+
+		acmp.compare( a, server.f7( a ) );
+	//	do_obj( a, acmp );
+	}
+
+	
+	private void do_s3( S3 v, CompareObj<object> cmp )
+	{
+		// test an S3 both by itself and as an array.
+		// also test the S3 as an S2, and the S3 array
+		// as an object.
+		
+		cmp.compare( v, server.f4( v ) );
+		do_s2( v, cmp );
+		
+		S3[] a = { v };
+		CompareObj<object[]> acmp = new AS3Compare( cmp );
+
+		acmp.compare( a, server.f8( a ) );
+	//	do_obj( a, acmp );
+	} 
+
+	
+	  [TestFixtureTearDown]
+	public void Dispose() 
+	{
+		if (server != null)
+			server._StopAndWaitDown( 4000 );
+        if (listener != null)
+            listener.TransportControl(TransportConsts.STOP_AND_WAIT_DOWN, 4000);
+	}
+}
+
+
+
+    }
diff --git a/tests/src/test/csharp/etch.tests/TestMainTest1Client.cs b/tests/src/test/csharp/etch.tests/TestMainTest1Client.cs
new file mode 100644
index 0000000..4c1afb9
--- /dev/null
+++ b/tests/src/test/csharp/etch.tests/TestMainTest1Client.cs
@@ -0,0 +1,720 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Threading;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+using org.apache.etch.tests;
+using org.apache.etch.tests.types.Test1;
+
+namespace etch.tests
+{
+    [TestFixture]
+    public class TestMainTest1Client
+    {
+        // Settings
+        //--------------------------------------------------------------------------
+
+        // Instance of the class.
+        private ImplTest1Client myMainTestClient;
+
+        // Instances of arguments types
+        private bool? myBool;
+        private sbyte? myByte;
+        private short? myShort;
+        private int? myInt;
+        private long? myLong;
+        private float? myFloat;
+        private double? myDouble;
+        private Object myObj;
+        private String myString;
+        private StrIntHashMap myMap;
+        private E1? myE1;
+        private S1 myS1;
+        private S2 myS2;
+        private S3 myS3;
+        private S4 myS4;
+        private Boolean[] myBools;
+        private sbyte[] myBytes;
+        private short[] myShorts;
+        private int[] myInts;
+        private long[] myLongs;
+        private float[] myFloats;
+        private double[] myDoubles;
+        private Object[] myObjs;
+        private String[] myStrings;
+        private StrIntHashMap[] myMaps;
+        private E1[] myE1s;
+        private S1[] myS1s;
+        private S2[] myS2s;
+
+        // Maintenance
+	    // -------------------------------------------------------------------------
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestMain" );
+        }
+
+	    [SetUp]
+	    public void SetUp()
+	    {
+            this.myMainTestClient = new ImplTest1Client( null);
+	    }
+
+
+	    // Tests
+	    //--------------------------------------------------------------------------
+
+	    [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void NothingMethod()
+	    {
+		    this.myMainTestClient.nothing();
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void IncrMethod()
+	    {
+		    this.myInt = this.myMainTestClient.incr(this.myInt);
+	    }
+
+	    [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void addMethod()
+	    {
+		    this.myInt = this.myMainTestClient.add(this.myInt, this.myInt);
+	    }
+
+        [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void subMethod()
+	    {
+		    this.myInt = this.myMainTestClient.sub(this.myInt, this.myInt);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void sumMethod()
+	    {
+		    this.myInt = this.myMainTestClient.sum(this.myInts);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void transMethod()
+	    {
+		    this.myInt = this.myMainTestClient.trans(this.myE1, this.myInt);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void distMethod()
+	    {
+		    this.myDouble = this.myMainTestClient.dist(this.myS1, this.myS1);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void fillMethod()
+	    {
+		    this.myInts = this.myMainTestClient.fill(this.myInt, this.myInt);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void fillObjectMethod()
+	    {
+		    this.myObjs = this.myMainTestClient.fillObject(this.myInt, this.myObj);
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void blowMethod()
+	    {
+		    this.myMainTestClient.blow(this.myString, this.myInt);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void beetsMethod()
+	    {
+		    this.myInt = this.myMainTestClient.beets(this.myE1);
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void throwExcp5Method()
+	    {
+		    this.myMainTestClient.throwExcp5(this.myString, this.myInt, this.myObj);
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void throwExcp6Method()
+	    {
+		    this.myMainTestClient.throwExcp6(this.myString, this.myInt, this.myObjs);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_booleanMethod()
+	    {
+		    this.myBool = this.myMainTestClient.p_boolean(this.myBool);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_boolean_arrayMethod()
+	    {
+		    this.myBools = this.myMainTestClient.p_boolean_array(this.myBools);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_byteMethod()
+	    {
+		    this.myByte = this.myMainTestClient.p_byte(this.myByte);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_byte_arrayMethod()
+	    {
+		    this.myBytes = this.myMainTestClient.p_byte_array(this.myBytes);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_shortMethod()
+	    {
+		    this.myShort = this.myMainTestClient.p_short(this.myShort);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_short_arrayMethod()
+	    {
+		    this.myShorts = this.myMainTestClient.p_short_array(this.myShorts);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_intMethod()
+	    {
+		    this.myInt = this.myMainTestClient.p_int(this.myInt);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_int_arrayMethod()
+	    {
+		    this.myInts = this.myMainTestClient.p_int_array(this.myInts);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_longMethod()
+	    {
+		    this.myLong = this.myMainTestClient.p_long(this.myLong);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_long_arrayMethod()
+	    {
+		    this.myLongs = this.myMainTestClient.p_long_array(this.myLongs);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_floatMethod()
+	    {
+		    this.myFloat = this.myMainTestClient.p_float(this.myFloat);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_float_arrayMethod()
+	    {
+		    this.myFloats = this.myMainTestClient.p_float_array(this.myFloats);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_doubleMethod()
+	    {
+		    this.myDouble = this.myMainTestClient.p_double(this.myDouble);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_double_arrayMethod()
+	    {
+		    this.myDoubles = this.myMainTestClient.p_double_array(this.myDoubles);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_stringMethod()
+	    {
+		    this.myString = this.myMainTestClient.p_string(this.myString);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_string_arrayMethod()
+	    {
+		    this.myStrings = this.myMainTestClient.p_string_array(this.myStrings);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_E1Method()
+	    {
+		    this.myE1 = this.myMainTestClient.p_E1(this.myE1);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_E1_arrayMethod()
+	    {
+		    this.myE1s = this.myMainTestClient.p_E1_array(this.myE1s);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_S1Method()
+	    {
+		     this.myS1 = this.myMainTestClient.p_S1(this.myS1);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_S1_arrayMethod()
+	    {
+		     this.myS1s = this.myMainTestClient.p_S1_array(this.myS1s);
+
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_S2Method()
+	    {
+		    this.myS2 = this.myMainTestClient.p_S2(this.myS2);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_S2_arrayMethod()
+	    {
+		    this.myS2s = this.myMainTestClient.p_S2_array(this.myS2s);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_BlobMethod()
+	    {
+		    this.myMap = this.myMainTestClient.p_Blob(this.myMap);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_Blob_ArrayMethod()
+	    {
+		    this.myMaps = this.myMainTestClient.p_Blob_array(this.myMaps);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_objectMethod()
+	    {
+		    this.myObj = this.myMainTestClient.p_object(this.myObj);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_object_arrayMethod()
+	    {
+		    this.myMainTestClient.p_object_array(null);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_object_structMethod()
+	    {
+		    this.myS3 = this.myMainTestClient.p_object_struct(this.myS3);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void p_object_struct_arrayMethod()
+	    {
+		    this.myS4 = this.myMainTestClient.p_object_struct_array(this.myS4);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void alwaysWordsMethod()
+	    {
+		    this.myInt = this.myMainTestClient.alwaysWorks();
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void isTrueMethod()
+	    {
+		    this.myBool = this.myMainTestClient.isTrue();
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void alwaysFailsMethod()
+	    {
+		    this.myMainTestClient.alwaysFails();
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void isFalseMethod()
+	    {
+		    this.myBool = this.myMainTestClient.isFalse();
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void m1Method()
+	    {
+		    this.myMainTestClient.m1();
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void can_m1Method()
+	    {
+		    this.myBool = this.myMainTestClient.can_m1();
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void m2Method()
+	    {
+		    this.myMainTestClient.m2();
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void can_m2Method()
+	    {
+		    this.myBool = this.myMainTestClient.can_m2(null);
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void m3Method()
+	    {
+		    this.myMainTestClient.m3();
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void can_m3Method()
+	    {
+		    this.myBool = this.myMainTestClient.can_m3(null);
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void m4Method()
+	    {
+		    this.myMainTestClient.m4();
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void can_m4Method()
+	    {
+		    this.myBool = this.myMainTestClient.can_m4(this.myBool);
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void m5Method()
+	    {
+		    this.myMainTestClient.m5();
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void can_m5Method()
+	    {
+		    this.myBool = this.myMainTestClient.can_m5(this.myByte);
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void m7Method()
+	    {
+		    this.myMainTestClient.m7();
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void can_m7Method()
+	    {
+		    this.myBool = this.myMainTestClient.can_m7(this.myInt);
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void m8Method()
+	    {
+		    this.myMainTestClient.m8();
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void can_m8Method()
+	    {
+		    this.myBool = this.myMainTestClient.can_m8(this.myLong);
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void m9Method()
+	    {
+		    this.myMainTestClient.m9();
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void can_m9Method()
+	    {
+		    this.myBool = this.myMainTestClient.can_m9(this.myFloat);
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void m10Method()
+	    {
+		    this.myMainTestClient.m10();
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void can_m10Method()
+	    {
+		    this.myBool = this.myMainTestClient.can_m10(this.myDouble);
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void m11Method()
+	    {
+		    this.myMainTestClient.m11();
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void can_m11Method()
+	    {
+		    this.myBool = this.myMainTestClient.can_m11(this.myString);
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void m12Method()
+	    {
+		    this.myMainTestClient.m12();
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void can_m12Method()
+	    {
+		    this.myBool = this.myMainTestClient.can_m12(this.myInt);
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void m13Method()
+	    {
+		    this.myMainTestClient.m13(this.myInt);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void can_m13Method()
+	    {
+		    this.myBool = this.myMainTestClient.can_m13(this.myInt);
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void m14Method()
+	    {
+		    this.myMainTestClient.m14(this.myS1);
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void can_m14Method()
+	    {
+		    this.myBool = this.myMainTestClient.can_m14(this.myInt);
+	    }
+
+        [Test]
+        [ExpectedException( typeof( NotSupportedException ) )]
+	    public void m15Method()
+	    {
+		    this.myMainTestClient.m15();
+	    }
+
+	    [Test]
+	    [ExpectedException( typeof( NotSupportedException ) )]
+	    public void can_m15Method()
+	    {
+		    this.myBool = this.myMainTestClient.can_m15(this.myE1);
+	    }
+
+        //[Test]
+        public void MainServiceListenerAndClient()
+        {
+            ThreadClient client = new ThreadClient();
+            ThreadListener listener = new ThreadListener();
+
+            // start the listener & wait until it has started
+            ( new Thread( new ThreadStart( listener.Run ) ) ).Start();
+            commonLock.WaitUntilEq( LISTENER_STARTED, 4000 );
+
+            // start the client
+            ( new Thread( new ThreadStart( client.Run ) ) ).Start();
+            commonLock.WaitUntilEq( CLIENT_STARTED, 4000 );
+
+            Console.WriteLine( "am i coming here?" );
+
+            if ( client.HasErrors() || listener.HasErrors() )
+                Assert.Fail();
+        }
+
+        public static Monitor<string> commonLock = new Monitor<string>( "common lock", null );
+
+        private class ThreadClient
+        {
+            /// <summary>
+            /// Record when an error occurs with client
+            /// </summary>
+            private Boolean myHasErrors;
+
+            public ThreadClient()
+            {
+                myHasErrors = false;
+            }
+
+            public void Run()
+            {
+                try
+                {
+                    MainTest1Client.Main( null );
+                }
+                catch ( Exception e )
+                {
+                    Console.WriteLine( e );
+                    myHasErrors = true;
+                }
+                TestMainTest1Client.commonLock.Set( TestMainTest1Client.CLIENT_STARTED );
+
+            }
+
+            public Boolean HasErrors()
+            {
+                return this.myHasErrors;
+            }
+        } 
+
+        private class SimpleThreadListener
+        {
+            private Boolean myHasErrors;
+
+            public SimpleThreadListener()
+            {
+                myHasErrors = false;
+            }
+
+            public void Run()
+            {
+                try
+                {
+   //                 MainTest1Listener.Main( null );  
+                }
+                catch ( Exception e )
+                {
+                    Console.WriteLine( e );
+                    myHasErrors = true;
+                }
+            }
+
+            public Boolean HasErrors()
+            {
+                return this.myHasErrors;
+            }
+        }
+
+        private class ThreadListener
+        {
+            private Boolean myHasErrors;
+
+            public ThreadListener()
+            {
+                myHasErrors = false;
+            }
+
+            public void Run()
+            {
+                SimpleThreadListener listener = new SimpleThreadListener();
+
+                try
+                {
+                    // start listener
+                    Thread t = ( new Thread( new ThreadStart( listener.Run ) ) );
+                    t.Start();
+                    TestMainTest1Client.commonLock.Set( TestMainTest1Client.LISTENER_STARTED );
+                }
+                catch ( Exception )
+                {
+                    // do nothing
+                }
+
+            }
+
+
+            public Boolean HasErrors()
+            {
+                return this.myHasErrors;
+            }
+        }
+
+        public const string LISTENER_STARTED = "Listener_Started";
+        public const string CLIENT_STARTED = "Client_Started";
+    }
+}
diff --git a/tests/src/test/csharp/etch.tests/TestMainTest1Listener.cs b/tests/src/test/csharp/etch.tests/TestMainTest1Listener.cs
new file mode 100644
index 0000000..ddc7dcf
--- /dev/null
+++ b/tests/src/test/csharp/etch.tests/TestMainTest1Listener.cs
@@ -0,0 +1,71 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using NUnit.Framework;
+using org.apache.etch.tests;
+
+namespace etch.tests
+{
+    public class TestMainTest1Listener
+    {
+        [Test]
+        public void NewTestServerMethod()
+        {
+            MainTest1Listener m = new MainTest1Listener();
+            Object o = m.NewTest1Server( null );
+            Assert.IsNotNull( o );
+            Assert.IsTrue( o is ImplTest1Server );
+        }
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine( "TestListener" );
+        }
+
+        private class ListenerThread
+        {
+            private Boolean myHasErrors;
+
+            public ListenerThread()
+            {
+                myHasErrors = false;
+            }
+
+            public void Run()
+            {
+                try
+                {
+    //                MainTest1Listener.Main( null );
+                }
+                catch ( Exception e )
+                {
+                    Console.WriteLine( e );
+                    myHasErrors = false;
+                }
+            }
+
+            public Boolean HasErrors()
+            {
+                return myHasErrors;
+            }
+        }
+    }
+}
diff --git a/tests/src/test/csharp/etch.tests/TestMixin.cs b/tests/src/test/csharp/etch.tests/TestMixin.cs
new file mode 100644
index 0000000..dbcc576
--- /dev/null
+++ b/tests/src/test/csharp/etch.tests/TestMixin.cs
@@ -0,0 +1,363 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System.Collections.Generic;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using NUnit.Framework;
+using org.apache.etch.tests;
+using org.apache.etch.tests.types.Bar;
+using org.apache.etch.tests.types.Baz;
+using org.apache.etch.tests.types.Foo;
+
+namespace etch.tests
+{
+     [TestFixture]
+    public class TestMixin
+    {
+      [Test]
+	public void Method_testBaz() 
+	{
+		
+		    BazData bazData = null;
+
+		    Baz baz = null;
+		    if (baz != null)
+		    {
+		        baz.baz1(bazData);
+		    }
+		
+	}
+	
+	
+	[Test]
+	public void Method_testBazClient() 
+	{
+		BazData bazData = null;
+		
+		BazClient bazClient = null;
+		if (bazClient != null)
+		{
+			bazClient.baz1( bazData );
+			bazClient.baz3( bazData );
+		}
+		
+		Baz baz = bazClient;
+	}
+	
+	
+	[Test]
+	public void Method_testBazServer() 
+	{
+		BazData bazData = null;
+		
+		BazServer bazServer = null;
+		if (bazServer != null)
+		{
+			bazServer.baz1( bazData );
+			bazServer.baz2( bazData );
+		}
+		
+		Baz baz = bazServer;
+	}
+	
+	
+	[Test]
+	public void Method_testBar() 
+	{
+		BarData barData = null;
+		BazData bazData = null;
+		
+		Bar bar = null;
+		if (bar != null)
+		{
+			bar.bar1( barData );
+			bar.baz1( bazData );
+		}
+		
+		Baz baz = bar;
+	}
+	
+	
+	[Test]
+	public void Method_testBarClient() 
+	{
+		BarData barData = null;
+		BazData bazData = null;
+		
+		BarClient barClient = null;
+		if (barClient != null)
+		{
+			barClient.bar1( barData );
+			barClient.bar3( barData );
+			barClient.baz1( bazData );
+			barClient.baz3( bazData );
+		}
+
+		BazClient bazClient = barClient;
+		Bar bar = barClient;
+		Baz baz = barClient;
+	}
+	
+	
+	[Test]
+	public void Method_testBarServer() 
+	{
+		BarData barData = null;
+		BazData bazData = null;
+		
+		BarServer barServer = null;
+		if (barServer != null)
+		{
+			barServer.bar1( barData );
+			barServer.bar2( barData );
+			barServer.baz1( bazData );
+			barServer.baz2( bazData );
+		}
+
+		BazServer bazServer = barServer;
+		Bar bar = barServer;
+		Baz baz = barServer;
+	}
+	
+	
+	[Test]
+	public void Method_testFoo() 
+	{
+		FooData fooData = null;
+		BarData barData = null;
+		BazData bazData = null;
+		
+		Foo foo = null;
+		if (foo != null)
+		{
+			foo.foo1( fooData );
+			foo.bar1( barData );
+			foo.baz1( bazData );
+		}
+		
+		Bar bar = foo;
+		Baz baz = foo;
+	}
+	
+	
+	[Test]
+	public void testFooClient() 
+	{
+		FooData fooData = null;
+		BarData barData = null;
+		BazData bazData = null;
+		
+		FooClient fooClient = null;
+		if (fooClient != null)
+		{
+			fooClient.foo1( fooData );
+			fooClient.foo3( fooData );
+			fooClient.bar1( barData );
+			fooClient.bar3( barData );
+			fooClient.baz1( bazData );
+			fooClient.baz3( bazData );
+		}
+		
+		BarClient barClient = fooClient;
+		BazClient bazClient = fooClient;
+		Foo foo = fooClient;
+		Bar bar = fooClient;
+		Baz baz = fooClient;
+	}
+	
+	
+	[Test]
+	public void testFooServer() 
+	{
+		FooData fooData = null;
+		BarData barData = null;
+		BazData bazData = null;
+		
+		FooServer fooServer = null;
+		if (fooServer != null)
+		{
+			fooServer.foo1( fooData );
+			fooServer.foo2( fooData );
+			fooServer.bar1( barData );
+			fooServer.bar2( barData );
+			fooServer.baz1( bazData );
+			fooServer.baz2( bazData );
+		}
+		
+		BarServer barServer = fooServer;
+		BazServer bazServer = fooServer;
+		Foo foo = fooServer;
+		Bar bar = fooServer;
+		Baz baz = fooServer;
+	}
+	
+	
+    [Test]
+	public void Method_testValueFactoryBazGetTypes() 
+	{
+        DefaultValueFactory vf = new ValueFactoryBaz("none:");
+		List<XType> atypes = (List<XType>)vf.GetTypes();
+		
+		List<XType> etypes = new List<XType>();
+
+
+        etypes.Add(vf.get_mt__Etch_RuntimeException());
+        etypes.Add(vf.Get_mt__Etch_List());
+        etypes.Add(vf.Get_mt__Etch_Map());
+        etypes.Add(vf.Get_mt__Etch_Datetime());
+        etypes.Add(vf.get_mt__Etch_AuthException());
+        etypes.Add(vf.get_mt__exception());
+		etypes.Add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_BazTable );
+		etypes.Add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_BazData );
+		etypes.Add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz1);
+		etypes.Add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz1 );
+		etypes.Add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz2 );
+		etypes.Add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz2 );
+		etypes.Add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz3 );
+		etypes.Add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz3 );
+        
+       
+       
+		
+		
+        Assert.AreEqual(etypes, atypes);
+		foreach (XType type in etypes )
+			testGetType( vf, type );
+	}
+	
+	private void testGetType( ValueFactory vf, XType type )
+	{
+	
+        Assert.AreSame(type, vf.GetType(type.Id));
+	
+        Assert.AreSame(type,vf.GetType(type.Name));
+	}
+
+	
+	[Test]
+	public void Method_testValueFactoryBarGetTypes() 
+	{
+        DefaultValueFactory vf = new ValueFactoryBar("none:");
+		List<XType> atypes = (List<XType>)vf.GetTypes();
+		
+		List<XType> etypes = new List<XType>();
+
+
+        etypes.Add(vf.get_mt__Etch_RuntimeException());
+        etypes.Add(vf.Get_mt__Etch_List());
+        etypes.Add(vf.Get_mt__Etch_Map());
+        etypes.Add(vf.Get_mt__Etch_Datetime());
+        etypes.Add(vf.get_mt__Etch_AuthException());
+        etypes.Add(vf.get_mt__exception());
+        
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar_BarTable);
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar_BarData);
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar_bar1);
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar__result_bar1);
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar_bar2);
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar__result_bar2);
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar_bar3);
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar__result_bar3);
+
+        
+       
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz_BazTable);
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz_BazData);
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz1);
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz1);
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz2);
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz2);
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz3);
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz3);
+		
+		Assert.AreEqual( etypes, atypes );
+		foreach (XType type in etypes )
+			testGetType( vf, type );
+	}
+	
+	
+	[Test]
+	public void Method_testValueFactoryFooGetTypes() 
+	{
+        DefaultValueFactory vf = new ValueFactoryFoo("none:");
+		List<XType> atypes = (List<XType>)vf.GetTypes();
+		
+		List<XType> etypes = new List<XType>();
+
+        etypes.Add(vf.get_mt__Etch_RuntimeException());
+        etypes.Add(vf.Get_mt__Etch_List());
+        etypes.Add(vf.Get_mt__Etch_Map());
+        etypes.Add(vf.Get_mt__Etch_Datetime());
+        etypes.Add(vf.get_mt__Etch_AuthException());
+        etypes.Add(vf.get_mt__exception());
+            
+        etypes.Add(ValueFactoryFoo._mt_org_apache_etch_tests_Foo_FooTable);
+        etypes.Add(ValueFactoryFoo._mt_org_apache_etch_tests_Foo_FooData);
+        etypes.Add(ValueFactoryFoo._mt_org_apache_etch_tests_Foo_foo1);
+        etypes.Add(ValueFactoryFoo._mt_org_apache_etch_tests_Foo__result_foo1);
+        etypes.Add(ValueFactoryFoo._mt_org_apache_etch_tests_Foo_foo2);
+        etypes.Add(ValueFactoryFoo._mt_org_apache_etch_tests_Foo__result_foo2);
+        etypes.Add(ValueFactoryFoo._mt_org_apache_etch_tests_Foo_foo3);
+        etypes.Add(ValueFactoryFoo._mt_org_apache_etch_tests_Foo__result_foo3);
+
+
+      
+       
+       
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar_BarTable);
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar_BarData);
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar_bar1);
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar__result_bar1);
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar_bar2);
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar__result_bar2);
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar_bar3);
+        etypes.Add(ValueFactoryBar._mt_org_apache_etch_tests_Bar__result_bar3);
+
+
+       
+       
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz_BazTable);
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz_BazData);
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz1);
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz1);
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz2);
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz2);
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz3);
+        etypes.Add(ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz3);
+		
+	 
+		
+		Assert.AreEqual( etypes, atypes );
+		foreach (XType type in etypes )
+			testGetType( vf, type );
+	}
+	
+	
+	[Test]
+	public void Method_duplicatesAreTheSame() 
+	{
+        Assert.AreEqual(new ValueFactoryBaz("none:").GetTypes(), new ValueFactoryBaz("none:").GetTypes());
+        Assert.AreEqual(new ValueFactoryBar("none:").GetTypes(), new ValueFactoryBar("none:").GetTypes());
+        Assert.AreEqual(new ValueFactoryFoo("none:").GetTypes(), new ValueFactoryFoo("none:").GetTypes());
+        
+	} 
+
+    }
+}
diff --git a/tests/src/test/csharp/etch.tests/TestRemoteTest1DotCsharp.cs b/tests/src/test/csharp/etch.tests/TestRemoteTest1DotCsharp.cs
new file mode 100644
index 0000000..41a2d6d
--- /dev/null
+++ b/tests/src/test/csharp/etch.tests/TestRemoteTest1DotCsharp.cs
@@ -0,0 +1,1354 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Transport;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+using org.apache.etch.tests;
+using org.apache.etch.tests.types.Test1;
+
+namespace etch.tests
+{
+    [TestFixture]
+    public class TestRemoteTest1DotCsharp
+    {
+        ValueFactory vf = new DummyValueFactory();
+
+        public TestRemoteTest1DotCsharp()
+        {
+             svc = new MyDeliveryService();
+             test = new RemoteTest1( svc, vf );
+        }
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestRemote" );
+        }
+
+
+        [SetUp]
+        public void SetUpAttribute()
+        {
+            svc = new MyDeliveryService();
+            test = new RemoteTest1( svc, vf );
+        }
+
+        [Test]
+        public void method_nothing()
+        {
+            test.nothing();
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_nothing,
+                new Field[] { },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_nothing,
+                4000 );
+        }
+
+        [Test]
+        public void method_incr1()
+        {
+            svc.xresult = 2;
+            Assert.AreEqual( 2, test.incr( 1 ) );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_incr,
+                new Field[] { ValueFactoryTest1._mf_x },
+                new Object[] { 1 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_incr,
+                4000 );
+        }
+
+        [Test]
+        public void method_incr2()
+        {
+            svc.xresult = 3;
+            Assert.AreEqual( 3, test.incr( 2 ) );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_incr,
+                new Field[] { ValueFactoryTest1._mf_x },
+                new Object[] { 2 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_incr,
+                4000 );
+        }
+
+        [Test]
+        public void method_incr3()
+        {
+            svc.xresult = -1;
+            Assert.AreEqual( -1, test.incr( -2 ) );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_incr,
+                new Field[] { ValueFactoryTest1._mf_x },
+                new Object[] { -2 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_incr,
+                4000 );
+        }
+
+        [Test]
+        public void method_sub1()
+        {
+            svc.xresult = 5;
+            Assert.AreEqual( 5, test.sub( 7, 2 ) );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sub,
+                new Field[] { ValueFactoryTest1._mf_x, ValueFactoryTest1._mf_y },
+                new Object[] { 7, 2 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sub,
+                4000 );
+        }
+
+        [Test]
+        public void method_sub2()
+        {
+            svc.xresult = 8;
+            Assert.AreEqual( 8, test.sub( 23, 15 ) );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sub,
+                new Field[] { ValueFactoryTest1._mf_x, ValueFactoryTest1._mf_y },
+                new Object[] { 23, 15 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sub,
+                4000 );
+        }
+
+        [Test]
+        public void method_sub3()
+        {
+            svc.xresult = -5;
+            Assert.AreEqual( -5, test.sub( 2, 7 ) );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sub,
+                new Field[] { ValueFactoryTest1._mf_x, ValueFactoryTest1._mf_y },
+                new Object[] { 2, 7 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sub,
+                4000 );
+        }
+
+        [Test]
+        public void method_sum()
+        {
+            svc.xresult = 24;
+            int[] arg = { 1, 2, 3, 7, 11 };
+            Assert.AreEqual( 24, test.sum( arg ) );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sum,
+                new Field[] { ValueFactoryTest1._mf_x },
+                new Object[] { arg },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sum,
+                4000 );
+        }
+
+        [Test]
+        public void method_trans1()
+        {
+            svc.xresult = 2;
+            Assert.AreEqual( 2, test.trans( E1.A, 5 ) ); // divide by 2
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_trans,
+                new Field[] { ValueFactoryTest1._mf_e, ValueFactoryTest1._mf_x },
+                new Object[] { E1.A, 5 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans,
+                4000 );
+        }
+
+        [Test]
+        public void method_trans2()
+        {
+            svc.xresult = 10;
+            Assert.AreEqual( 10, test.trans( E1.B, 5 ) ); // mul by 2
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_trans,
+                new Field[] { ValueFactoryTest1._mf_e, ValueFactoryTest1._mf_x },
+                new Object[] { E1.B, 5 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans,
+                4000 );
+        }
+
+        [Test]
+        public void method_trans3()
+        {
+            svc.xresult = 12;
+            Assert.AreEqual( 12, test.trans( E1.C, 5 ) ); // add 7
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_trans,
+                new Field[] { ValueFactoryTest1._mf_e, ValueFactoryTest1._mf_x },
+                new Object[] { E1.C, 5 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans,
+                4000 );
+        }
+
+        [Test]
+        public void method_dist1()
+        {
+            svc.xresult = Math.Sqrt( 3 );
+            S1 arg1 =  new S1( 1, 1, 1 );
+            S1 arg2 = new S1( 0, 0, 0 );
+            Assert.AreEqual( Math.Sqrt( 3 ), test.dist( arg1, arg2 ) );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_dist,
+                new Field[] { ValueFactoryTest1._mf_a, ValueFactoryTest1._mf_b },
+                new Object[] { arg1, arg2 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_dist,
+                4000 );
+        }
+
+        [Test]
+        public void method_dist2()
+        {
+            svc.xresult = Math.Sqrt( 35 );
+            S1 arg1 = new S1( 1, 2, 3 );
+            S1 arg2 = new S1( 6, 5, 4 );
+            Assert.AreEqual( Math.Sqrt( 35 ), test.dist( arg1, arg2 ) );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_dist,
+                new Field[] { ValueFactoryTest1._mf_a, ValueFactoryTest1._mf_b },
+                new Object[] { arg1, arg2 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_dist,
+                4000 );
+        }
+
+        [Test]
+        public void method_dist3()
+        {
+            svc.xresult = Math.Sqrt( 56 );
+            S1 arg1 = new S1( 1, 2, 3 );
+            S1 arg2 = new S1( -1, -2, -3 );
+            Assert.AreEqual( Math.Sqrt( 56 ), test.dist( arg1, arg2 ) );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_dist,
+                new Field[] { ValueFactoryTest1._mf_a, ValueFactoryTest1._mf_b },
+                new Object[] { arg1, arg2 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_dist,
+                4000 );
+        }
+
+        [Test]
+        public void method_fill1()
+        {
+            svc.xresult = new int[] { };
+            int[] x = test.fill( 0, 1 );
+            Assert.AreEqual( 0, x.Length );
+            foreach ( int i in x )
+                Assert.AreEqual( 1, i );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_fill,
+                new Field[] { ValueFactoryTest1._mf_n, ValueFactoryTest1._mf_x },
+                new Object[] { 0, 1 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fill,
+                4000 );
+        }
+
+        [Test]
+        public void method_fill2()
+        {
+            svc.xresult = new int[] { 2 };
+            int[] x = test.fill( 1, 2 );
+            Assert.AreEqual( 1, x.Length );
+            foreach ( int i in x )
+                Assert.AreEqual( 2, i );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_fill,
+                new Field[] { ValueFactoryTest1._mf_n, ValueFactoryTest1._mf_x },
+                new Object[] { 1, 2 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fill,
+                4000 );
+        }
+
+        [Test]
+        public void method_fill3()
+        {
+            svc.xresult = new int[] { 3, 3 };
+            int[] x = test.fill( 2, 3 );
+            Assert.AreEqual( 2, x.Length );
+            foreach ( int i in x )
+                Assert.AreEqual( 3, i );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_fill,
+                new Field[] { ValueFactoryTest1._mf_n, ValueFactoryTest1._mf_x },
+                new Object[] { 2, 3 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fill,
+                4000 );
+        }
+
+        [Test]
+        public void method_blow1()
+        {
+            try
+            {
+                svc.xresult = new Excp1( "foo", 2 );
+                test.blow( "foo", 2 );
+
+            }
+            catch ( Excp1 e )
+            {
+                Assert.AreEqual( "foo", e.msg );
+                Assert.AreEqual( 2, e.code );
+            }
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_blow,
+                new Field[] { ValueFactoryTest1._mf_msg, ValueFactoryTest1._mf_code },
+                new Object[] { "foo", 2 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_blow,
+                4000 );
+        }
+
+        [Test]
+        public void method_blow2()
+        {
+            try
+            {
+                svc.xresult = new Excp1( "bar", 3 );
+                test.blow( "bar", 3 );
+                //fail( "blow did not throw" );
+            }
+            catch ( Excp1 e )
+            {
+                Assert.AreEqual( "bar", e.msg );
+                Assert.AreEqual( 3, e.code );
+            }
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_blow,
+                new Field[] { ValueFactoryTest1._mf_msg, ValueFactoryTest1._mf_code },
+                new Object[] { "bar", 3 },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_blow,
+                4000 );
+        }
+
+        [Test]
+        public void method_beets1()
+        {
+            svc.xresult = 5;
+            Assert.AreEqual( 5, test.beets( E1.A ) );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets,
+                new Field[] { ValueFactoryTest1._mf_e },
+                new Object[] { E1.A },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets,
+                4000 );
+        }
+
+        [Test]
+        public void method_beets2()
+        {
+            bool exceptionFlag = false;
+            try
+            {
+                svc.xresult = new Excp3();
+                test.beets( E1.B );
+            }
+            catch ( Excp3 )
+            {
+                exceptionFlag = true;
+            }
+            Assert.IsTrue(exceptionFlag);
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets,
+                new Field[] { ValueFactoryTest1._mf_e },
+                new Object[] { E1.B },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets,
+                4000 );
+        }
+
+        [Test]
+        public void method_beets3()
+        {
+            bool exceptionFlag = false;
+            try
+            {
+                svc.xresult = new Excp4();
+                test.beets( E1.C );
+            }
+            catch ( Excp4  )
+            {
+                exceptionFlag = true;
+            }
+            Assert.IsTrue( exceptionFlag );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets,
+                new Field[] { ValueFactoryTest1._mf_e },
+                new Object[] { E1.C },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets,
+                4000 );
+        }
+
+        //[Test]
+        //public void method_beets4()
+        //{
+        //    svc.xresult = null;
+        //    Assert.IsNull( test.beets( null ) );
+        //    check( What.CALL,
+        //        ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets,
+        //        new Field[] { ValueFactoryTest1._mf_e },
+        //        new Object[] { null },
+        //        ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets,
+        //        4000 );
+        //}
+
+        /////////////
+        // bool //
+        /////////////
+
+        [Test]
+        public void method_p_boolean_null()
+        {
+            svc.clear();
+            bool? a = null;
+            svc.xresult = a;
+            bool? r = test.p_boolean( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_boolean,
+                new Field[] {},
+                new Object[] {},
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_boolean()
+        {
+            bool? a = true;
+            svc.xresult = a;
+            bool? r = test.p_boolean( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_boolean,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_boolean_array_null()
+        {
+            bool[] a = null;
+            svc.xresult = a;
+            bool[] r = test.p_boolean_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_boolean_array,
+                new Field[] {  },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean_array,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_boolean_array()
+        {
+            bool x = false;
+            bool y = true;
+            bool[] a = { x, y };
+            svc.xresult = a;
+            bool[] r = test.p_boolean_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_boolean_array,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean_array,
+                4000 );
+        }
+
+        //////////
+        // sbyte //
+        //////////
+
+        [Test]
+        public void method_p_byte_null()
+        {
+            sbyte? a = null;
+            svc.xresult = a;
+            sbyte? r = test.p_byte( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_byte,
+                new Field[] { },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_byte()
+        {
+            sbyte? a = 1;
+            svc.xresult = a;
+            sbyte? r = test.p_byte( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_byte,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_byte_array_null()
+        {
+            sbyte[] a = null;
+            svc.xresult = a;
+            sbyte[] r = test.p_byte_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_byte_array,
+                new Field[] {  },
+                new Object[] {},
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte_array,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_byte_array()
+        {
+            sbyte x = 12;
+            sbyte y = 23;
+            sbyte[] a = { x, y };
+            svc.xresult = a;
+            sbyte[] r = test.p_byte_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_byte_array,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte_array,
+                4000 );
+        }
+
+        ///////////
+        // SHORT //
+        ///////////
+
+        [Test]
+        public void method_p_short_null()
+        {
+            short? a = null;
+            svc.xresult = a;
+            short? r = test.p_short( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_short,
+                new Field[] {  },
+                new Object[] {  },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_short()
+        {
+            short? a = 1234;
+            svc.xresult = a;
+            short? r = test.p_short( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_short,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_short_array_null()
+        {
+            short[] a = null;
+            svc.xresult = a;
+            short[] r = test.p_short_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_short_array,
+                new Field[] { },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short_array,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_short_array()
+        {
+            short x = 1234;
+            short y = 2345;
+            short[] a = { x, y };
+            svc.xresult = a;
+            short[] r = test.p_short_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_short_array,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short_array,
+                4000 );
+        }
+
+        /////////
+        // INT //
+        /////////
+
+        [Test]
+        public void method_p_int_null()
+        {
+            int? a = null;
+            svc.xresult = a;
+            int? r = test.p_int( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_int,
+                new Field[] { },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_int()
+        {
+            int? a = 12345678;
+            svc.xresult = a;
+            int? r = test.p_int( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_int,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_int_array_null()
+        {
+            int[] a = null;
+            svc.xresult = a;
+            int[] r = test.p_int_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_int_array,
+                new Field[] { },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int_array,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_int_array()
+        {
+            int x = 12345678;
+            int y = 23456789;
+            int[] a = { x, y };
+            svc.xresult = a;
+            int[] r = test.p_int_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_int_array,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int_array,
+                4000 );
+        }
+
+        //////////
+        // LONG //
+        //////////
+
+        [Test]
+        public void method_p_long_null()
+        {
+            long? a = null;
+            svc.xresult = a;
+            long? r = test.p_long( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_long,
+                new Field[] {  },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_long()
+        {
+            long? a = 1234567812345678L;
+            svc.xresult = a;
+            long? r = test.p_long( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_long,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_long_array_null()
+        {
+            long[] a = null;
+            svc.xresult = a;
+            long[] r = test.p_long_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_long_array,
+                new Field[] {  },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long_array,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_long_array()
+        {
+            long x = 1234567812345678L;
+            long y = 2345678923456789L;
+            long[] a = { x, y };
+            svc.xresult = a;
+            long[] r = test.p_long_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_long_array,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long_array,
+                4000 );
+        }
+
+        ///////////
+        // float //
+        ///////////
+
+        [Test]
+        public void method_p_float_null()
+        {
+            float? a = null;
+            svc.xresult = a;
+            float? r = test.p_float( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_float,
+                new Field[] {  },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_float()
+        {
+            float? a = 123.456f;
+            svc.xresult = a;
+            float? r = test.p_float( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_float,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_float_array_null()
+        {
+            float[] a = null;
+            svc.xresult = a;
+            float[] r = test.p_float_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_float_array,
+                new Field[] { },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float_array,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_float_array()
+        {
+            float x = 123.456f;
+            float y = 234.567f;
+            float[] a = { x, y };
+            svc.xresult = a;
+            float[] r = test.p_float_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_float_array,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float_array,
+                4000 );
+        }
+
+        ////////////
+        // DOUBLE //
+        ////////////
+
+        [Test]
+        public void method_p_double_null()
+        {
+            double? a = null;
+            svc.xresult = a;
+            double? r = test.p_double( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_double,
+                new Field[] { },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_double()
+        {
+            double? a = 12345678.12345678;
+            svc.xresult = a;
+            double? r = test.p_double( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_double,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_double_array_null()
+        {
+            double[] a = null;
+            svc.xresult = a;
+            double[] r = test.p_double_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_double_array,
+                new Field[] {  },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double_array,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_double_array()
+        {
+            double x = 12345678.12345678;
+            double y = 23456789.23456789;
+            double[] a = { x, y };
+            svc.xresult = a;
+            double[] r = test.p_double_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_double_array,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double_array,
+                4000 );
+        }
+
+        ////////////
+        // STRING //
+        ////////////
+
+        [Test]
+        public void method_p_string_null()
+        {
+            String a = null;
+            svc.xresult = a;
+            String r = test.p_string( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_string,
+                new Field[] { },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_string()
+        {
+            String a = "abc";
+            svc.xresult = a;
+            String r = test.p_string( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_string,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_string_array_null()
+        {
+            String[] a = null;
+            svc.xresult = a;
+            String[] r = test.p_string_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_string_array,
+                new Field[] {  },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string_array,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_string_array()
+        {
+            String x = "abc";
+            String y = "bcd";
+            String[] a = { x, y };
+            svc.xresult = a;
+            String[] r = test.p_string_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_string_array,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string_array,
+                4000 );
+        }
+
+        ////////
+        // E1 //
+        ////////
+
+        [Test]
+        public void method_p_E1_null()
+        {
+            E1? a = null;
+            svc.xresult = a;
+            E1? r = test.p_E1( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_E1,
+                new Field[] { },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_E1()
+        {
+            E1 a = E1.A;
+            svc.xresult = a;
+            E1? r = test.p_E1( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_E1,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_E1_array_null()
+        {
+            E1[] a = null;
+            svc.xresult = a;
+            E1[] r = test.p_E1_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_E1_array,
+                new Field[] {  },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1_array,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_E1_array()
+        {
+            E1 x = E1.A;
+            E1 y = E1.B;
+            E1[] a = { x, y };
+            svc.xresult = a;
+            E1[] r = test.p_E1_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_E1_array,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1_array,
+                4000 );
+        }
+
+        ////////
+        // S1 //
+        ////////
+
+        [Test]
+        public void method_p_S1_null()
+        {
+            S1 a = null;
+            svc.xresult = a;
+            S1 r = test.p_S1( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S1,
+                new Field[] {  },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_S1()
+        {
+            S1 a = new S1( 1, 2, 3 );
+            svc.xresult = a;
+            S1 r = test.p_S1( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S1,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_S1_array_null()
+        {
+            S1[] a = null;
+            svc.xresult = a;
+            S1[] r = test.p_S1_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S1_array,
+                new Field[] {  },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1_array,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_S1_array()
+        {
+            S1 x = new S1( 1, 2, 3 );
+            S1 y = new S1( 2, 3, 4 );
+            S1[] a = { x, y };
+            svc.xresult = a;
+            S1[] r = test.p_S1_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S1_array,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1_array,
+                4000 );
+        }
+
+        ////////
+        // S2 //
+        ////////
+
+        [Test]
+        public void method_p_S2_null()
+        {
+            S2 a = null;
+            svc.xresult = a;
+            S2 r = test.p_S2( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S2,
+                new Field[] {  },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_S2()
+        {
+            S2 a = new S2( new S1( 1, 2, 3 ), new S1( 2, 3, 4 ), E1.A );
+            svc.xresult = a;
+            S2 r = test.p_S2( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S2,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_S2_array_null()
+        {
+            S2[] a = null;
+            svc.xresult = a;
+            S2[] r = test.p_S2_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S2_array,
+                new Field[] {  },
+                new Object[] { },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2_array,
+                4000 );
+        }
+
+        [Test]
+        public void method_p_S2_array()
+        {
+            S2 x = new S2( new S1( 1, 2, 3 ), new S1( 2, 3, 4 ), E1.A );
+            S2 y = new S2( new S1( 2, 3, 4 ), new S1( 3, 4, 5 ), E1.B );
+            S2[] a = { x, y };
+            svc.xresult = a;
+            S2[] r = test.p_S2_array( a );
+            assertObjectEquals( a, r );
+            check( What.CALL,
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S2_array,
+                new Field[] { ValueFactoryTest1._mf_a },
+                new Object[] { a },
+                ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2_array,
+                4000 );
+        }
+
+        ///////////////////
+        // UTILITY STUFF //
+        ///////////////////
+
+        /**
+         * @param a
+         * @param b
+         */
+        private void assertObjectEquals( Object a, Object b )
+        {
+            if ( a == b )
+                return;
+
+            if ( a == null || b == null )
+            {
+                //fail( "a == null || b == null" );
+                Assert.IsTrue( false );
+                return;
+            }
+
+            Assert.AreSame( a.GetType(), b.GetType() );
+
+            if ( ( a is Array ) && ( b is Array ) )
+            {
+                assertArrayEquals( a, b );
+                return;
+            }
+
+            Assert.AreEqual( a, b );
+        }
+
+        /**
+         * @param a
+         * @param b
+         */
+        private void assertArrayEquals( Object a, Object b )
+        {
+            int n = ( ( Array ) a ).Length;
+            Assert.AreEqual( n, ( ( Array ) b ).Length );
+            for ( int i = 0; i < n; i++ )
+                assertObjectEquals( ( ( Array ) a ).GetValue( i ), ( ( Array ) b ).GetValue( i ) );
+        }
+
+        private void check( What what, XType type, Field[] fields, Object[] objects,
+            XType resultType, int timeout )
+        {
+            Assert.AreEqual( what, svc.what );
+            Assert.AreEqual( type, svc.xmsg.GetXType );
+
+            int n = fields.Length;
+            Assert.AreEqual( n, objects.Length );
+
+            //Console.WriteLine( "size = " + svc.xmsg.Count );
+            Assert.AreEqual( n, svc.xmsg.Count );
+
+            for ( int i = 0; i < n; i++ )
+            {
+                Field f = fields[ i ];
+                Assert.AreEqual( objects[ i ], svc.xmsg.Get( f ) );
+            }
+
+            Assert.AreEqual( resultType, svc.xresponseType );
+            Assert.AreEqual( ValueFactoryTest1._mf_result, svc.xresponseField );
+            Assert.AreEqual(  timeout, svc.xtimeout );
+        }
+
+        public enum What { SEND, CALL, SHUTDOWNOUTPUT, BEGINCALL }
+
+        private MyDeliveryService svc;
+        private org.apache.etch.tests.Test1 test;
+
+        public  class MyDeliveryService : DeliveryService,MailboxManager
+        {
+            public Enum what;
+            public Message xmsg;
+            public XType xresponseType;
+            public Field xresponseField;
+            public int? xtimeout;
+            public Object xresult;
+            public Mailbox xmb;
+
+            public void clear()
+            {
+                what = null;
+                xmsg = null;
+                xresponseType = null;
+                xresponseField = null;
+                xtimeout = null;
+                xresult = null;
+            }
+
+            public void Send( Message msg )
+            {
+                Assert.IsNull( what );
+                what = What.SEND;
+                xmsg = msg;
+            }
+
+            public Mailbox BeginCall( Message msg )
+            {
+                Assert.IsNull( what );
+                what = What.BEGINCALL;
+                xmsg = msg;
+                xmb = new PlainMailbox( this, 0L );
+                return xmb;
+            }
+
+            public Object EndCall( Mailbox mb, XType responseType )
+            {
+                Assert.AreEqual( What.BEGINCALL, what );
+                Assert.AreEqual( xmb, mb );
+                what = What.CALL;
+                xmb = null;
+                xresponseType = responseType;
+                xresponseField = responseType.ResponseField;
+                xtimeout = responseType.Timeout;
+                if ( xresult is Exception )
+                    throw ( Exception ) xresult;
+                return xresult;
+            }
+
+            #region Transport Members
+
+            public object TransportQuery( object query )
+            {
+                // ignore
+                return null;
+            }
+
+            public void TransportControl( object control, object value )
+            {
+                //ignore
+            }
+
+            public void TransportNotify( object eventObj )
+            {
+                //ignore
+            }
+
+            #endregion
+
+            #region DeliveryService Members
+
+        
+            #endregion
+
+            public void Redeliver( Who sender, Message msg ) 
+		    {
+			// ignore
+		    }
+
+		    public void Unregister( Mailbox mb )
+		    {
+			// ignore
+		    }
+
+
+            #region TransportMessage Members
+
+            public void TransportMessage(Who recipient, Message msg)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+
+            #region Transport<SessionMessage> Members
+
+
+            public void SetSession(SessionMessage session)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public SessionMessage GetSession()
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+
+            #region SessionMessage Members
+
+            public bool SessionMessage(Who sender, Message msg)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+
+            #region Session Members
+
+            public object SessionQuery(object query)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SessionControl(object control, object value)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SessionNotify(object eventObj)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+
+            #region MailboxManager Members
+
+
+            public Mailbox TransportCall(Who recipient, Message msg)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+        }
+    }
+}
diff --git a/tests/src/test/csharp/etch.tests/TestStubTest1DotCsharp.cs b/tests/src/test/csharp/etch.tests/TestStubTest1DotCsharp.cs
new file mode 100644
index 0000000..3679b6d
--- /dev/null
+++ b/tests/src/test/csharp/etch.tests/TestStubTest1DotCsharp.cs
@@ -0,0 +1,426 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Transport;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+using org.apache.etch.tests;
+using org.apache.etch.tests.types.Test1;
+
+namespace etch.tests
+{
+    [TestFixture]
+    public class TestStubTest1DotCsharp
+    {
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestStub" );
+        }
+
+        [SetUp]
+        public void Setup()
+        {
+            test = new FakeTest1();
+            vf = new ValueFactoryTest1("none:");
+	        pool = new FreePool();
+            src = new MyMessageSource( this );
+            stub = new StubTest1( src, test, pool, pool );
+            xreplyMon.Set( null );
+        }
+
+        Monitor<Message> xreplyMon = new Monitor<Message>( "Monitor for xreply" );
+
+        [Test]
+	    public void method_nothing() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_nothing, vf );
+            // msg.Add( ValueFactoryTest1._mf_x, 3 );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+            xreplyMon.WaitUntilNotEq( null );
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_nothing );
+		    Assert.AreEqual( 0, src.xreply.Count );
+	    }
+
+	    [Test]
+	    public void method_incr1() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_incr, vf );
+		    msg.Add( ValueFactoryTest1._mf_x, 3 );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+            xreplyMon.WaitUntilNotEq( null );
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_incr );
+            Assert.AreEqual(1, src.xreply.Count);
+		    Assert.AreEqual( 4, src.xreply.Get( ValueFactoryTest1._mf_result ) );
+	    }
+
+
+	    [Test]
+	    public void method_sub() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sub, vf );
+		    msg.Add( ValueFactoryTest1._mf_x, 7 );
+		    msg.Add( ValueFactoryTest1._mf_y, 3 );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sub );
+            Assert.AreEqual(1, src.xreply.Count);
+		    Assert.AreEqual( 4, src.xreply.Get( ValueFactoryTest1._mf_result ) );
+	    }
+
+	    [Test]
+	    public void method_sum() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sum, vf );
+            msg.Add( ValueFactoryTest1._mf_x, new int[] { 1, 2, 3, 7, 11 } );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sum );
+            Assert.AreEqual(1, src.xreply.Count);
+		    Assert.AreEqual( 24, src.xreply.Get( ValueFactoryTest1._mf_result ) );
+	    }
+
+	    [Test]
+	    public void method_trans1() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_trans, vf );
+		    msg.Add( ValueFactoryTest1._mf_e, E1.A );
+		    msg.Add( ValueFactoryTest1._mf_x, 5 );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans );
+            Assert.AreEqual(1, src.xreply.Count);
+		    Assert.AreEqual( 2, src.xreply.Get( ValueFactoryTest1._mf_result ) );
+	    }
+
+	    [Test]
+	    public void method_trans2() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_trans, vf );
+		    msg.Add( ValueFactoryTest1._mf_e, E1.B );
+		    msg.Add( ValueFactoryTest1._mf_x, 5 );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans );
+            Assert.AreEqual(1, src.xreply.Count);
+		    Assert.AreEqual( 10, src.xreply.Get( ValueFactoryTest1._mf_result ) );
+	    }
+
+	    [Test]
+	    public void method_trans3() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_trans, vf );
+		    msg.Add( ValueFactoryTest1._mf_e, E1.C );
+		    msg.Add( ValueFactoryTest1._mf_x, 5 );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans );
+            Assert.AreEqual(1, src.xreply.Count);
+		    Assert.AreEqual( 12, src.xreply.Get( ValueFactoryTest1._mf_result ) );
+	    }
+
+	    [Test]
+	    public void method_dist1() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_dist, vf );
+		    msg.Add( ValueFactoryTest1._mf_a, new S1( 1, 1, 1 ) );
+		    msg.Add( ValueFactoryTest1._mf_b, new S1( 0, 0, 0 ) );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_dist );
+		    Assert.AreEqual( 1, src.xreply.Count );
+		    Assert.AreEqual( Math.Sqrt( 3 ), src.xreply.Get( ValueFactoryTest1._mf_result ) );
+	    }
+
+	    [Test]
+	    public void method_dist2() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_dist, vf );
+		    msg.Add( ValueFactoryTest1._mf_a, new S1( 1, 2, 3 ) );
+		    msg.Add( ValueFactoryTest1._mf_b, new S1( 6, 5, 4 ) );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_dist );
+		    Assert.AreEqual( 1, src.xreply.Count );
+		    Assert.AreEqual( Math.Sqrt( 35 ), src.xreply.Get( ValueFactoryTest1._mf_result ) );
+	    }
+
+	    [Test]
+	    public void method_fill() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_fill, vf );
+		    msg.Add( ValueFactoryTest1._mf_n, 4 );
+		    msg.Add( ValueFactoryTest1._mf_x, 3 );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fill );
+            Assert.AreEqual(1, src.xreply.Count);
+		    int[] x = (int[]) src.xreply.Get( ValueFactoryTest1._mf_result );
+            Assert.IsNotNull( x );
+		    Assert.AreEqual( 4, x.Length );
+		    foreach (int y in x)
+			    Assert.AreEqual( 3, y );
+	    }
+
+	    [Test]
+	    public void method_blow() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_blow, vf );
+		    msg.Add( ValueFactoryTest1._mf_msg, "foo" );
+		    msg.Add( ValueFactoryTest1._mf_code, 23 );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_blow );
+            Assert.AreEqual(1, src.xreply.Count);
+		    Excp1 e = (Excp1) src.xreply.Get( ValueFactoryTest1._mf_result );
+		    Assert.IsNotNull( e );
+		    Assert.AreEqual( "foo", e.msg );
+		    Assert.AreEqual( 23, e.code );
+	    }
+
+	    [Test]
+	    public void method_beets1() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets, vf );
+		    msg.Add( ValueFactoryTest1._mf_e, E1.A );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets );
+		    Assert.AreEqual( 1, src.xreply.Count );
+		    Object o = src.xreply.Get( ValueFactoryTest1._mf_result );
+		    Assert.AreEqual( 5, o );
+	    }
+
+	    [Test]
+	    public void method_beets2() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets, vf );
+		    msg.Add( ValueFactoryTest1._mf_e, E1.B );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets );
+		    Assert.AreEqual( 1, src.xreply.Count );
+		    Object o = src.xreply.Get( ValueFactoryTest1._mf_result );
+		    Assert.AreEqual( typeof(Excp3), o.GetType() );
+	    }
+
+	    [Test]
+	    public void method_beets3() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets, vf );
+		    msg.Add( ValueFactoryTest1._mf_e, E1.C );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets );
+		    Assert.AreEqual( 1, src.xreply.Count );
+		    Object o = src.xreply.Get( ValueFactoryTest1._mf_result );
+		    Assert.AreEqual( typeof(Excp4), o.GetType() );
+	    }
+
+	    //[Test]
+	    //public void method_beets4() 
+	    //{
+		//    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets, vf );
+		//    msg.Add( ValueFactoryTest1._mf_e, null );
+		//    stub.Message( null, msg );
+		   // check the result.
+		//    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets );
+		//    Assert.AreEqual( 0, src.xreply.Count );
+		//    Object o = src.xreply.Get( ValueFactoryTest1._mf_result );
+		//    Assert.IsNull( o );
+	    //}
+    	
+	    [Test]
+	    public void method_isTrue() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_isTrue, vf );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_isTrue );
+            Assert.AreEqual(1, src.xreply.Count);
+		    Object o = src.xreply.Get( ValueFactoryTest1._mf_result );
+		    Assert.AreEqual( true, o );
+	    }
+    	
+	    [Test]
+	    public void method_isFalse() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_isFalse, vf );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+		    src.xreply.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_isFalse );
+            Assert.AreEqual(1, src.xreply.Count);
+		    Object o = src.xreply.Get( ValueFactoryTest1._mf_result );
+		    Assert.AreEqual( false, o );
+	    }
+    	
+	    [Test]
+	    public void method_alwaysWorks() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_alwaysWorks, vf );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+            src.xreply.CheckType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_alwaysWorks);
+            Assert.AreEqual(1, src.xreply.Count);
+            Object o = src.xreply.Get(ValueFactoryTest1._mf_result);
+		    Assert.AreEqual( 23, o );
+	    }
+    	
+	    [Test]
+	    public void method_alwaysFails() 
+	    {
+		    Message msg = new Message( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_alwaysFails, vf );
+		    stub.SessionMessage( null, msg );
+		    // check the result.
+            src.xreply.CheckType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_alwaysFails);
+            Assert.AreEqual(1, src.xreply.Count);
+            Object o = src.xreply.Get(ValueFactoryTest1._mf_result);
+		    Assert.IsTrue( o is _Etch_AuthException );
+		    _Etch_AuthException e = (_Etch_AuthException) o;
+		    Assert.AreEqual( "alwaysFails", e.msg );
+	    }
+
+        private FakeTest1 test;
+        private ValueFactoryTest1 vf;
+        private Pool pool;
+
+        private StubTest1 stub;
+        private MyMessageSource src;
+    	
+	    public class MyMessageSource : DeliveryService
+	    {
+
+            private TestStubTest1DotCsharp _baseObj;
+	        private SessionMessage session;
+
+            public MyMessageSource( TestStubTest1DotCsharp baseObj  )
+            {
+                _baseObj = baseObj;
+            }
+
+            #region MessageSource Members
+            
+            public Message xreply;
+            
+            public void Messagex( Who recipient, Message msg )
+            {
+                Assert.IsNull( recipient );
+                Assert.IsNull( xreply );
+                xreply = msg;
+                _baseObj.xreplyMon.Set(new Message(new XType("dummy"), new ValueFactoryTest1("none:")));
+            }
+
+            #endregion
+
+            #region DeliveryService Members
+
+            public Mailbox BeginCall(Message msg)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public object EndCall(Mailbox mb, XType responseType)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+
+            #region TransportMessage Members
+
+            public void TransportMessage(Who recipient, Message msg)
+            {
+                Assert.IsNull(recipient);
+                Assert.IsNull(xreply);
+                xreply = msg;
+                _baseObj.xreplyMon.Set(new Message(new XType("dummy"), new ValueFactoryTest1("none:")));
+            }
+
+            #endregion
+
+            #region Transport<SessionMessage> Members
+
+            public object TransportQuery(object query)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void TransportControl(object control, object value)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void TransportNotify(object eventObj)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SetSession(SessionMessage session)
+            {
+                this.session = session;
+            }
+
+            #endregion
+
+            #region SessionMessage Members
+
+            public bool SessionMessage(Who sender, Message msg)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+
+            #region Session Members
+
+            public object SessionQuery(object query)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SessionControl(object control, object value)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            public void SessionNotify(object eventObj)
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+
+            #region Transport<SessionMessage> Members
+
+
+            public SessionMessage GetSession()
+            {
+                throw new Exception("The method or operation is not implemented.");
+            }
+
+            #endregion
+        }
+    }
+}
diff --git a/tests/src/test/csharp/etch.tests/TestTest1DotCsharp.cs b/tests/src/test/csharp/etch.tests/TestTest1DotCsharp.cs
new file mode 100644
index 0000000..d3eb82f
--- /dev/null
+++ b/tests/src/test/csharp/etch.tests/TestTest1DotCsharp.cs
@@ -0,0 +1,696 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using NUnit.Framework;
+using org.apache.etch.tests;
+using org.apache.etch.tests.types.Test1;
+
+namespace etch.tests
+{
+    [TestFixture]
+    public class TestTest1DotCsharp
+    {
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestTest" );
+        }
+
+
+        [Test]
+	    public void const_booleans()  
+	    {
+		    Assert.IsFalse( ConstsTest1.BOOL1 );
+		    Assert.IsTrue( ConstsTest1.BOOL2 );
+	    }
+    	
+	    [Test]
+	    public void const_bytes()  
+	    {
+		    Assert.AreEqual( sbyte.MinValue, ConstsTest1.BYTE1 );
+		    Assert.AreEqual( (sbyte) -1, ConstsTest1.BYTE2 );
+		    Assert.AreEqual( (sbyte) 0, ConstsTest1.BYTE3 );
+		    Assert.AreEqual( (sbyte) 1, ConstsTest1.BYTE4 );
+		    Assert.AreEqual( sbyte.MaxValue, ConstsTest1.BYTE5 );
+	    }
+    	
+	    [Test]
+	    public void const_shorts()  
+	    {
+            
+		    Assert.AreEqual( short.MinValue, ConstsTest1.SHORT1 );
+		    Assert.AreEqual( (short) -1, ConstsTest1.SHORT2 );
+		    Assert.AreEqual( (short) 0, ConstsTest1.SHORT3 );
+		    Assert.AreEqual( (short) 1, ConstsTest1.SHORT4 );
+		    Assert.AreEqual( short.MaxValue, ConstsTest1.SHORT5 );
+	    }
+    	
+	    [Test]
+	    public void const_ints()  
+	    {
+            Assert.AreEqual(int.MinValue, ConstsTest1.INT1);
+            Assert.AreEqual(-1, ConstsTest1.INT2);
+            Assert.AreEqual(0, ConstsTest1.INT3);
+            Assert.AreEqual(1, ConstsTest1.INT4);
+            Assert.AreEqual(int.MaxValue, ConstsTest1.INT5);
+	    }
+    	
+	    [Test]
+	    public void const_longs()  
+	    {
+            Assert.AreEqual(long.MinValue, ConstsTest1.LONG1);
+            Assert.AreEqual((long)-1, ConstsTest1.LONG2);
+            Assert.AreEqual((long)0, ConstsTest1.LONG3);
+            Assert.AreEqual((long)1, ConstsTest1.LONG4);
+            Assert.AreEqual(long.MaxValue, ConstsTest1.LONG5);
+	    }
+    	
+	    [Test]
+	    public void const_floats()  
+	    {
+            Assert.AreEqual(1.4e-45f, ConstsTest1.FLOAT1);
+            Assert.AreEqual((float)-1, ConstsTest1.FLOAT2);
+            Assert.AreEqual((float)0, ConstsTest1.FLOAT3);
+            Assert.AreEqual((float)1, ConstsTest1.FLOAT4);
+            Assert.AreEqual(3.4028235e38f, ConstsTest1.FLOAT5);
+	    }
+    	
+	    [Test]
+	    public void const_doubles()  
+	    {
+            Assert.AreEqual(4.9e-324, ConstsTest1.DOUBLE1);
+            Assert.AreEqual((double)-1, ConstsTest1.DOUBLE2);
+            Assert.AreEqual((double)0, ConstsTest1.DOUBLE3);
+            Assert.AreEqual((double)1, ConstsTest1.DOUBLE4);
+            Assert.AreEqual(1.7976931348623157e308, ConstsTest1.DOUBLE5);
+	    }
+    	
+	    [Test]
+	    public void const_strings()  
+	    {
+            Assert.AreEqual("", ConstsTest1.STRING1);
+            Assert.AreEqual("a", ConstsTest1.STRING2);
+            Assert.AreEqual("abc", ConstsTest1.STRING3);
+            Assert.AreEqual("a\tb\tc\r\n", ConstsTest1.STRING4);
+            Assert.AreEqual("x x", ConstsTest1.STRING5);
+            Assert.AreEqual("x\u00bfx", ConstsTest1.STRING6);
+            Assert.AreEqual("x\u03a9x", ConstsTest1.STRING7);
+            Assert.AreEqual("x\\x", ConstsTest1.STRING8);
+            Assert.AreEqual("x'x", ConstsTest1.STRING9);
+            Assert.AreEqual("x\"x", ConstsTest1.STRING10);
+	    }
+    	
+	    [Test]
+	    public void enum_E1()  
+	    {
+            //Assert.AreEqual( 3, E1.values().Length );
+		    Assert.IsNotNull( E1.A );
+		    Assert.IsNotNull( E1.B );
+		    Assert.IsNotNull( E1.C );
+            //Assert.AreEqual( E1.A, E1.valueOf( "A" ) );
+            //Assert.AreEqual( E1.B, E1.valueOf( "B" ) );
+            //Assert.AreEqual( E1.C, E1.valueOf( "C" ) );
+            //Assert.AreEqual( 0, E1.A.ordinal() );
+            //Assert.AreEqual( 1, E1.B.ordinal() );
+            //Assert.AreEqual( 2, E1.C.ordinal() );
+	    }
+    	
+	    [Test]
+	    public void struct_S1()  
+	    {
+		    S1 s = new S1( 1, 2, 3 );
+		    Assert.AreEqual( 1, s.x );
+		    Assert.AreEqual( 2, s.y );
+		    Assert.AreEqual( 3, s.z );
+    		
+		    s = new S1( null, null, null );
+		    Assert.IsNull( s.x );
+		    Assert.IsNull( s.y );
+		    Assert.IsNull( s.z );
+    		
+		    s = new S1();
+		    Assert.IsNull( s.x );
+		    Assert.IsNull( s.y );
+		    Assert.IsNull( s.z );
+    		
+		    s.x = 4;
+		    s.y = 5;
+		    s.z = 6;
+    		
+		    Assert.AreEqual( 4, s.x );
+		    Assert.AreEqual( 5, s.y );
+		    Assert.AreEqual( 6, s.z );
+    		
+		    s.x = null;
+		    Assert.IsNull( s.x );
+    		
+		    s.x = 7;
+		    Assert.AreEqual( 7, s.x );
+	    }
+    	
+	    [Test]
+	    public void except_Excp1()  
+	    {
+		    Excp1 e = new Excp1( "foo", 23 );
+		    Assert.AreEqual( "foo", e.msg );
+		    Assert.AreEqual( 23, e.code );
+    		
+		    e = new Excp1( null, null );
+		    Assert.IsNull( e.msg );
+		    Assert.IsNull( e.code );
+    		
+		    e = new Excp1();
+		    Assert.IsNull( e.msg );
+		    Assert.IsNull( e.code );
+    		
+		    e.msg = "bar";
+		    e.code = 24;
+    		
+		    Assert.AreEqual( "bar", e.msg );
+		    Assert.AreEqual( 24, e.code );
+    		
+		    e.msg = null;
+		    e.code = null;
+    		
+		    Assert.IsNull( e.msg );
+		    Assert.IsNull( e.code );
+
+            //Throwable t = e;
+            //Assert.IsTrue( t is Exception );
+            //Assert.IsFalse( t is RuntimeException );
+	    }
+    	
+	    [Test]
+	    public void except_Excp2()  
+	    {
+		    Excp2 e = new Excp2();
+
+		    Exception t = e;
+		    Assert.IsTrue( t is Exception );
+		    //Assert.IsTrue( t is RuntimeException );
+	    }
+    	
+	    [Test]
+	    public void except_Excp3()  
+	    {
+		    Excp3 e = new Excp3();
+
+            Exception t = e;
+            Assert.IsTrue( t is Exception );
+            //Assert.IsTrue( t is RuntimeException );
+	    }
+    	
+	    [Test]
+	    public void except_Excp4()  
+	    {
+		    Excp4 e = new Excp4();
+
+		    Exception t = e;
+		    Assert.IsTrue( t is Exception );
+		    //Assert.IsFalse( t is Exception );
+	    }
+    	
+	    [Test]
+	    public void method_nothing()  
+	    {
+		    test.nothing();
+	    }
+    	
+	    [Test]
+	    public void method_incr1()  
+	    {
+		    Assert.AreEqual( 2, test.incr( 1 ) );
+	    }
+    	
+	    [Test]
+	    public void method_incr2()  
+	    {
+		    Assert.AreEqual( 3, test.incr( 2 ) );
+	    }
+    	
+	    [Test]
+	    public void method_incr3()  
+	    {
+		    Assert.AreEqual( -1, test.incr( -2 ) );
+	    }
+    	
+	    [Test]
+	    public void method_sub1()  
+	    {
+		    Assert.AreEqual( 5, test.sub( 7, 2 ) );
+	    }
+    	
+	    [Test]
+	    public void method_sub2()  
+	    {
+		    Assert.AreEqual( 8, test.sub( 23, 15 ) );
+	    }
+    	
+	    [Test]
+	    public void method_sub3()  
+	    {
+		    Assert.AreEqual( -5, test.sub( 2, 7 ) );
+	    }
+    	
+	    [Test]
+	    public void method_sum()  
+	    {
+		    Assert.AreEqual( 24, test.sum( new int[] { 1, 2, 3, 7, 11 } ) );
+	    }
+    	
+	    [Test]
+	    public void method_trans1()  
+	    {
+		    Assert.AreEqual( 2, test.trans( E1.A, 5 ) ); // divide by 2
+	    }
+    	
+	    [Test]
+	    public void method_trans2()  
+	    {
+		    Assert.AreEqual( 10, test.trans( E1.B, 5 ) ); // mul by 2
+	    }
+    	
+	    [Test]
+	    public void method_trans3()  
+	    {
+		    Assert.AreEqual( 12, test.trans( E1.C, 5 ) ); // add 7
+	    }
+    	
+	    [Test]
+	    public void method_dist1()  
+	    {
+		    Assert.AreEqual( Math.Sqrt( 3 ), test.dist( new S1( 1, 1, 1 ), new S1( 0, 0, 0 ) ) );
+	    }
+    	
+	    [Test]
+	    public void method_dist2()  
+	    {
+		    Assert.AreEqual( Math.Sqrt( 35 ), test.dist( new S1( 1, 2, 3 ), new S1( 6, 5, 4 ) ) );
+	    }
+    	
+	    [Test]
+	    public void method_dist3()  
+	    {
+		    Assert.AreEqual( Math.Sqrt( 56 ), test.dist( new S1( 1, 2, 3 ), new S1( -1, -2, -3 ) ) );
+	    }
+    	
+	    [Test]
+	    public void method_fill1()  
+	    {
+		    int[] x = test.fill( 0, 1 );
+		    Assert.AreEqual( 0, x.Length );
+		    foreach (int i in x)
+			    Assert.AreEqual( 1, i );
+	    }
+    	
+	    [Test]
+	    public void method_fill2()  
+	    {
+		    int[] x = test.fill( 1, 2 );
+		    Assert.AreEqual( 1, x.Length );
+		    foreach (int i in x)
+			    Assert.AreEqual( 2, i );
+	    }
+    	
+	    [Test]
+	    public void method_fill3()  
+	    {
+		    int[] x = test.fill( 2, 3 );
+		    Assert.AreEqual( 2, x.Length );
+		    foreach (int i in x)
+			    Assert.AreEqual( 3, i );
+	    }
+    	
+	    [Test]
+	    public void method_blow1()  
+	    {
+		    try
+		    {
+			    test.blow( "foo", 2 );
+                Assert.IsTrue( false, "blow did not throw" );
+		    }
+		    catch( Excp1 e )
+		    {
+			    Assert.AreEqual( "foo", e.msg );
+			    Assert.AreEqual( 2, e.code );
+		    }
+	    }
+    	
+	    [Test]
+	    public void method_blow2()  
+	    {
+		    try
+		    {
+			    test.blow( "bar", 3 );
+                Assert.IsTrue( false, "blow did not throw" );
+		    }
+		    catch( Excp1 e )
+		    {
+			    Assert.AreEqual( "bar", e.msg );
+			    Assert.AreEqual( 3, e.code );
+		    }
+	    }
+    	
+	    [Test]
+	    public void method_beets1()  
+	    {
+		    Assert.AreEqual( 5, test.beets( E1.A ) );
+	    }
+    	
+	    [Test]
+	    public void method_beets2()  
+	    {
+		    try
+		    {
+			    test.beets( E1.B );
+                Assert.IsTrue( false, "beets did not throw" );
+		    }
+		    catch ( Excp3 )
+		    {
+			    Assert.IsTrue( true );
+		    }
+	    }
+    	
+	    [Test]
+	    public void method_beets3()  
+	    {
+		    try
+		    {
+			    test.beets( E1.C );
+			    Assert.IsTrue(false, "beets did not throw" );
+		    }
+		    catch ( Excp4 )
+		    {
+			    Assert.IsTrue( true );
+		    }
+	    }
+    	
+        //[Test]
+        //public void method_beets4()  
+        //{
+        //    Assert.IsNull( test.beets( null ) );
+        //}
+
+     
+	 
+	    //
+        //Verify that an object can be passed as a parameter in a stuct.
+        //
+        [Test]
+	    public void struct_S3() 
+	    {
+		    testS3Helper( "bool", ConstsTest1.BOOL2 );
+            testS3Helper( "byte", ConstsTest1.BYTE5 );
+            testS3Helper( "short", ConstsTest1.SHORT5 );
+            testS3Helper("int", ConstsTest1.INT5);
+            testS3Helper("long", ConstsTest1.LONG5);
+            testS3Helper("float", ConstsTest1.FLOAT5);
+            testS3Helper("double", ConstsTest1.DOUBLE5);
+            testS3Helper("string", ConstsTest1.STRING3);		
+	    }
+    	
+	    /*
+	     * Verify that an array of objects can be passed as a parameter 
+	     * in a stuct.
+	     */
+	    [Test]
+	    public void struct_S4() 
+	    {		
+		    int sz = 10;
+    		
+		    testS4Helper(sz, "boolean", ConstsTest1.BOOL2 );
+		    testS4Helper(sz, "byte", ConstsTest1.BYTE5 );
+		    testS4Helper(sz, "short", ConstsTest1.SHORT5 );
+            testS4Helper(sz, "int", ConstsTest1.INT5);
+            testS4Helper(sz, "long", ConstsTest1.LONG5);
+            testS4Helper(sz, "float", ConstsTest1.FLOAT5);
+            testS4Helper(sz, "double", ConstsTest1.DOUBLE5);
+            testS4Helper(sz, "string", ConstsTest1.STRING3);		
+
+	    }
+    	
+	    // Verify that an object can be passed as a parameter in an
+	    // exception
+	    [Test]
+	    public void except_Excp5() 
+	    {
+		    int code = 500;
+		    String msg = "Excp5";
+
+            testExcp5Helper(msg, code, ConstsTest1.BOOL1);
+		    testExcp5Helper (msg, code, ConstsTest1.BYTE5);
+		    testExcp5Helper (msg, code, ConstsTest1.SHORT5);
+            testExcp5Helper(msg, code, ConstsTest1.INT5);
+            testExcp5Helper(msg, code, ConstsTest1.LONG5);
+            testExcp5Helper(msg, code, ConstsTest1.FLOAT5);
+            testExcp5Helper(msg, code, ConstsTest1.DOUBLE5);
+            testExcp5Helper(msg, code, ConstsTest1.STRING3);		
+	    }
+    	
+	    [Test]
+	    public void except_Excp6() 
+	    {
+		    int sz = 10;
+		    int code = 500;
+		    String msg = "Excp6";
+
+            testExcp6Helper(sz, msg, code, ConstsTest1.BOOL1);
+		    testExcp6Helper( sz, msg, code, ConstsTest1.BYTE5 );
+		    testExcp6Helper( sz, msg, code, ConstsTest1.SHORT5 );
+            testExcp6Helper(sz, msg, code, ConstsTest1.INT5);
+            testExcp6Helper(sz, msg, code, ConstsTest1.LONG5);
+            testExcp6Helper(sz, msg, code, ConstsTest1.FLOAT5);
+            testExcp6Helper(sz, msg, code, ConstsTest1.DOUBLE5);
+            testExcp6Helper(sz, msg, code, ConstsTest1.STRING3);		
+	    }
+    	
+	    [Test]
+	    public void method_throwExcp5() 
+	    {
+		    String msg = "throwExcp5";
+		    int code = 500;
+
+            method_throwExcp5Helper(msg, code, ConstsTest1.BOOL1);
+		    method_throwExcp5Helper( msg, code, ConstsTest1.BYTE5 );
+		    method_throwExcp5Helper( msg, code, ConstsTest1.SHORT5 );
+            method_throwExcp5Helper(msg, code, ConstsTest1.INT5);
+            method_throwExcp5Helper(msg, code, ConstsTest1.LONG5);
+            method_throwExcp5Helper(msg, code, ConstsTest1.FLOAT5);
+            method_throwExcp5Helper(msg, code, ConstsTest1.DOUBLE5);
+            method_throwExcp5Helper(msg, code, ConstsTest1.STRING3);		
+	    }
+    	
+	    [Test]
+	    public void method_throwExcp6() 
+	    {
+		    String msg = "throwExcp6";
+		    int code = 500;
+		    int sz = 10;
+
+            method_throwExcp6Helper(sz, msg, code, ConstsTest1.BOOL1);
+		    method_throwExcp6Helper( sz, msg, code, ConstsTest1.BYTE5 );
+		    method_throwExcp6Helper( sz, msg, code, ConstsTest1.SHORT5 );
+            method_throwExcp6Helper(sz, msg, code, ConstsTest1.INT5);
+            method_throwExcp6Helper(sz, msg, code, ConstsTest1.LONG5);
+            method_throwExcp6Helper(sz, msg, code, ConstsTest1.FLOAT5);
+            method_throwExcp6Helper(sz, msg, code, ConstsTest1.DOUBLE5);
+            method_throwExcp6Helper(sz, msg, code, ConstsTest1.STRING3);		
+
+	    }
+
+        #region Helper methods
+
+        private void testS3Helper( string type, object value )
+	    {
+		    S3 s = new S3( type, value );
+		    Assert.AreEqual( type, s.tipe );
+		    Assert.AreEqual( value, s.x );
+    		
+		    s = new S3( null, null );
+            Assert.IsNull(s.tipe);
+		    Assert.IsNull( s.x );
+    		
+		    s = new S3();
+		    Assert.IsNull( s.tipe );
+		    Assert.IsNull( s.x );
+    		
+		    s.tipe = type;
+		    s.x = value;	
+		    Assert.AreEqual( type, s.tipe );
+		    Assert.AreEqual( value, s.x );
+    		
+		    s.x = null;
+		    Assert.IsNull( s.x );
+    		
+		    s.x = value;
+		    Assert.AreEqual( value, s.x );
+	    }
+
+        public void testS4Helper( int sz, string type, object value )
+        {
+            object[] myObject = test.fillObject( sz, value );
+            S4 s = new S4( type, myObject );
+            Assert.AreEqual( type, s.tipe );
+            Assert.AreEqual( sz, myObject.Length );
+
+            for ( int i = 0; i < myObject.Length; i++ )
+                Assert.AreEqual( value, myObject[ i ] );
+        }
+
+
+        private void testExcp5Helper( String msg, int code, Object value )
+	    {
+		    Excp5 e = new Excp5( msg, code, value );
+		    Assert.AreEqual( msg, e.msg );
+		    Assert.AreEqual( code, e.code );
+		    Assert.AreEqual( value, e.x);
+    		
+		    e = new Excp5( null, null, null );
+		    Assert.IsNull( e.msg );
+		    Assert.IsNull( e.code );
+		    Assert.IsNull( e.x);
+
+		    e = new Excp5();
+		    Assert.IsNull( e.msg );
+		    Assert.IsNull( e.code );
+		    Assert.IsNull( e.x );
+    		
+		    e.msg = msg;
+		    e.code = code;
+		    e.x = value;
+    		
+		    Assert.AreEqual( msg, e.msg );
+		    Assert.AreEqual( code, e.code );
+		    Assert.AreEqual( value, e.x );
+    		
+		    e.msg = null;
+		    e.code = null;
+		    e.x = null;
+    		
+		    Assert.IsNull( e.msg );
+		    Assert.IsNull( e.code );
+		    Assert.IsNull( e.x );		
+
+		    //Throwable t = e;
+		    Assert.IsTrue( e is Exception );
+		    //assertFalse( t instanceof RuntimeException );
+	    }
+
+        private void testExcp6Helper( int sz, String msg, int code, Object value )
+        {
+	        Object[] myObject = test.fillObject( sz, value );
+    		
+	        Excp6 e = new Excp6( msg, code, myObject );
+	        Assert.AreEqual( msg, e.msg );
+	        Assert.AreEqual( code, e.code );
+
+	        for ( int i = 0; i < myObject.Length; i++ ) 
+	        {
+		        Assert.AreEqual( value, myObject[i] );
+	        }
+    		
+	        e = new Excp6( null, null, null );
+	        Assert.IsNull( e.msg );
+	        Assert.IsNull( e.code );
+	        Assert.IsNull( e.x );
+
+	        e = new Excp6();
+	        Assert.IsNull( e.msg );
+	        Assert.IsNull( e.code );
+	        Assert.IsNull( e.x );
+    		
+	        e.msg = msg;
+	        e.code = code;
+	        e.x = myObject;
+    		
+	        Assert.AreEqual( msg, e.msg );
+	        Assert.AreEqual( code, e.code );
+    		
+	        for ( int i = 0; i < myObject.Length ; i++ ) 
+	        {
+		        Assert.AreEqual( value, myObject[i] );
+	        }
+    		
+	        e.msg = null;
+	        e.code = null;
+	        e.x = null;
+    		
+	        Assert.IsNull( e.msg );
+	        Assert.IsNull( e.code );
+	        Assert.IsNull( e.x );		
+
+
+	        //Exception t = e;
+	        Assert.IsTrue( e is Exception );
+	        // assertFalse( t is RuntimeException );
+        }
+
+        private void method_throwExcp5Helper( String msg, int code, Object value )
+        {
+            try
+            {
+                test.throwExcp5( msg, code, value );
+                Assert.Fail( "throwExcp5 did not throw" );
+            }
+            catch ( Excp5 e )
+            {
+                Assert.AreEqual( msg, e.msg );
+                Assert.AreEqual( code, e.code );
+                Assert.AreEqual( value, e.x );
+            }
+        }
+
+        private void method_throwExcp6Helper( int sz, String msg, int code, Object value )
+        {
+            Object[] myObject = test.fillObject( sz, value );
+
+            try
+            {
+                test.throwExcp6( msg, code, myObject );
+                Assert.Fail( "throwExcp5 did not throw" );
+            }
+            catch ( Excp6 e )
+            {
+                Assert.AreEqual( msg, e.msg );
+                Assert.AreEqual( code, e.code );
+
+                for ( int i = 0; i < myObject.Length; i++ )
+                {
+                    Assert.AreEqual( value, e.x[ i ] );
+                }
+            }
+        }
+
+        private void method_fillObjectHelper( int sz, Object value )
+        {
+            Object[] myObject = test.fillObject( sz, value );
+
+            for ( int i = 0; i < myObject.Length; i++ )
+            {
+                Assert.AreEqual( value, myObject[ i ] );
+            }
+        }
+
+        #endregion
+
+        private Test1 test = new FakeTest1();
+    }
+}
diff --git a/tests/src/test/csharp/etch.tests/TestTest1Helper.cs b/tests/src/test/csharp/etch.tests/TestTest1Helper.cs
new file mode 100644
index 0000000..327baad
--- /dev/null
+++ b/tests/src/test/csharp/etch.tests/TestTest1Helper.cs
@@ -0,0 +1,91 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using Org.Apache.Etch.Bindings.Csharp.Support;
+using Org.Apache.Etch.Bindings.Csharp.Transport;
+using Org.Apache.Etch.Bindings.Csharp.Util;
+using NUnit.Framework;
+using org.apache.etch.tests;
+
+namespace etch.tests
+{
+    [TestFixture]
+    public class TestTest1Helper
+    {
+        public static ServerFactory listener;
+        
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestHelper" );
+        }
+
+        [SetUp]
+        public void Method_OpenNewTestListener()
+        {
+            TransportFactory.Define("blah", new TcpTransportFactory(false));
+
+            string uri = "blah://localhost:4040";
+
+            MainTest1Listener implFactory = new MainTest1Listener();
+
+            listener = Test1Helper.NewListener( uri, null, implFactory );
+            listener.TransportControl( TransportConsts.START_AND_WAIT_UP, 4000 );
+        }
+
+        [Test]
+        public void Method_NewTestServer()
+        {
+            Boolean flag = true;
+
+            string uri = "blah://localhost:4040";
+
+            MainTest1Client client = new MainTest1Client();
+
+            RemoteTest1Server server;
+
+            try
+            {
+                server = Test1Helper.NewServer( uri, null, client );
+                server._StartAndWaitUp( 4000 );
+
+                // Insert your code here
+                // -----------------------------------------------------------------------
+
+                server._Stop();
+            }
+            catch ( Exception e )
+            {
+                flag = false;
+                Console.WriteLine( e );
+                Assert.IsTrue(flag);
+            }
+
+            Assert.IsTrue( flag );
+        }
+
+        [TearDown]
+        public void Method_CloseNewTestListener()
+        {
+            listener.TransportControl( TransportConsts.STOP_AND_WAIT_DOWN, 0 );
+        }
+    }
+}
diff --git a/tests/src/test/csharp/etch.tests/TestValueFactoryTest1DotCsharp.cs b/tests/src/test/csharp/etch.tests/TestValueFactoryTest1DotCsharp.cs
new file mode 100644
index 0000000..89eb374
--- /dev/null
+++ b/tests/src/test/csharp/etch.tests/TestValueFactoryTest1DotCsharp.cs
@@ -0,0 +1,1112 @@
+// $Id$
+// 
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+using System;
+using System.Collections.Generic;
+using Org.Apache.Etch.Bindings.Csharp.Msg;
+using NUnit.Framework;
+using org.apache.etch.tests;
+using org.apache.etch.tests.types.Test1;
+
+namespace etch.tests
+{
+    [TestFixture]
+    public class TestValueFactoryTest1DotCsharp
+    {
+        private ValueFactoryTest1 vf = new ValueFactoryTest1("none:");
+
+        [TestFixtureSetUp]
+        public void First()
+        {
+            Console.WriteLine();
+            Console.Write( "TestVF" );
+        }
+
+	    [Test]
+	    public void test_E1()
+	    {
+		    // type //
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_E1,
+                       
+		            ValueFactoryTest1._mf_A,
+		   ValueFactoryTest1._mf_B,
+		   ValueFactoryTest1._mf_C );
+	    }
+    	
+	    [Test]
+	    public void test_E1_export()
+	    {
+            testEnumExport( E1.A,
+			    ValueFactoryTest1._mt_org_apache_etch_tests_Test1_E1,
+			    ValueFactoryTest1._mf_A );
+
+            testEnumExport( E1.B,
+			    ValueFactoryTest1._mt_org_apache_etch_tests_Test1_E1,
+			    ValueFactoryTest1._mf_B );
+
+            testEnumExport( E1.C,
+			    ValueFactoryTest1._mt_org_apache_etch_tests_Test1_E1,
+			    ValueFactoryTest1._mf_C );
+	    }
+    	
+	    [Test]
+	    public void test_E1_import()
+	    {
+            testEnumImport( E1.A,
+			    ValueFactoryTest1._mt_org_apache_etch_tests_Test1_E1,
+			    ValueFactoryTest1._mf_A );
+
+            testEnumImport( E1.B,
+			    ValueFactoryTest1._mt_org_apache_etch_tests_Test1_E1,
+			    ValueFactoryTest1._mf_B );
+
+            testEnumImport( E1.C,
+			    ValueFactoryTest1._mt_org_apache_etch_tests_Test1_E1,
+			    ValueFactoryTest1._mf_C );
+	    }
+
+	    [Test]
+	    public void test_S1()
+	    {
+		    // type //
+
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S1, 
+    		
+		    // fields //
+    		
+		 ValueFactoryTest1._mf_x,
+		    ValueFactoryTest1._mf_y,
+		    ValueFactoryTest1._mf_z );
+	    }
+    	
+	    [Test]
+	    public void test_S1_export()
+	    {
+            StructValue sv = vf.ExportCustomValue( new S1( 19, 23, 29 ) );
+		    sv.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S1 );
+		    Assert.AreEqual( 3, sv.Count );
+		    Assert.AreEqual( 19, sv.Get( ValueFactoryTest1._mf_x ) );
+		    Assert.AreEqual( 23, sv.Get( ValueFactoryTest1._mf_y ) );
+		    Assert.AreEqual( 29, sv.Get( ValueFactoryTest1._mf_z ) );
+	    }
+    	
+	    [Test]
+	    public void test_S1_import()
+	    {
+            StructValue sv = new StructValue(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S1, vf);
+		    sv.Add( ValueFactoryTest1._mf_x, 101 );
+		    sv.Add( ValueFactoryTest1._mf_y, 103 );
+		    sv.Add( ValueFactoryTest1._mf_z, 107 );
+            S1 s = ( S1 ) vf.ImportCustomValue( sv );
+		    Assert.AreEqual( 101, s.x );
+		    Assert.AreEqual( 103, s.y );
+		    Assert.AreEqual( 107, s.z );
+	    }
+
+	    [Test]
+	    public void test_S2()
+	    {
+		    // type //
+
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S2,
+   
+		    ValueFactoryTest1._mf_a,
+		    ValueFactoryTest1._mf_b,
+		    ValueFactoryTest1._mf_c );
+	    }
+    	
+	    [Test]
+	    public void test_S2_export()
+	    {
+            S1 a = new S1( 21, 22, 23 );
+            S1 b = new S1( 31, 32, 33 );
+            E1 c = E1.A;
+
+            StructValue sv = vf.ExportCustomValue( new S2( a, b, c ) );
+		    sv.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S2 );
+		    Assert.AreEqual( 3, sv.Count );
+    		
+		    Assert.AreEqual( a, sv.Get( ValueFactoryTest1._mf_a ) );
+		    Assert.AreEqual( b, sv.Get( ValueFactoryTest1._mf_b ) );
+		    Assert.AreEqual( c, sv.Get( ValueFactoryTest1._mf_c ) );
+	    }
+    	
+	    [Test]
+	    public void test_S2_import()
+	    {
+            StructValue sv = new StructValue(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S2, vf);
+
+            sv.Add( ValueFactoryTest1._mf_a, new S1( 21, 22, 23 ) );
+            sv.Add( ValueFactoryTest1._mf_b, new S1( 31, 32, 33 ) );
+            sv.Add( ValueFactoryTest1._mf_c, E1.A );
+
+            S2 s = ( S2 ) vf.ImportCustomValue( sv );
+		    Assert.AreEqual( 21, s.a.x );
+		    Assert.AreEqual( 22, s.a.y );
+		    Assert.AreEqual( 23, s.a.z );
+		    Assert.AreEqual( 31, s.b.x );
+		    Assert.AreEqual( 32, s.b.y );
+		    Assert.AreEqual( 33, s.b.z );
+            Assert.AreEqual( E1.A, s.c );
+	    }
+    	
+        [Test]
+        public void test_S3()
+	    {
+		    // type //
+
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S3,
+    		
+		    // fields //
+	//	    ValueFactoryTest1._mf_type1,
+            ValueFactoryTest1._mf_tipe,
+		    ValueFactoryTest1._mf_x );
+	    }
+    	
+	    [Test]
+	    public void test_S3_export()
+	    {		
+		    testS3Export("boolean", ConstsTest1.BOOL1);
+		    testS3Export("byte", ConstsTest1.BYTE5);
+		    testS3Export("short", ConstsTest1.SHORT5);
+		    testS3Export("int", ConstsTest1.INT5);
+		    testS3Export("long", ConstsTest1.LONG5);
+		    testS3Export("float", ConstsTest1.FLOAT5);
+		    testS3Export("double", ConstsTest1.DOUBLE5);
+		    testS3Export("string", ConstsTest1.STRING3);
+	    }
+    	
+	    [Test]
+	    public void test_S3_import()
+	    {
+		    testS3Import("boolean", ConstsTest1.BOOL1);
+		    testS3Import("byte", ConstsTest1.BYTE5);
+		    testS3Import("short", ConstsTest1.SHORT5);
+		    testS3Import("int", ConstsTest1.INT5);
+		    testS3Import("long", ConstsTest1.LONG5);
+		    testS3Import("float", ConstsTest1.FLOAT5);
+		    testS3Import("double", ConstsTest1.DOUBLE5);
+		    testS3Import("string", ConstsTest1.STRING3);
+	    }
+    	
+	    [Test]
+	    public void test_S4()
+	    {
+		    // type //
+
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S4,
+    		
+		    // fields //
+		     ValueFactoryTest1._mf_tipe,
+		    ValueFactoryTest1._mf_x );
+	    }
+    	
+	    [Test]
+	    public void test_S4_export()
+	    {	
+		    Object[] boolObject = new Object[] {ConstsTest1.BOOL1, ConstsTest1.BOOL2};
+		    Object[] byteObject = new Object[] {ConstsTest1.BYTE1, ConstsTest1.BYTE2, ConstsTest1.BYTE3, ConstsTest1.BYTE4, ConstsTest1.BYTE5};
+		    Object[] shortObject = new Object[] {ConstsTest1.SHORT1, ConstsTest1.SHORT2, ConstsTest1.SHORT3, ConstsTest1.SHORT4, ConstsTest1.SHORT5};
+		    Object[] intObject = new Object[]{ConstsTest1.INT1, ConstsTest1.INT2, ConstsTest1.INT3, ConstsTest1.INT4, ConstsTest1.INT5};
+		    Object[] longObject = new Object[] {ConstsTest1.LONG1, ConstsTest1.LONG2, ConstsTest1.LONG3, ConstsTest1.LONG4, ConstsTest1.LONG5};
+		    Object[] floatObject = new Object[]{ConstsTest1.FLOAT1, ConstsTest1.FLOAT2, ConstsTest1.FLOAT3, ConstsTest1.FLOAT4, ConstsTest1.FLOAT5};
+		    Object[] doubleObject = new Object[] {ConstsTest1.DOUBLE1, ConstsTest1.DOUBLE2, ConstsTest1.DOUBLE3, ConstsTest1.DOUBLE4, ConstsTest1.DOUBLE5};
+		    Object[] stringObject = new Object []{ConstsTest1.STRING1, ConstsTest1.STRING2, ConstsTest1.STRING3, ConstsTest1.STRING4, ConstsTest1.STRING5};
+
+		    testS4Export("boolean", boolObject);
+		    testS4Export("byte", byteObject);
+		    testS4Export("short", shortObject);
+		    testS4Export("int", intObject);
+		    testS4Export("long", longObject);
+		    testS4Export("float", floatObject);
+		    testS4Export("double", doubleObject);
+		    testS4Export("string", stringObject);
+	    }
+    	
+	    [Test]
+	    public void test_S4_import()
+	    {
+		    Object[] boolObject = new Object[] {ConstsTest1.BOOL1, ConstsTest1.BOOL2};
+		    Object[] byteObject = new Object[] {ConstsTest1.BYTE1, ConstsTest1.BYTE2, ConstsTest1.BYTE3, ConstsTest1.BYTE4, ConstsTest1.BYTE5};
+		    Object[] shortObject = new Object[] {ConstsTest1.SHORT1, ConstsTest1.SHORT2, ConstsTest1.SHORT3, ConstsTest1.SHORT4, ConstsTest1.SHORT5};
+		    Object[] intObject = new Object[]{ConstsTest1.INT1, ConstsTest1.INT2, ConstsTest1.INT3, ConstsTest1.INT4, ConstsTest1.INT5};
+		    Object[] longObject = new Object[] {ConstsTest1.LONG1, ConstsTest1.LONG2, ConstsTest1.LONG3, ConstsTest1.LONG4, ConstsTest1.LONG5};
+		    Object[] floatObject = new Object[]{ConstsTest1.FLOAT1, ConstsTest1.FLOAT2, ConstsTest1.FLOAT3, ConstsTest1.FLOAT4, ConstsTest1.FLOAT5};
+		    Object[] doubleObject = new Object[] {ConstsTest1.DOUBLE1, ConstsTest1.DOUBLE2, ConstsTest1.DOUBLE3, ConstsTest1.DOUBLE4, ConstsTest1.DOUBLE5};
+		    Object[] stringObject = new Object []{ConstsTest1.STRING1, ConstsTest1.STRING2, ConstsTest1.STRING3, ConstsTest1.STRING4, ConstsTest1.STRING5};
+
+		    testS4Import("boolean", boolObject);
+		    testS4Import("byte", byteObject);
+		    testS4Import("short", shortObject);
+		    testS4Import("int", intObject);
+		    testS4Import("long", longObject);
+		    testS4Import("float", floatObject);
+		    testS4Import("double", doubleObject);
+		    testS4Import("string", stringObject);
+	    }	
+
+	    [Test]
+	    public void test_excps()
+	    {
+		    // type //
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp1, ValueFactoryTest1._mf_msg, ValueFactoryTest1._mf_code ); 
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp2 );
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp3 );
+            checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp4 );
+            checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp5, ValueFactoryTest1._mf_msg,ValueFactoryTest1._mf_code, ValueFactoryTest1._mf_x );
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp6, ValueFactoryTest1._mf_msg, ValueFactoryTest1._mf_code, ValueFactoryTest1._mf_x);
+    		
+		    // fields //
+    		
+		 //   checkField( ValueFactoryTest._mf_msg );
+          //  checkField( ValueFactoryTest._mf_code );
+          //  checkField( ValueFactoryTest._mf_x );
+	    }
+    	
+	    [Test]
+	    public void test_excps_export()
+	    {
+            Object[] boolObject = new Object[] { ConstsTest1.BOOL1, ConstsTest1.BOOL2 };
+            Object[] byteObject = new Object[] { ConstsTest1.BYTE1, ConstsTest1.BYTE2, ConstsTest1.BYTE3, ConstsTest1.BYTE4, ConstsTest1.BYTE5 };
+            Object[] shortObject = new Object[] { ConstsTest1.SHORT1, ConstsTest1.SHORT2, ConstsTest1.SHORT3, ConstsTest1.SHORT4, ConstsTest1.SHORT5 };
+            Object[] intObject = new Object[] { ConstsTest1.INT1, ConstsTest1.INT2, ConstsTest1.INT3, ConstsTest1.INT4, ConstsTest1.INT5 };
+            Object[] longObject = new Object[] { ConstsTest1.LONG1, ConstsTest1.LONG2, ConstsTest1.LONG3, ConstsTest1.LONG4, ConstsTest1.LONG5 };
+            Object[] floatObject = new Object[] { ConstsTest1.FLOAT1, ConstsTest1.FLOAT2, ConstsTest1.FLOAT3, ConstsTest1.FLOAT4, ConstsTest1.FLOAT5 };
+            Object[] doubleObject = new Object[] { ConstsTest1.DOUBLE1, ConstsTest1.DOUBLE2, ConstsTest1.DOUBLE3, ConstsTest1.DOUBLE4, ConstsTest1.DOUBLE5 };
+            Object[] stringObject = new Object[] { ConstsTest1.STRING1, ConstsTest1.STRING2, ConstsTest1.STRING3, ConstsTest1.STRING4, ConstsTest1.STRING5 };
+
+            String msg = "Exception";
+            int code = 500;
+
+		    StructValue sv = vf.ExportCustomValue( new Excp1( "abc", 23 ) );
+		    sv.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp1 );
+		    Assert.AreEqual( 2, sv.Count );
+		    Assert.AreEqual( "abc", sv.Get( ValueFactoryTest1._mf_msg ) );
+		    Assert.AreEqual( 23, sv.Get( ValueFactoryTest1._mf_code ) );
+
+            sv = vf.ExportCustomValue( new Excp2() );
+		    sv.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp2 );
+		    Assert.AreEqual( 0, sv.Count );
+
+            sv = vf.ExportCustomValue( new Excp3() );
+		    sv.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp3 );
+		    Assert.AreEqual( 0, sv.Count );
+
+            sv = vf.ExportCustomValue( new Excp4() );
+		    sv.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp4 );
+		    Assert.AreEqual( 0, sv.Count );
+
+            // Import exception with object as param
+            testExcp5Export( msg, code, ConstsTest1.BOOL2 );
+            testExcp5Export( msg, code, ConstsTest1.BYTE5 );
+            testExcp5Export( msg, code, ConstsTest1.SHORT5 );
+            testExcp5Export( msg, code, ConstsTest1.INT5 );
+            testExcp5Export( msg, code, ConstsTest1.LONG5 );
+            testExcp5Export( msg, code, ConstsTest1.FLOAT5 );
+            testExcp5Export( msg, code, ConstsTest1.DOUBLE5 );
+            testExcp5Export( msg, code, ConstsTest1.STRING3 );
+
+            // Import exception with array of object as param
+            testExcp6Export( msg, code, boolObject );
+            testExcp6Export( msg, code, byteObject );
+            testExcp6Export( msg, code, shortObject );
+            testExcp6Export( msg, code, intObject );
+            testExcp6Export( msg, code, longObject );
+            testExcp6Export( msg, code, floatObject );
+            testExcp6Export( msg, code, doubleObject );
+            testExcp6Export( msg, code, stringObject );	
+	    }
+    	
+	    [Test]
+	    public void test_excps_import()
+	    {
+
+            Object[] boolObject = new Object[] { ConstsTest1.BOOL1, ConstsTest1.BOOL2 };
+            Object[] byteObject = new Object[] { ConstsTest1.BYTE1, ConstsTest1.BYTE2, ConstsTest1.BYTE3, ConstsTest1.BYTE4, ConstsTest1.BYTE5 };
+            Object[] shortObject = new Object[] { ConstsTest1.SHORT1, ConstsTest1.SHORT2, ConstsTest1.SHORT3, ConstsTest1.SHORT4, ConstsTest1.SHORT5 };
+            Object[] intObject = new Object[] { ConstsTest1.INT1, ConstsTest1.INT2, ConstsTest1.INT3, ConstsTest1.INT4, ConstsTest1.INT5 };
+            Object[] longObject = new Object[] { ConstsTest1.LONG1, ConstsTest1.LONG2, ConstsTest1.LONG3, ConstsTest1.LONG4, ConstsTest1.LONG5 };
+            Object[] floatObject = new Object[] { ConstsTest1.FLOAT1, ConstsTest1.FLOAT2, ConstsTest1.FLOAT3, ConstsTest1.FLOAT4, ConstsTest1.FLOAT5 };
+            Object[] doubleObject = new Object[] { ConstsTest1.DOUBLE1, ConstsTest1.DOUBLE2, ConstsTest1.DOUBLE3, ConstsTest1.DOUBLE4, ConstsTest1.DOUBLE5 };
+            Object[] stringObject = new Object[] { ConstsTest1.STRING1, ConstsTest1.STRING2, ConstsTest1.STRING3, ConstsTest1.STRING4, ConstsTest1.STRING5 };
+
+            String msg = "Exception";
+            int code = 500;
+
+            StructValue sv = new StructValue(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp1, vf);
+		    sv.Add( ValueFactoryTest1._mf_msg, "def" );
+		    sv.Add( ValueFactoryTest1._mf_code, 29 );
+            Excp1 e1 = ( Excp1 ) vf.ImportCustomValue( sv );
+		    Assert.AreEqual( "def", e1.msg );
+		    Assert.AreEqual( 29, e1.code );
+		    e1 = null;
+
+            sv = new StructValue(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp2, vf);
+            Excp2 e2 = ( Excp2 ) vf.ImportCustomValue( sv );
+		    Assert.IsNotNull( e2 );
+		    e2 = null;
+
+            sv = new StructValue(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp3, vf);
+            Excp3 e3 = ( Excp3 ) vf.ImportCustomValue( sv );
+		    Assert.IsNotNull( e3 );
+		    e3 = null;
+
+            sv = new StructValue(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp4, vf);
+            Excp4 e4 = ( Excp4 ) vf.ImportCustomValue( sv );
+		    Assert.IsNotNull( e4 );
+		    e4 = null;
+
+            // Import exception with object as param
+            testExcp5Import( msg, code, ConstsTest1.BOOL2 );
+            testExcp5Import( msg, code, ConstsTest1.BYTE5 );
+            testExcp5Import( msg, code, ConstsTest1.SHORT5 );
+            testExcp5Import( msg, code, ConstsTest1.INT5 );
+            testExcp5Import( msg, code, ConstsTest1.LONG5 );
+            testExcp5Import( msg, code, ConstsTest1.FLOAT5 );
+            testExcp5Import( msg, code, ConstsTest1.DOUBLE5 );
+            testExcp5Import( msg, code, ConstsTest1.STRING3 );
+
+            // Import exception with array of object as param
+            testExcp6Import( msg, code, boolObject );
+            testExcp6Import( msg, code, byteObject );
+            testExcp6Import( msg, code, shortObject );
+            testExcp6Import( msg, code, intObject );
+            testExcp6Import( msg, code, longObject );
+            testExcp6Import( msg, code, floatObject );
+            testExcp6Import( msg, code, doubleObject );
+            testExcp6Import( msg, code, stringObject );	
+	    }
+    	
+	    [Test]
+	    public void test_method_nothing()
+	    {
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_nothing, ValueFactoryTest1._mf__messageId);
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_nothing, 
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+			ValueFactoryTest1._mf_result );
+		
+	    }
+    	
+	    [Test]
+	    public void test_method_incr()
+	    {
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_incr, ValueFactoryTest1._mf__messageId,
+        ValueFactoryTest1._mf_x);
+
+
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_incr, ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+		    
+	    }
+    	
+	    [Test]
+	    public void test_method_sub()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sub, ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_x, ValueFactoryTest1._mf_y );
+
+
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sub, ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo, ValueFactoryTest1._mf_result);
+		
+	    }
+    	
+	    [Test]
+	    public void test_method_sum()
+	    {
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sum, ValueFactoryTest1._mf__messageId,
+        ValueFactoryTest1._mf_x);
+
+
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sum, ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+		 
+	    }
+    	
+	    [Test]
+	    public void test_method_trans()
+	    {
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_trans, ValueFactoryTest1._mf__messageId,
+        ValueFactoryTest1._mf_e,
+        ValueFactoryTest1._mf_x);
+
+
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans, ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+		
+	    }
+    	
+	    [Test]
+	    public void test_method_dist()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_dist,
+                ValueFactoryTest1._mf__messageId,
+		    ValueFactoryTest1._mf_a,
+		    ValueFactoryTest1._mf_b );
+
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_dist, ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+		
+	    }
+    	
+	    [Test]
+	    public void test_method_fill()
+	    {
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_fill, ValueFactoryTest1._mf__messageId,
+		    ValueFactoryTest1._mf_n, ValueFactoryTest1._mf_x );
+
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fill, ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+		   
+	    }
+    	
+        [Test]
+	    public void test_method_fillObject()
+	    {
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_fillObject, ValueFactoryTest1._mf__messageId,
+		    ValueFactoryTest1._mf_n, ValueFactoryTest1._mf_o );
+
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fillObject, ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+		   
+	    }
+    	
+
+	    [Test]
+	    public void test_method_blow()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_blow , ValueFactoryTest1._mf__messageId,
+		    ValueFactoryTest1._mf_msg,
+		    ValueFactoryTest1._mf_code );
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_blow, ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+		  
+	    }
+    	
+	    [Test]
+	    public void test_method_beets()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets, ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_e );   		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets, ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+		    
+	    }
+    	
+        [Test]
+	    public void test_method_throwExcp5()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_throwExcp5,
+                ValueFactoryTest1._mf__messageId,
+                ValueFactoryTest1._mf_msg,
+                 ValueFactoryTest1._mf_code,
+                 ValueFactoryTest1._mf_value);
+		
+            checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_throwExcp5,
+                ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+
+		
+	    }
+    	
+	    [Test]
+	    public void test_method_throwExcp6()
+	    {
+            checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_throwExcp5,
+                ValueFactoryTest1._mf__messageId,
+        ValueFactoryTest1._mf_msg,
+        ValueFactoryTest1._mf_code,
+        ValueFactoryTest1._mf_value);
+
+		    
+            checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_throwExcp6,
+                ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+	
+	    }
+
+	    [Test]
+	    public void test_method_p_boolean()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_boolean,
+                ValueFactoryTest1._mf__messageId,
+        ValueFactoryTest1._mf_a);
+
+		  
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean,
+                ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+		  
+	    }
+    	
+	    [Test]
+	    public void test_method_p_boolean_array()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_boolean_array,
+                ValueFactoryTest1._mf__messageId,
+        ValueFactoryTest1._mf_a);
+	
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean_array,
+                ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+		
+	    }
+    	
+	    [Test]
+	    public void test_method_p_byte()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_byte,
+                ValueFactoryTest1._mf__messageId,
+        ValueFactoryTest1._mf_a);
+	
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte,
+                ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+
+		
+	    }
+    	
+	    [Test]
+	    public void test_method_p_byte_array()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_byte_array,
+                ValueFactoryTest1._mf__messageId,
+        ValueFactoryTest1._mf_a);
+
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte_array,
+                ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+
+		   
+	    }
+    	
+	    [Test]
+	    public void test_method_p_short()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_short,
+                ValueFactoryTest1._mf__messageId,
+        ValueFactoryTest1._mf_a);
+		    
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short,
+                ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+		   
+	    }
+    	
+	    [Test]
+	    public void test_method_p_short_array()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_short_array,
+               ValueFactoryTest1._mf__messageId,
+        ValueFactoryTest1._mf_a);
+	
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short_array,
+            ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+
+
+		
+	    }
+    	
+	    [Test]
+	    public void test_method_p_int()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_int,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int,
+                ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+
+	
+	    }
+    	
+	    [Test]
+	    public void test_method_p_int_array()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_int_array ,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int_array,
+                ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+	    }
+    	
+	    [Test]
+	    public void test_method_p_long()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_long,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long,
+                ValueFactoryTest1._mf__messageId,
+            ValueFactoryTest1._mf__inReplyTo,
+        ValueFactoryTest1._mf_result);
+
+
+		
+	    }
+    	
+	    [Test]
+	    public void test_method_p_long_array()
+	    {
+	        checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_long_array,
+	                  ValueFactoryTest1._mf__messageId,
+	                  ValueFactoryTest1._mf_a);
+
+
+	        checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long_array,
+	                  ValueFactoryTest1._mf__messageId,
+	                  ValueFactoryTest1._mf__inReplyTo,
+	                  ValueFactoryTest1._mf_result);
+	    }
+
+        [Test]
+	    public void test_method_p_float()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_float,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		   
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+		    
+	    }
+    	
+	    [Test]
+	    public void test_method_p_float_array()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_float_array,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float_array,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+
+	
+	    }
+    	
+	    [Test]
+	    public void test_method_p_double()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_double,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+
+		   
+	    }
+    	
+	    [Test]
+	    public void test_method_p_double_array()
+	    {
+	        checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_double_array,
+	                  ValueFactoryTest1._mf__messageId,
+	                  ValueFactoryTest1._mf_a);
+		   
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double_array,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+
+	
+	    }
+    	
+	    [Test]
+	    public void test_method_p_string()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_string,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+
+		   
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+
+		   
+	    }
+
+        [Test]
+        public void test_method_p_string_array()
+        {
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_string_array,
+                      ValueFactoryTest1._mf__messageId,
+                      ValueFactoryTest1._mf_a);
+
+
+            checkType(ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string_array,
+                      ValueFactoryTest1._mf__messageId,
+                      ValueFactoryTest1._mf__inReplyTo,
+                      ValueFactoryTest1._mf_result);
+        }
+
+        [Test]
+	    public void test_method_p_E1()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_E1,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+
+		    
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+
+		    
+	    }
+    	
+	    [Test]
+	    public void test_method_p_E1_array()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_E1_array,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+
+
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1_array,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	
+	    }
+    	
+	    [Test]
+	    public void test_method_p_S1()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S1,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+
+	    }
+    	
+	    [Test]
+	    public void test_method_p_S1_array()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S1_array,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1_array,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	    
+	    }
+    	
+	    [Test]
+	    public void test_method_p_S2()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S2,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+		   
+	    }
+    	
+	    [Test]
+	    public void test_method_p_S2_array()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S2_array,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2_array,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+		  
+	    }
+    	
+	    [Test]
+	    public void test_method_p_Blob()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_Blob,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_Blob,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+		  
+	    }
+    	
+	    [Test]
+	    public void test_method_p_Blob_array()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_Blob_array,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_Blob_array,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+		   
+	    }
+
+        [Test]
+	    public void test_method_p_object()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_object,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		   
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+		   
+	    }
+    	
+	    [Test]
+	    public void test_method_p_object_array()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_object_array,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		   
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object_array,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+		   
+	    }
+    	
+	    [Test]
+	    public void test_method_p_object_struct()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_object_struct,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		   
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object_struct,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+		   
+	    }
+
+	    [Test]
+	    public void test_method_p_object_struct_array()
+	    {
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_object_struct_array,
+                ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		    
+    		
+		    checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object_struct_array,
+                ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+		  
+	    }
+
+	    /////////////////////
+	    // UTILITY METHODS //
+	    /////////////////////
+	    
+
+        private void checkType( XType type, params Field[] fields )
+	{
+		 Assert.IsNotNull( type );
+		Assert.AreSame( typeof(XType), type.GetType() );
+		Assert.AreSame( type, vf.GetType( type.Id ) );
+		
+		List<Field> tfields = type.GetFields();
+
+		if (fields != null)
+		{
+			Assert.AreEqual( fields.Length, tfields.Count );
+			
+			//for (Field f: fields)
+            for (int i = 0; i < fields.Length;i++ )
+            {
+                Assert.IsNotNull(type.GetValidator(fields[i]));
+                Assert.AreSame(fields[i], type.GetField(fields[i].Id));
+                Assert.AreSame(fields[i], type.GetField(fields[i].Name));
+            }
+		}
+		else
+		{
+			Assert.AreEqual( 0, tfields.Count );
+		}
+	}
+
+	   
+	    private void testEnumExport( E1 e, XType t, Field f )
+	    {
+		    StructValue sv = vf.ExportCustomValue( e );
+		    sv.CheckType( t );
+		    Assert.AreEqual( 1, sv.Count );
+		    Assert.IsTrue( (Boolean) sv.Get( f ) );
+	    }
+    	
+	    private void testEnumImport( E1 e, XType t, Field f )
+	    {
+            StructValue sv = new StructValue(t, vf);
+		    sv.Add( f, true );
+		    E1 a = (E1) vf.ImportCustomValue( sv );
+		    Assert.AreEqual( e, a );
+	    }
+
+        private void testS3Export( String s, Object value )
+        {
+            StructValue sv = vf.ExportCustomValue( new S3( s, value ) );
+            sv.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S3 );
+            Assert.AreEqual( 2, sv.Count );
+            Assert.AreEqual( s, sv[ ValueFactoryTest1._mf_tipe ] );
+            Assert.AreEqual( value, sv[ ValueFactoryTest1._mf_x ] );
+        }
+
+        private void testS3Import( String s, Object value )
+        {
+            StructValue sv = new StructValue(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S3, vf);
+            sv.Add(ValueFactoryTest1._mf_tipe, s);
+            sv.Add( ValueFactoryTest1._mf_x, value );
+            S3 myS3 = ( S3 ) vf.ImportCustomValue( sv );
+            Assert.AreEqual( s, myS3.tipe );
+            Assert.AreEqual( value, myS3.x );
+        }
+
+        private void testS4Export( String s, Object[] value )
+        {
+            StructValue sv = vf.ExportCustomValue( new S4( s, value ) );
+            sv.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S4 );
+            Assert.AreEqual( 2, sv.Count );
+            Assert.AreEqual(s, sv[ValueFactoryTest1._mf_tipe]);
+            Assert.AreEqual( value, sv[ ValueFactoryTest1._mf_x ] );
+        }
+
+        private void testS4Import( String s, Object[] value )
+        {
+            StructValue sv = new StructValue(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S4, vf);
+            sv.Add(ValueFactoryTest1._mf_tipe, s);
+            sv.Add( ValueFactoryTest1._mf_x, value );
+            S4 myS4 = ( S4 ) vf.ImportCustomValue( sv );
+            Assert.AreEqual( s, myS4.tipe );
+            Assert.AreEqual( value, myS4.x );
+        }
+
+        private void testExcp5Export( String msg, int code, Object value )
+        {
+            StructValue sv = vf.ExportCustomValue( new Excp5( msg, code, value ) );
+            sv.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp5 );
+            Assert.AreEqual( 3, sv.Count );
+            Assert.AreEqual( msg, sv[ValueFactoryTest1._mf_msg] );
+            Assert.AreEqual( code, sv[ ValueFactoryTest1._mf_code] );
+            Assert.AreEqual( value, sv[ ValueFactoryTest1._mf_x ] );
+        }
+
+        private void testExcp5Import( String msg, int code, Object value )
+        {
+            StructValue sv = new StructValue(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp5, vf);
+            sv.Add( ValueFactoryTest1._mf_msg, msg );
+            sv.Add( ValueFactoryTest1._mf_code, code );
+            sv.Add( ValueFactoryTest1._mf_x, value );
+            Excp5 e = ( Excp5 ) vf.ImportCustomValue( sv );
+            Assert.AreEqual( msg, e.msg );
+            Assert.AreEqual( code, e.code );
+            Assert.AreEqual( value, e.x );
+        }
+
+        private void testExcp6Export( String msg, int code, Object[] value )
+        {
+            StructValue sv = vf.ExportCustomValue( new Excp6( msg, code, value ) );
+            sv.CheckType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp6 );
+            Assert.AreEqual( 3, sv.Count );
+            Assert.AreEqual( msg, sv[ ValueFactoryTest1._mf_msg ] );
+            Assert.AreEqual( code, sv[ ValueFactoryTest1._mf_code]  );
+            Assert.AreEqual( value, sv[ ValueFactoryTest1._mf_x ] );
+        }
+
+        private void testExcp6Import( String msg, int code, Object[] value )
+        {
+            StructValue sv = new StructValue(ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp6, vf);
+            sv.Add( ValueFactoryTest1._mf_msg, msg );
+            sv.Add( ValueFactoryTest1._mf_code, code );
+            sv.Add( ValueFactoryTest1._mf_x, value );
+            Excp6 e = ( Excp6 ) vf.ImportCustomValue( sv );
+            Assert.AreEqual( msg, e.msg );
+            Assert.AreEqual( code, e.code );
+            Assert.AreEqual( value, e.x );
+        }
+    }
+}
diff --git a/tests/src/test/java/org/apache/etch/tests/FakeTest1.java b/tests/src/test/java/org/apache/etch/tests/FakeTest1.java
new file mode 100644
index 0000000..8ed05ef
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/FakeTest1.java
@@ -0,0 +1,517 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import org.apache.etch.bindings.java.util.StrIntHashMap;
+
+/**
+ * Silly implementation of Test used for testing.
+ */
+public class FakeTest1 implements Test1
+{
+	public Integer beets( E1 e ) throws Excp3, Excp4
+	{
+		if (e == null)
+			return null;
+		
+		switch (e)
+		{
+			case A: return 5;
+			case B: throw new Excp3();
+			case C: throw new Excp4();
+			default: return null;
+		}
+	}
+
+	public void blow( String msg, Integer code ) throws Excp1
+	{
+		throw new Excp1( msg, code );
+	}
+
+	public Double dist( S1 a, S1 b )
+	{
+		S1 c = new S1( a.x-b.x, a.y-b.y, a.z-b.z );
+		return Math.sqrt( c.x*c.x + c.y*c.y + c.z*c.z );
+	}
+
+	public Integer incr( Integer x )
+	{
+		return x+1;
+	}
+
+	public void nothing()
+	{
+		// nothing.
+	}
+
+	public Integer sub( Integer x, Integer y )
+	{
+		return x-y;
+	}
+
+	public Integer sum( int[] x )
+	{
+		int sum = 0;
+		for (int i: x)
+			sum += i;
+		return sum;
+	}
+
+	public Integer trans( E1 e, Integer x )
+	{
+		switch (e)
+		{
+			case A: return x / 2;
+			case B: return x * 2;
+			case C: return x + 7;
+			default: return null;
+		}
+	}
+
+	public int[] fill( Integer n, Integer x )
+	{
+		int[] y = new int[n];
+		for (int i = 0; i < n; i++)
+			y[i] = x;
+		return y;
+	}
+
+	// Fill numElements of an array with value o
+	public Object[] fillObject( Integer numElements, Object o )
+	{
+		Object [] y = new Object[numElements];
+		for (int i = 0; i < numElements; i++)
+			y[i] = o;
+		return y;
+	}
+	
+	public E1 p_E1( E1 a )
+	{
+		return a;
+	}
+
+	public E1[] p_E1_array( E1[] a )
+	{
+		return a;
+	}
+
+	public S1 p_S1( S1 a )
+	{
+		return a;
+	}
+
+	public S1[] p_S1_array( S1[] a )
+	{
+		return a;
+	}
+
+	public S2 p_S2( S2 a )
+	{
+		return a;
+	}
+
+	public S2[] p_S2_array( S2[] a )
+	{
+		return a;
+	}
+
+	public Boolean p_boolean( Boolean a )
+	{
+		return a;
+	}
+
+	public boolean[] p_boolean_array( boolean[] a )
+	{
+		return a;
+	}
+
+	public Byte p_byte( Byte a )
+	{
+		return a;
+	}
+
+	public byte[] p_byte_array( byte[] a )
+	{
+		return a;
+	}
+
+	public Double p_double( Double a )
+	{
+		return a;
+	}
+
+	public double[] p_double_array( double[] a )
+	{
+		return a;
+	}
+
+	public Float p_float( Float a )
+	{
+		return a;
+	}
+
+	public float[] p_float_array( float[] a )
+	{
+		return a;
+	}
+
+	public Integer p_int( Integer a )
+	{
+		return a;
+	}
+
+	public int[] p_int_array( int[] a )
+	{
+		return a;
+	}
+
+	public Long p_long( Long a )
+	{
+		return a;
+	}
+
+	public long[] p_long_array( long[] a )
+	{
+		return a;
+	}
+
+	public Short p_short( Short a )
+	{
+		return a;
+	}
+
+	public short[] p_short_array( short[] a )
+	{
+		return a;
+	}
+
+	public String p_string( String a )
+	{
+		return a;
+	}
+
+	public String[] p_string_array( String[] a )
+	{
+		return a;
+	}
+
+	public StrIntHashMap p_Blob( StrIntHashMap a )
+	{
+		return a;
+	}
+
+	public StrIntHashMap[] p_Blob_array( StrIntHashMap[] a )
+	{
+		return a;
+	}
+
+	public void alwaysFails()
+	{
+		// i'm never called.
+		throw new UnsupportedOperationException( "alwaysFails" );
+	}
+
+	public Integer alwaysWorks()
+	{
+		// i'm always called.
+		return 23;
+	}
+
+	public Boolean isFalse()
+	{
+		return false;
+	}
+
+	public Boolean isTrue()
+	{
+		return true;
+	}
+
+	public Integer add( Integer a, Integer b )
+	{
+		return a + b;
+	}
+
+	public Boolean can_m1()
+	{
+		// not needed
+		return null;
+	}
+
+	public Boolean can_m10( Double x )
+	{
+		// not needed
+		return null;
+	}
+
+	public Boolean can_m2( Boolean x )
+	{
+		// not needed
+		return null;
+	}
+
+	public Boolean can_m3( Boolean x )
+	{
+		// not needed
+		return null;
+	}
+
+	public Boolean can_m4( Boolean x )
+	{
+		// not needed
+		return null;
+	}
+
+	public Boolean can_m7( Integer x )
+	{
+		// not needed
+		return null;
+	}
+
+	public void m1()
+	{
+		// not needed
+		
+	}
+
+	public void m10()
+	{
+		// not needed
+		
+	}
+
+	public void m2()
+	{
+		// not needed
+		
+	}
+
+	public void m3()
+	{
+		// not needed
+		
+	}
+
+	public void m4()
+	{
+		// not needed
+		
+	}
+
+	public void m7()
+	{
+		// not needed
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#m11()
+	 */
+	public void m11()
+	{
+		// not needed
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#m5()
+	 */
+	public void m5()
+	{
+		// not needed
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#m6()
+	 */
+	public void m6()
+	{
+		// not needed
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#m8()
+	 */
+	public void m8()
+	{
+		// not needed
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#m9()
+	 */
+	public void m9()
+	{
+		// not needed
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#can_m11(java.lang.String)
+	 */
+	public Boolean can_m11( String x )
+	{
+		// not needed
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#can_m5(java.lang.Byte)
+	 */
+	public Boolean can_m5( Byte x )
+	{
+		// not needed
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#can_m6(java.lang.Short)
+	 */
+	public Boolean can_m6( Short x )
+	{
+		// not needed
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#can_m8(java.lang.Long)
+	 */
+	public Boolean can_m8( Long x )
+	{
+		// not needed
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#can_m9(java.lang.Float)
+	 */
+	public Boolean can_m9( Float x )
+	{
+		// not needed
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#can_m12(java.lang.Integer)
+	 */
+	public Boolean can_m12( Integer x )
+	{
+		// not needed
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#can_m13(java.lang.Integer)
+	 */
+	public Boolean can_m13( Integer x )
+	{
+		// not needed
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#can_m14(java.lang.Integer)
+	 */
+	public Boolean can_m14( Integer x )
+	{
+		// not needed
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#can_m15(etch.tests.Test.E1)
+	 */
+	public Boolean can_m15( E1 x )
+	{
+		// not needed
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#m12()
+	 */
+	public void m12()
+	{
+		// not needed
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#m13(java.lang.Integer)
+	 */
+	public void m13( Integer k )
+	{
+		// not needed
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#m14(etch.tests.Test.S1)
+	 */
+	public void m14( S1 k )
+	{
+		// not needed
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see etch.tests.Test#m15()
+	 */
+	public void m15()
+	{
+		// not needed
+		
+	}
+
+	public Object p_object(Object a) {
+		// not needed
+		return a;
+	}
+
+	public Object[] p_object_array(Object[] a) {
+		// not needed
+		return a;
+	}
+
+	public S3 p_object_struct(S3 a) {
+		// not needed
+		return a;
+	}
+
+	public S4 p_object_struct_array(S4 a) {
+		// not needed
+		return a;
+	}
+
+	public void throwExcp5(String msg, Integer code, Object value) throws Excp5 {
+		// not needed
+		throw new Excp5( msg, code, value );
+	}
+
+	public void throwExcp6(String msg, Integer code, Object[] value) throws Excp6 {
+		// not needed
+		throw new Excp6( msg, code, value );		
+	}
+
+}
\ No newline at end of file
diff --git a/tests/src/test/java/org/apache/etch/tests/TestAsyncClient.java b/tests/src/test/java/org/apache/etch/tests/TestAsyncClient.java
new file mode 100644
index 0000000..01194ca
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/TestAsyncClient.java
@@ -0,0 +1,110 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.etch.util.Log;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+/**
+ * Main implementation for AsyncClient.
+ */
+public class TestAsyncClient
+{
+	/** @throws Exception */
+	@BeforeClass
+	public static void init()
+		throws Exception
+	{
+		Log.addSink( null );
+		Log.report( "TestAsyncClient" );
+		
+		MainAsyncListener.main( new String[] {} );
+		
+		String uri = "tcp://localhost:4003";
+
+		server = AsyncHelper.newServer( uri, null,
+			new AsyncHelper.AsyncClientFactory()
+			{
+				public AsyncClient newAsyncClient( RemoteAsyncServer server )
+					throws Exception
+				{
+					return new ImplAsyncClient( server );
+				}
+			} );
+		
+		server._startAndWaitUp( 4000 );
+		up = true;
+	}
+	
+	private static boolean up = false;
+	
+	/** @throws Exception */
+	@Test
+	public void sync1() throws Exception
+	{
+		assertEquals( 0, server.sync( 0 ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = RuntimeException.class ) // remote side times out
+	public void sync2() throws Exception
+	{
+		server.sync( 1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void async_queued1() throws Exception
+	{
+		for (int i = 0; i < 5; i++)
+			assertEquals( i, server.async_queued( i ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = RuntimeException.class ) // remote side times out
+	public void async_queued2() throws Exception
+	{
+		server.async_queued( 5 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void async_free() throws Exception
+	{
+		for (int i = 0; i < 100; i++)
+			assertEquals( i, server.async_free( i ) );
+	}
+	
+	/** @throws Exception */
+	@AfterClass
+	public static void fini() throws Exception
+	{
+		if (server != null && up)
+			server._stopAndWaitDown( 4000 );
+	}
+	
+	private static RemoteAsyncServer server;
+}
diff --git a/tests/src/test/java/org/apache/etch/tests/TestImplIncludes.java b/tests/src/test/java/org/apache/etch/tests/TestImplIncludes.java
new file mode 100644
index 0000000..49598ab
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/TestImplIncludes.java
@@ -0,0 +1,80 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Simple tests to ensure that includes defined in TestIncludes.etch 
+ * work properly and all included variables & messages can be accessed
+ *
+ * @author dattas
+ */
+
+
+
+public class TestImplIncludes
+{
+	
+	private RemoteTestIncludesClient tc = null;
+	private RemoteTestIncludesServer ts = null;
+	private ImplTestIncludesServer testServer = null;
+	private ImplTestIncludesClient testClient = null;
+	
+	/** */
+	@Before public void setup() {
+		testServer = new ImplTestIncludesServer(tc);
+		testClient = new ImplTestIncludesClient(ts);
+	}
+	
+	/** */
+	@Test public void testConsts() {
+		
+		try
+		{	
+			testServer.testConst2();
+			testServer.testConst3();
+			Integer x = new Integer(5);
+			Integer y = new Integer(50);
+			testClient.testConst1( x, y );
+			testClient.testConst2();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+		}		
+	}
+	
+	/** */
+	@Test public void testEnums() {
+		try
+		{
+			testServer.testEnum2();
+			testClient.testEnum1();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+		}	
+	}
+	
+}
diff --git a/tests/src/test/java/org/apache/etch/tests/TestImplTest1.java b/tests/src/test/java/org/apache/etch/tests/TestImplTest1.java
new file mode 100644
index 0000000..dcd868d
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/TestImplTest1.java
@@ -0,0 +1,1178 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import org.apache.etch.bindings.java.util.StrIntHashMap;
+import org.apache.etch.tests.Test1.E1;
+import org.apache.etch.tests.Test1.S1;
+import org.apache.etch.tests.Test1.S2;
+import org.apache.etch.tests.Test1.S3;
+import org.apache.etch.tests.Test1.S4;
+import org.junit.Before;
+import org.junit.Test;
+
+
+/**
+ * Simple tests to ensure that ImplTestClient and ImplTestServer are generated
+ * correctly
+ *
+ * @author gsandhir
+ */
+public class TestImplTest1
+{
+	private ImplTest1Server testServer = null;
+	private ImplTest1Client testClient = null;
+	
+	/** */
+	@Before public void setup() {
+		RemoteTest1Client tc = null;
+		RemoteTest1Server ts = null;
+		testServer = new ImplTest1Server(tc);
+		testClient = new ImplTest1Client(ts);
+	}
+	
+	/** */
+	@Test public void testIncr() {
+		
+		try
+		{
+			Integer i = new Integer(5);		
+			testServer.incr(i);			
+			testClient.incr( i );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+		
+		}
+	}
+	
+	/** */
+	@Test public void testNothing() {
+		
+		try
+		{			
+			testServer.nothing();		
+			testClient.nothing();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+		
+		}
+	}
+	
+	/** */
+	@Test public void testAdd() {
+		try
+		{
+			Integer i = new Integer(5);
+			Integer j = new Integer(3);
+			testServer.add( i,j);
+			testClient.add( i,j);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void testSub() {
+		try
+		{
+			Integer i = new Integer(5);
+			Integer j = new Integer(3);
+			testServer.sub( i,j);
+			testClient.sub( i,j);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testSum() {
+		try
+		{
+			int[] x = {1,2,3};
+			testServer.sum( x );
+			testClient.sum( x );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}				
+	}
+	
+	/** */
+	@Test public void  testFill() {
+		try
+		{
+			Integer i = new Integer(5);
+			Integer j = new Integer(3);
+			testServer.fill( i, j );
+			testClient.fill( i,j );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}				
+	}
+	
+	/** */
+	@Test public void  testFillObject() {
+		try
+		{
+			Integer i = new Integer(5);
+			Object j = null;
+			testServer.fillObject( i, j );
+			testClient.fillObject( i,j );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}				
+	}
+	
+	
+	/** */
+	@Test public void  testTrans() {
+		try
+		{
+			Integer i = new Integer(5);
+			E1 enumA = E1.A;
+			testServer.trans( enumA,i  );
+			testClient.trans( enumA,i  );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}				
+	}
+	
+	/** */
+	@Test public void  testDist() {
+		try
+		{
+			S1 a = new S1();
+			S1 b = new S1();
+			testServer.dist( a, b );
+			testClient.dist( a, b );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}			
+	}
+	
+	/** @throws Exception */
+	@Test public void  testBlow() throws Exception {
+		try
+		{
+			Integer i = new Integer(5);		
+			testServer.blow( "", i);
+			testClient.blow( "", i );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}			
+	}
+	
+	/** @throws Exception */
+	@Test public void  testExcp5() throws Exception {
+		try
+		{
+			Integer i = new Integer(5);	
+			Object value = null;
+			testServer.throwExcp5( "", i, value );
+			testClient.throwExcp5( "", i, value );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}			
+	}
+	
+	/** @throws Exception */
+	@Test public void  testExcp6() throws Exception {
+		try
+		{
+			Integer i = new Integer(5);	
+			Object value[] = null;
+			testServer.throwExcp6( "", i, value );
+			testClient.throwExcp6( "", i, value );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}			
+	}
+	
+	/** */
+	@Test public void  testBoolean() {
+		try
+		{
+			Boolean b = null;	
+			testServer.p_boolean( b );
+			testClient.p_boolean( b );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}		
+	}
+	
+	/** */
+	@Test public void  testBooleanArray() {
+		try
+		{
+			boolean b[] = null;	
+			testServer.p_boolean_array( b );
+			testClient.p_boolean_array( b )	;
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testByte() {
+		try
+		{
+			Byte a = null;
+			testServer.p_byte( a );
+			testClient.p_byte( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testByteArray() {
+		try
+		{
+			byte a[] = null;
+			testServer.p_byte_array( a );
+			testClient.p_byte_array( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testShort() {
+		try
+		{
+			Short a  = null;
+			testServer.p_short( a );
+			testClient.p_short( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testShortArray() {
+		try
+		{
+			short a[] = null;
+			testServer.p_short_array( a );
+			testClient.p_short_array( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+		
+		}
+	}
+	
+	/** */
+	@Test public void  testInt() {
+		try
+		{
+			Integer a  = null;
+			testServer.p_int( a );
+			testClient.p_int( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testIntArray() {
+		try
+		{
+			int a[]  = null;
+			testServer.p_int_array( a );
+			testClient.p_int_array( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testLong() {
+		try
+		{
+			Long a  = null;
+			testServer.p_long( a );
+			testClient.p_long( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testLongArray() {
+		try
+		{
+			long a[]  = null;
+			testServer.p_long_array( a );
+			testClient.p_long_array( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testFloat() {
+		try
+		{
+			Float a  = null;
+			testServer.p_float( a );
+			testClient.p_float( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testFloatArray() {
+		try
+		{
+			float a[]  = null;
+			testServer.p_float_array( a );
+			testClient.p_float_array( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	
+	
+	/** */
+	@Test public void  testDouble() {
+		try
+		{
+			Double a  = null;
+			testServer.p_double( a );
+			testClient.p_double( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testDoubleArray() {
+		try
+		{
+			double a[]  = null;
+			testServer.p_double_array( a );
+			testClient.p_double_array( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testString() {
+		try
+		{
+			String a  = null;
+			testServer.p_string( a );
+			testClient.p_string( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testStringArray() {
+		try
+		{
+			String a[]  = null;
+			testServer.p_string_array( a );
+			testClient.p_string_array( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testE1() {
+		try
+		{
+			E1 a  = null;
+			testServer.p_E1( a );
+			testClient.p_E1( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testE1Array() {
+		try
+		{
+			E1 a[]  = null;
+			testServer.p_E1_array( a );
+			testClient.p_E1_array( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testS1() {
+		try
+		{
+			S1 a  = null;
+			testServer.p_S1( a );
+			testClient.p_S1( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testS1Array() {
+		try
+		{
+			S1 a[]  = null;
+			testServer.p_S1_array( a );
+			testClient.p_S1_array( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testS2() {
+		try
+		{
+			S2 a  = null;
+			testServer.p_S2( a );
+			testClient.p_S2( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testS2Array() {
+		try
+		{
+			S2 a[]  = null;
+			testServer.p_S2_array( a );
+			testClient.p_S2_array( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testBlob() {
+		try
+		{
+			StrIntHashMap a  = null;
+			testServer.p_Blob( a );
+			testClient.p_Blob( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testBlobArray() {
+		try
+		{
+			StrIntHashMap[] a  = null;
+			testServer.p_Blob_array( a );
+			testClient.p_Blob_array( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testObject() {
+		try
+		{
+			Object a  = null;
+			testServer.p_object( a );
+			testClient.p_object( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testObjectArray() {
+		try
+		{
+			Object[] a  = null;
+			testServer.p_object_array( a );
+			testClient.p_object_array( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testObjectStruct() {
+		try
+		{
+			S3 a  = null;
+			testServer.p_object_struct( a );
+			testClient.p_object_struct( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testObjectStructArray() {
+		try
+		{
+			S4 a  = null;
+			testServer.p_object_struct_array( a );
+			testClient.p_object_struct_array( a );
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testAlwaysWork() {
+		try
+		{
+			
+			testServer.alwaysWorks();
+			testClient.alwaysWorks();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testAlwaysFail() {
+		try
+		{
+			
+			testServer.alwaysFails();
+			testClient.alwaysFails();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testIsTrue() {
+		try
+		{
+			
+			testServer.isTrue();
+			testClient.isTrue();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testIsFalse() {
+		try
+		{
+			
+			testServer.isFalse();
+			testClient.isFalse();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testM1() {
+		try
+		{
+			
+			testServer.m1();
+			testClient.m1();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testCanM1() {
+		try
+		{
+			
+			testServer.can_m1();
+			testClient.can_m1();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testM2() {
+		try
+		{
+			
+			testServer.m2();
+			testClient.m2();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testCanM2() {
+		try
+		{
+			Boolean b = null;
+			testServer.can_m2(b);
+			testClient.can_m2(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testM3() {
+		try
+		{
+			
+			testServer.m3();
+			testClient.m3();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testCanM3() {
+		try
+		{
+			Boolean b = null;
+			testServer.can_m3(b);
+			testClient.can_m3(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testM4() {
+		try
+		{
+			
+			testServer.m4();
+			testClient.m4();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testCanM4() {
+		try
+		{
+			Boolean b = null;
+			testServer.can_m4(b);
+			testClient.can_m4(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testM5() {
+		try
+		{
+			
+			testServer.m5();
+			testClient.m5();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testCanM5() {
+		try
+		{
+			Byte b = null;
+			testServer.can_m5(b);
+			testClient.can_m5(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testM6() {
+		try
+		{
+			
+			testServer.m6();
+			testClient.m6();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testCanM6() {
+		try
+		{
+			Short b = null;
+			testServer.can_m6(b);
+			testClient.can_m6(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testM7() {
+		try
+		{
+			
+			testServer.m7();
+			testClient.m7();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testCanM7() {
+		try
+		{
+			Integer b = null;
+			testServer.can_m7(b);
+			testClient.can_m7(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testM8() {
+		try
+		{
+			
+			testServer.m8();
+			testClient.m8();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testCanM8() {
+		try
+		{
+			Long b = null;
+			testServer.can_m8(b);
+			testClient.can_m8(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testM9() {
+		try
+		{
+			
+			testServer.m6();
+			testClient.m6();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testCanM9() {
+		try
+		{
+			Float b = null;
+			testServer.can_m9(b);
+			testClient.can_m9(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testM10() {
+		try
+		{
+			
+			testServer.m10();
+			testClient.m10();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testCanM10() {
+		try
+		{
+			Double b = null;
+			testServer.can_m10(b);
+			testClient.can_m10(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testM11() {
+		try
+		{
+			
+			testServer.m11();
+			testClient.m11();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testCanM11() {
+		try
+		{
+			String b = null;
+			testServer.can_m11(b);
+			testClient.can_m11(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testM12() {
+		try
+		{
+			
+			testServer.m12();
+			testClient.m12();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testCanM12() {
+		try
+		{
+			Integer b = null;
+			testServer.can_m12(b);
+			testClient.can_m12(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testM13() {
+		try
+		{
+			Integer b = null;
+			testServer.m13(b);
+			testClient.m13(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testCanM13() {
+		try
+		{
+			Integer b = null;
+			testServer.can_m13(b);
+			testClient.can_m13(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testM14() {
+		try
+		{
+			S1 b = null;
+			testServer.m14(b);
+			testClient.m14(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testCanM14() {
+		try
+		{
+			Integer b = null;
+			testServer.can_m14(b);
+			testClient.can_m14(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testM15() {
+		try
+		{
+		
+			testServer.m15();
+			testClient.m15();
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	/** */
+	@Test public void  testCanM15() {
+		try
+		{
+			E1 b = null;
+			testServer.can_m15(b);
+			testClient.can_m15(b);
+		}
+		catch ( UnsupportedOperationException e )
+		{
+			// ignore
+			
+		}
+	}
+	
+	
+	
+	
+	
+}
diff --git a/tests/src/test/java/org/apache/etch/tests/TestInheritance.java b/tests/src/test/java/org/apache/etch/tests/TestInheritance.java
new file mode 100644
index 0000000..9f39b88
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/TestInheritance.java
@@ -0,0 +1,578 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.etch.tests.Inheritance.E1;
+import org.apache.etch.tests.Inheritance.E2;
+import org.apache.etch.tests.Inheritance.E3;
+import org.apache.etch.tests.Inheritance.S1;
+import org.apache.etch.tests.Inheritance.S2;
+import org.apache.etch.tests.Inheritance.S3;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+/**
+ * Main implementation for InheritanceClient.
+ */
+public class TestInheritance
+{
+	/** @throws Exception */
+	@BeforeClass
+	public static void setUp() throws Exception
+	{
+		MainInheritanceListener.main( new String[] { "tcp://127.0.0.1:0" } );
+		
+		String uri = MainInheritanceListener.localUri;
+
+		server = InheritanceHelper.newServer( uri, null,
+			new InheritanceHelper.InheritanceClientFactory()
+			{
+				public InheritanceClient newInheritanceClient(
+					RemoteInheritanceServer server ) throws Exception
+				{
+					return new ImplInheritanceClient( server );
+				}
+			} );
+		
+		server._startAndWaitUp( 4000 );
+	}
+	
+	private static RemoteInheritanceServer server;
+	
+	/** @throws Exception */
+	@Test
+	public void types() throws Exception
+	{
+		assertEquals( true, S1.class.isAssignableFrom( S1.class ) );
+		assertEquals( true, S1.class.isAssignableFrom( S2.class ) );
+		assertEquals( true, S1.class.isAssignableFrom( S3.class ) );
+		
+		assertEquals( false, S2.class.isAssignableFrom( S1.class ) );
+		assertEquals( true, S2.class.isAssignableFrom( S2.class ) );
+		assertEquals( true, S2.class.isAssignableFrom( S3.class ) );
+		
+		assertEquals( false, S3.class.isAssignableFrom( S1.class ) );
+		assertEquals( false, S3.class.isAssignableFrom( S2.class ) );
+		assertEquals( true, S3.class.isAssignableFrom( S3.class ) );
+		
+		assertEquals( true, E1.class.isAssignableFrom( E1.class ) );
+		assertEquals( true, E1.class.isAssignableFrom( E2.class ) );
+		assertEquals( true, E1.class.isAssignableFrom( E3.class ) );
+		
+		assertEquals( true, Exception.class.isAssignableFrom( E1.class ) );
+		assertEquals( true, Exception.class.isAssignableFrom( E2.class ) );
+		assertEquals( true, Exception.class.isAssignableFrom( E3.class ) );
+		
+		assertEquals( false, E2.class.isAssignableFrom( E1.class ) );
+		assertEquals( true, E2.class.isAssignableFrom( E2.class ) );
+		assertEquals( true, E2.class.isAssignableFrom( E3.class ) );
+		
+		assertEquals( false, E3.class.isAssignableFrom( E1.class ) );
+		assertEquals( false, E3.class.isAssignableFrom( E2.class ) );
+		assertEquals( true, E3.class.isAssignableFrom( E3.class ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construct_s1() throws Exception
+	{
+		check_s1( new S1(), null, null );
+		
+		check_s1( new S1( null, null ), null, null );
+		
+		check_s1( new S1( 1, 2 ), 1, 2 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construct_s2() throws Exception
+	{
+		check_s2( new S2(), null, null, null, null );
+		
+		check_s2( new S2( null, null, null, null ), null, null, null, null );
+		
+		check_s2( new S2( 1, 2, 3, 4 ), 1, 2, 3, 4 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construct_s3() throws Exception
+	{
+		check_s3( new S3(), null, null, null, null, null, null );
+		
+		check_s3( new S3( null, null, null, null, null, null ),
+			null, null, null, null, null, null );
+		
+		check_s3( new S3( 1, 2, 3, 4, 5, 6 ), 1, 2, 3, 4, 5, 6 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construct_e1() throws Exception
+	{
+		check_e1( new E1(), null, null );
+		
+		check_e1( new E1( null, null ), null, null );
+		
+		check_e1( new E1( 1, 2 ), 1, 2 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construct_e2() throws Exception
+	{
+		check_e2( new E2(), null, null, null, null );
+		
+		check_e2( new E2( null, null, null, null ), null, null, null, null );
+		
+		check_e2( new E2( 1, 2, 3, 4 ), 1, 2, 3, 4 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construct_e3() throws Exception
+	{
+		check_e3( new E3(), null, null, null, null, null, null );
+		
+		check_e3( new E3( null, null, null, null, null, null ),
+			null, null, null, null, null, null );
+		
+		check_e3( new E3( 1, 2, 3, 4, 5, 6 ), 1, 2, 3, 4, 5, 6 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void assign_s1() throws Exception
+	{
+		S1 v = new S1( 1, 2 ); check_s1( v, 1, 2 );
+		
+		v.a = null;            check_s1( v, null, 2 );
+		v.a = 3;               check_s1( v, 3, 2 );
+		v.setA( null );        check_s1( v, null, 2 );
+		v.setA( 4 );           check_s1( v, 4, 2 );
+		
+		v.b = null;            check_s1( v, 4, null );
+		v.b = 5;               check_s1( v, 4, 5 );
+		v.setB( null );        check_s1( v, 4, null );
+		v.setB( 6 );           check_s1( v, 4, 6 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void assign_s2() throws Exception
+	{
+		S2 v = new S2( 1, 2, 3, 4 ); check_s2( v, 1, 2, 3, 4 );
+		
+		v.a = null;                  check_s2( v, null, 2, 3, 4 );
+		v.a = 5;                     check_s2( v, 5, 2, 3, 4 );
+		v.setA( null );              check_s2( v, null, 2, 3, 4 );
+		v.setA( 6 );                 check_s2( v, 6, 2, 3, 4 );
+		
+		v.b = null;                  check_s2( v, 6, null, 3, 4 );
+		v.b = 7;                     check_s2( v, 6, 7, 3, 4 );
+		v.setB( null );              check_s2( v, 6, null, 3, 4 );
+		v.setB( 8 );                 check_s2( v, 6, 8, 3, 4 );
+		
+		v.c = null;                  check_s2( v, 6, 8, null, 4 );
+		v.c = 9;                     check_s2( v, 6, 8, 9, 4 );
+		v.setC( null );              check_s2( v, 6, 8, null, 4 );
+		v.setC( 10 );                check_s2( v, 6, 8, 10, 4 );
+		
+		v.d = null;                  check_s2( v, 6, 8, 10, null );
+		v.d = 11;                    check_s2( v, 6, 8, 10, 11 );
+		v.setD( null );              check_s2( v, 6, 8, 10, null );
+		v.setD( 12 );                check_s2( v, 6, 8, 10, 12 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void assign_s3() throws Exception
+	{
+		S3 v = new S3( 1, 2, 3, 4, 5, 6 ); check_s3( v, 1, 2, 3, 4, 5, 6 );
+		
+		v.a = null;                        check_s3( v, null, 2, 3, 4, 5, 6 );
+		v.a = 7;                           check_s3( v, 7, 2, 3, 4, 5, 6 );
+		v.setA( null );                    check_s3( v, null, 2, 3, 4, 5, 6 );
+		v.setA( 8 );                       check_s3( v, 8, 2, 3, 4, 5, 6 );
+		
+		v.b = null;                        check_s3( v, 8, null, 3, 4, 5, 6 );
+		v.b = 9;                           check_s3( v, 8, 9, 3, 4, 5, 6 );
+		v.setB( null );                    check_s3( v, 8, null, 3, 4, 5, 6 );
+		v.setB( 10 );                      check_s3( v, 8, 10, 3, 4, 5, 6 );
+		
+		v.c = null;                        check_s3( v, 8, 10, null, 4, 5, 6 );
+		v.c = 11;                          check_s3( v, 8, 10, 11, 4, 5, 6 );
+		v.setC( null );                    check_s3( v, 8, 10, null, 4, 5, 6 );
+		v.setC( 12 );                      check_s3( v, 8, 10, 12, 4, 5, 6 );
+		
+		v.d = null;                        check_s3( v, 8, 10, 12, null, 5, 6 );
+		v.d = 13;                          check_s3( v, 8, 10, 12, 13, 5, 6 );
+		v.setD( null );                    check_s3( v, 8, 10, 12, null, 5, 6 );
+		v.setD( 14 );                      check_s3( v, 8, 10, 12, 14, 5, 6 );
+		
+		v.e = null;                        check_s3( v, 8, 10, 12, 14, null, 6 );
+		v.e = 15;                          check_s3( v, 8, 10, 12, 14, 15, 6 );
+		v.setE( null );                    check_s3( v, 8, 10, 12, 14, null, 6 );
+		v.setE( 16 );                      check_s3( v, 8, 10, 12, 14, 16, 6 );
+		
+		v.f = null;                        check_s3( v, 8, 10, 12, 14, 16, null );
+		v.f = 17;                          check_s3( v, 8, 10, 12, 14, 16, 17 );
+		v.setF( null );                    check_s3( v, 8, 10, 12, 14, 16, null );
+		v.setF( 18 );                      check_s3( v, 8, 10, 12, 14, 16, 18 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void tostring() throws Exception
+	{
+		assertEquals(
+			"S1(a=1; b=2)",
+			new S1( 1, 2 ).toString() );
+		
+		assertEquals(
+			"S2(S1(a=1; b=2); c=3; d=4)",
+			new S2( 1, 2, 3, 4 ).toString() );
+		
+		assertEquals(
+			"S3(S2(S1(a=1; b=2); c=3; d=4); e=5; f=6)",
+			new S3( 1, 2, 3, 4, 5, 6 ).toString() );
+		
+		assertEquals(
+			"org.apache.etch.tests.Inheritance$E1: a=1; b=2",
+			new E1( 1, 2 ).toString() );
+		
+		assertEquals(
+			"org.apache.etch.tests.Inheritance$E2: a=1; b=2; c=3; d=4",
+			new E2( 1, 2, 3, 4 ).toString() );
+		
+		assertEquals(
+			"org.apache.etch.tests.Inheritance$E3: a=1; b=2; c=3; d=4; e=5; f=6",
+			new E3( 1, 2, 3, 4, 5, 6 ).toString() );
+	}
+
+	private void check_s1( S1 v, Integer a, Integer b )
+	{
+		assertEquals( a, v.a );
+		assertEquals( a, v.getA() );
+		
+		assertEquals( b, v.b );
+		assertEquals( b, v.getB() );
+	}
+
+	private void check_s2( S2 v, Integer a, Integer b, Integer c, Integer d )
+	{
+		check_s1( v, a, b );
+		
+		assertEquals( c, v.c );
+		assertEquals( c, v.getC() );
+		
+		assertEquals( d, v.d );
+		assertEquals( d, v.getD() );
+	}
+
+	private void check_s3( S3 v, Integer a, Integer b, Integer c, Integer d,
+		Integer e, Integer f )
+	{
+		check_s2( v, a, b, c, d );
+		
+		assertEquals( e, v.e );
+		assertEquals( e, v.getE() );
+		
+		assertEquals( f, v.f );
+		assertEquals( f, v.getF() );
+	}
+
+	private void check_e1( E1 v, Integer a, Integer b )
+	{
+		assertEquals( a, v.a );
+		assertEquals( a, v.getA() );
+		
+		assertEquals( b, v.b );
+		assertEquals( b, v.getB() );
+	}
+
+	private void check_e2( E2 v, Integer a, Integer b, Integer c, Integer d )
+	{
+		check_e1( v, a, b );
+		
+		assertEquals( c, v.c );
+		assertEquals( c, v.getC() );
+		
+		assertEquals( d, v.d );
+		assertEquals( d, v.getD() );
+	}
+
+	private void check_e3( E3 v, Integer a, Integer b, Integer c, Integer d,
+		Integer e, Integer f )
+	{
+		check_e2( v, a, b, c, d );
+		
+		assertEquals( e, v.e );
+		assertEquals( e, v.getE() );
+		
+		assertEquals( f, v.f );
+		assertEquals( f, v.getF() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test_s1() throws Exception
+	{
+		do_s1( new S1( 1, 2 ), new S1Compare() );
+		do_s1( new S1( 9, 8 ), new S1Compare() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test_s2() throws Exception
+	{
+		do_s2( new S2( 1, 2, 3, 4 ), new S2Compare() );
+		do_s2( new S2( 9, 8, 7, 6 ), new S2Compare() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void test_s3() throws Exception
+	{
+		do_s3( new S3( 1, 2, 3, 4, 5, 6 ), new S3Compare() );
+		do_s3( new S3( 9, 8, 7, 6, 5, 4 ), new S3Compare() );
+	}
+	
+	private interface Compare<T>
+	{
+		/**
+		 * @param a
+		 * @param b
+		 */
+		public void compare( T a, T b );
+	}
+	
+	/**
+	 * Class to compare one S1 to another.
+	 */
+	static class S1Compare implements Compare<S1>
+	{
+		public void compare( S1 a, S1 b )
+		{
+			assertEquals( S1.class, a.getClass() );
+			assertEquals( S1.class, b.getClass() );
+			assertEquals( a.a, b.a );
+			assertEquals( a.b, b.b );
+		}
+	}
+	
+	/**
+	 * Class to compare one S2 to another.
+	 */
+	static class S2Compare implements Compare<S2>
+	{
+		public void compare( S2 a, S2 b )
+		{
+			assertEquals( S2.class, a.getClass() );
+			assertEquals( S2.class, b.getClass() );
+			assertEquals( a.a, b.a );
+			assertEquals( a.b, b.b );
+			assertEquals( a.c, b.c );
+			assertEquals( a.d, b.d );
+		}
+	}
+
+	/**
+	 * Class to compare one S3 to another.
+	 */
+	static class S3Compare implements Compare<S3>
+	{
+		public void compare( S3 a, S3 b )
+		{
+			assertEquals( S3.class, a.getClass() );
+			assertEquals( S3.class, b.getClass() );
+			assertEquals( a.a, b.a );
+			assertEquals( a.b, b.b );
+			assertEquals( a.c, b.c );
+			assertEquals( a.d, b.d );
+			assertEquals( a.e, b.e );
+			assertEquals( a.f, b.f );
+		}
+	}
+	
+	private static class AObjectCompare implements Compare<Object[]>
+	{
+		/**
+		 * @param cmp
+		 */
+		public AObjectCompare( Compare<Object> cmp )
+		{
+			this.cmp = cmp;
+		}
+		
+		private final Compare<Object> cmp;
+
+		@SuppressWarnings("unchecked")
+		public void compare( Object[] a, Object[] b )
+		{
+			assertEquals( a.length, b.length );
+			for (int i = 0; i < a.length; i++)
+				cmp.compare( a[i], b[i] );
+		}
+	}
+	
+	private static class AS1Compare implements Compare<S1[]>
+	{
+		/**
+		 * @param cmp
+		 */
+		public AS1Compare( Compare<S1> cmp )
+		{
+			this.cmp = cmp;
+		}
+		
+		private final Compare<S1> cmp;
+
+		@SuppressWarnings("unchecked")
+		public void compare( S1[] a, S1[] b )
+		{
+			assertEquals( a.length, b.length );
+			for (int i = 0; i < a.length; i++)
+				cmp.compare( a[i], b[i] );
+		}
+	}
+	
+	private static class AS2Compare implements Compare<S2[]>
+	{
+		/**
+		 * @param cmp
+		 */
+		public AS2Compare( Compare<S2> cmp )
+		{
+			this.cmp = cmp;
+		}
+		
+		private final Compare<S2> cmp;
+
+		@SuppressWarnings("unchecked")
+		public void compare( S2[] a, S2[] b )
+		{
+			assertEquals( a.length, b.length );
+			for (int i = 0; i < a.length; i++)
+				cmp.compare( a[i], b[i] );
+		}
+	}
+	
+	private static class AS3Compare implements Compare<S3[]>
+	{
+		/**
+		 * @param cmp
+		 */
+		public AS3Compare( Compare<S3> cmp )
+		{
+			this.cmp = cmp;
+		}
+		
+		private final Compare<S3> cmp;
+
+		@SuppressWarnings("unchecked")
+		public void compare( S3[] a, S3[] b )
+		{
+			assertEquals( a.length, b.length );
+			for (int i = 0; i < a.length; i++)
+				cmp.compare( a[i], b[i] );
+		}
+	}
+
+	/////////////
+	// HELPERS //
+	/////////////
+	
+	@SuppressWarnings("unchecked")
+	private void do_obj( Object v, Compare cmp )
+	{
+		// test an object both by itself and as an array.
+		
+		cmp.compare( v, server.f1( v ) );
+		
+		Object[] a = { v };
+		Compare acmp = new AObjectCompare( cmp );
+		
+		acmp.compare( a, server.f5( a ) );
+	}
+
+	@SuppressWarnings("unchecked")
+	private void do_s1( S1 v, Compare cmp )
+	{
+		// test an S1 both by itself and as an array.
+		// also test each of those as an object.
+		
+		cmp.compare( v, server.f2( v ) );
+		do_obj( v, cmp );
+		
+		S1[] a = { v };
+		Compare acmp = new AS1Compare( cmp );
+
+		acmp.compare( a, server.f6( a ) );
+		do_obj( a, acmp );
+	}
+
+	@SuppressWarnings("unchecked")
+	private void do_s2( S2 v, Compare cmp )
+	{
+		// test an S2 both by itself and as an array.
+		// also test the S2 as an S1, and the S2 array
+		// as an object.
+		
+		cmp.compare( v, server.f3( v ) );
+		do_s1( v, cmp );
+		
+		S2[] a = { v };
+		Compare acmp = new AS2Compare( cmp );
+
+		acmp.compare( a, server.f7( a ) );
+		do_obj( a, acmp );
+	}
+
+	@SuppressWarnings("unchecked")
+	private void do_s3( S3 v, Compare cmp )
+	{
+		// test an S3 both by itself and as an array.
+		// also test the S3 as an S2, and the S3 array
+		// as an object.
+		
+		cmp.compare( v, server.f4( v ) );
+		do_s2( v, cmp );
+		
+		S3[] a = { v };
+		Compare acmp = new AS3Compare( cmp );
+
+		acmp.compare( a, server.f8( a ) );
+		do_obj( a, acmp );
+	}
+
+	/** @throws Exception */
+	@AfterClass
+	public static void fini() throws Exception
+	{
+		if (server != null)
+			server._stopAndWaitDown( 4000 );
+	}
+}
diff --git a/tests/src/test/java/org/apache/etch/tests/TestInheritanceXml.java b/tests/src/test/java/org/apache/etch/tests/TestInheritanceXml.java
new file mode 100644
index 0000000..8940854
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/TestInheritanceXml.java
@@ -0,0 +1,981 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.junit.After;
+import org.junit.Before;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/** */
+public class TestInheritanceXml
+{
+
+	Document document;
+
+	/** @throws Exception */
+	@Before
+	public void setUp() throws Exception {
+		// Load Test.xml into DOM
+		DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+		//String userDir = System.getProperty("user.dir");
+		try
+		{
+			File f = new File("tests/target/generated-sources/main/etch/xml/org/apache/etch/tests/Inheritance.xml");
+			document = builder.parse(f);
+		}
+		catch(Exception e)
+		{
+			System.out.println("Unable to load Test.xml document: " + e);
+			System.out.println("Current dir is "+new File("." ).getAbsolutePath() );
+			assertTrue( false );
+		}
+	}
+
+	/** @throws Exception */
+	@After
+	public void tearDown() throws Exception {
+		// unload Test.xml 
+		document = null;
+	}
+
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void testModule() throws Exception
+	{
+		NodeList list = document.getElementsByTagName("module");
+		
+		assertEquals(list.getLength(), 1);
+		
+		String moduleName = list.item(0).getAttributes().getNamedItem("name").getNodeValue();
+		assertEquals(moduleName, "org.apache.etch.tests");
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(list.item(0), new String[] {"name"}));
+		
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(list.item(0), new String[] {"description", "service"}));
+		
+		Node child = getDescriptionElement(list.item(0));
+		assertNull(child);
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void testService() throws Exception
+	{
+		NodeList list = document.getElementsByTagName("service");
+		
+		assertEquals(list.getLength(), 1);
+		
+		String serviceName = list.item(0).getAttributes().getNamedItem("name").getNodeValue();
+		assertEquals(serviceName, "Inheritance");
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(list.item(0), new String[] {"name"}));
+			
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(list.item(0), new String[] {"description", "consts", "externs", "enums", "structs", "exceptions", "methods"}));
+		
+		Node child = getDescriptionElement(list.item(0));
+		assertNull(child);
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void testConsts() throws Exception
+	{
+		// verify consts
+		NodeList list = document.getElementsByTagName("const");
+		
+		// no consts
+		assertEquals(list.getLength(), 0);
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void testExterns() throws Exception
+	{
+		// verify consts
+		NodeList list = document.getElementsByTagName("extern");
+		
+		// no externs
+		assertEquals(list.getLength(), 0);
+		
+	}
+		
+	/** @throws Exception */
+	@org.junit.Test
+	public void testEnums() throws Exception
+	{
+		// verify enums
+		NodeList list = document.getElementsByTagName("enum");
+		
+		assertEquals(list.getLength(), 0);
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void testStructs() throws Exception
+	{
+		// verify structs
+		NodeList list = document.getElementsByTagName("struct");
+		
+		assertEquals(list.getLength(), 3);
+		
+		int nodeCount = 0;
+		
+		Node structNode = list.item(nodeCount++);
+		
+		checkStructProperties(structNode, "S1", "-1054787880", "org.apache.etch.tests.Inheritance.S1", 
+				"null", "S1 descr.");
+		checkStructValueProperties(structNode, "a", "352988316", "a", "int", "true", "false", null, "blah about a.");
+		checkStructValueProperties(structNode, "b", "352988317", "b", "int", "true", "false", null, "blah about b.");
+		
+		structNode = list.item(nodeCount++);
+		
+		checkStructProperties(structNode, "S2", "-1054787879", "org.apache.etch.tests.Inheritance.S2", 
+			"org.apache.etch.tests.Inheritance.S1", "S2 descr.");
+		checkStructValueProperties(structNode, "c", "352988318", "c", "int", "true", "false", null, "blah about c.");
+		checkStructValueProperties(structNode, "d", "352988319", "d", "int", "true", "false", null, "blah about d.");
+		
+		structNode = list.item(nodeCount++);
+		
+		checkStructProperties(structNode, "S3", "-1054787878", "org.apache.etch.tests.Inheritance.S3", 
+			"org.apache.etch.tests.Inheritance.S2", "S3 descr.");
+		checkStructValueProperties(structNode, "e", "352988320", "e", "int", "true", "false", null, "blah about e.");
+		checkStructValueProperties(structNode, "f", "352988321", "f", "int", "true", "false", null, "blah about f.");
+		
+	}
+		
+	/** @throws Exception */
+	@org.junit.Test
+	public void textExceptions() throws Exception
+	{
+//		 verify structs
+		NodeList exceptionsNodeList = document.getElementsByTagName("exceptions");
+		
+		assertEquals(exceptionsNodeList.getLength(), 1);
+		
+		Node exceptionsNode = exceptionsNodeList.item(0);
+		
+		ArrayList<Node>list = new ArrayList<Node>();
+			
+		NodeList exceptionsNodeChildren = exceptionsNode.getChildNodes();
+		for(int i = 0; i < exceptionsNodeChildren.getLength(); i++)
+		{
+			if(exceptionsNodeChildren.item(i).getNodeName() == "exception")
+			{
+				list.add(exceptionsNodeChildren.item(i));
+			}
+		}
+		
+		
+		assertEquals(list.size(), 3);
+		
+		int nodeCount = 0;
+		
+		Node exceptionNode = list.get(nodeCount++);
+		
+		checkExceptionProperties(exceptionNode, "E1", "false", "-1055706266", "org.apache.etch.tests.Inheritance.E1", 
+				"null", "E1 descr.");
+		checkExceptionValueProperties(exceptionNode, "a", "352988316", "a", "int", "false", null, "blah about a.");
+		checkExceptionValueProperties(exceptionNode, "b", "352988317", "b", "int", "false", null, "blah about b.");
+		
+		exceptionNode = list.get(nodeCount++);
+		
+		checkExceptionProperties(exceptionNode, "E2", "false", "-1055706265", "org.apache.etch.tests.Inheritance.E2", 
+			"org.apache.etch.tests.Inheritance.E1", "E2 descr.");
+		checkExceptionValueProperties(exceptionNode, "c", "352988318", "c", "int", "false", null, "blah about c.");
+		checkExceptionValueProperties(exceptionNode, "d", "352988319", "d", "int", "false", null, "blah about d.");
+		
+		exceptionNode = list.get(nodeCount++);
+		
+		checkExceptionProperties(exceptionNode, "E3", "false", "-1055706264", "org.apache.etch.tests.Inheritance.E3", 
+			"org.apache.etch.tests.Inheritance.E2", "E3 descr.");
+		checkExceptionValueProperties(exceptionNode, "e", "352988320", "e", "int", "false", null, "blah about e.");
+		checkExceptionValueProperties(exceptionNode, "f", "352988321", "f", "int", "false", null, "blah about f.");
+		
+		
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void testMethods() throws Exception
+	{
+
+		// verify methods
+		NodeList list = document.getElementsByTagName("method");
+		
+		assertEquals(16, list.getLength());
+		
+		int nodeCount = 0;
+		
+		Node methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "f1", "-1053541499", "org.apache.etch.tests.Inheritance.f1", 
+				"none", "false", "server", null, "Blah about f1.", null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "v", "352988337", "v", "object", "true", "false", null, "a value.");
+		checkResult(methodNode, "1309743944", "org.apache.etch.tests.Inheritance._result_f1", 
+				"object", "true", "false", null, "the same value.");
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_f1", "1309743944", "org.apache.etch.tests.Inheritance._result_f1", 
+				"none", "true", "client", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result", 
+				"object", "true", "false", null, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "f2", "-1053541498", "org.apache.etch.tests.Inheritance.f2", 
+				"none", "false", "server", null, "Blah about f2.", null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "v", "352988337", "v", 
+			"org.apache.etch.tests.Inheritance.S1", "false", "false", null, "a value.");
+		checkResult(methodNode, "1309743945", "org.apache.etch.tests.Inheritance._result_f2", 
+			"org.apache.etch.tests.Inheritance.S1", "false", "false", null, "the same value.");
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_f2", "1309743945", "org.apache.etch.tests.Inheritance._result_f2", 
+				"none", "true", "client", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result", 
+			"org.apache.etch.tests.Inheritance.S1", "false", "false", null, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "f3", "-1053541497", "org.apache.etch.tests.Inheritance.f3", 
+				"none", "false", "server", null, "Blah about f3.", null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "v", "352988337", "v", "org.apache.etch.tests.Inheritance.S2", 
+				"false", "false", null, "a value.");
+		checkResult(methodNode, "1309743946", "org.apache.etch.tests.Inheritance._result_f3", 
+			"org.apache.etch.tests.Inheritance.S2", "false", "false", null, "the same value.");
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_f3", "1309743946", "org.apache.etch.tests.Inheritance._result_f3", 
+				"none", "true", "client", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result", 
+			"org.apache.etch.tests.Inheritance.S2", "false", "false", null, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "f4", "-1053541496", "org.apache.etch.tests.Inheritance.f4", 
+				"none", "false", "server", null, "Blah about f4.", null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "v", "352988337", "v", "org.apache.etch.tests.Inheritance.S3", 
+				"false", "false", null, "a value.");
+		checkResult(methodNode, "1309743947", "org.apache.etch.tests.Inheritance._result_f4", 
+			"org.apache.etch.tests.Inheritance.S3", "false",  "false", null, "the same value.");
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_f4", "1309743947", "org.apache.etch.tests.Inheritance._result_f4", 
+				"none", "true", "client", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result", 
+			"org.apache.etch.tests.Inheritance.S3", "false", "false", null, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "f5", "-1053541495", "org.apache.etch.tests.Inheritance.f5", 
+				"none", "false", "server", null, "Blah about f5.", null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "v", "352988337", "v", "object", "true", "true", "1", "a value.");
+		checkResult(methodNode, "1309743948", "org.apache.etch.tests.Inheritance._result_f5", 
+				"object", "true", "true", "1", "the same value.");
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_f5", "1309743948", "org.apache.etch.tests.Inheritance._result_f5", 
+				"none", "true", "client", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result", 
+				"object", "true", "true", "1", null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "f6", "-1053541494", "org.apache.etch.tests.Inheritance.f6", 
+				"none", "false", "server", null, "Blah about f6.", null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "v", "352988337", "v", "org.apache.etch.tests.Inheritance.S1", 
+				"false", "true", "1", "a value.");
+		checkResult(methodNode, "1309743949", "org.apache.etch.tests.Inheritance._result_f6", 
+			"org.apache.etch.tests.Inheritance.S1", "false",  "true", "1", "the same value.");
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_f6", "1309743949", "org.apache.etch.tests.Inheritance._result_f6", 
+				"none", "true", "client", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result", 
+			"org.apache.etch.tests.Inheritance.S1", "false", "true", "1", null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "f7", "-1053541493", "org.apache.etch.tests.Inheritance.f7", 
+				"none", "false", "server", null, "Blah about f7.", null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "v", "352988337", "v", "org.apache.etch.tests.Inheritance.S2", 
+				"false", "true", "1", "a value.");
+		checkResult(methodNode, "1309743950", "org.apache.etch.tests.Inheritance._result_f7", 
+			"org.apache.etch.tests.Inheritance.S2", "false",  "true", "1", "the same value.");
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_f7", "1309743950", "org.apache.etch.tests.Inheritance._result_f7", 
+				"none", "true", "client", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result", 
+			"org.apache.etch.tests.Inheritance.S2", "false", "true", "1", null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "f8", "-1053541492", "org.apache.etch.tests.Inheritance.f8", 
+				"none", "false", "server", null, "Blah about f8.", null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "v", "352988337", "v", "org.apache.etch.tests.Inheritance.S3", 
+				"false", "true", "1", "a value.");
+		checkResult(methodNode, "1309743951", "org.apache.etch.tests.Inheritance._result_f8", 
+			"org.apache.etch.tests.Inheritance.S3", "false",  "true", "1", "the same value.");
+		
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_f8", "1309743951", "org.apache.etch.tests.Inheritance._result_f8", 
+				"none", "true", "client", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result", 
+			"org.apache.etch.tests.Inheritance.S3", "false", "true", "1", null); 
+		
+		
+	}
+	
+	private void checkStructProperties(Node structNode, String structName, String structTypeId, 
+			String structTypeName, String baseTypeName, String description)
+	{
+		NamedNodeMap attrs = structNode.getAttributes();
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(structNode, new String[] {"name", "typeId", "typeName", "baseType"}));
+
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(structNode, new String[] {"description", "field"}));
+
+		// verify that no new stuff has snuck into the XML binding
+		assertEquals(attrs.getLength(), 4);
+		
+		String nameAttr = attrs.getNamedItem("name").getNodeValue();
+		String typeAttr = attrs.getNamedItem("typeId").getNodeValue();
+		String valueAttr = attrs.getNamedItem("typeName").getNodeValue();
+		String baseTypeAttr = attrs.getNamedItem("baseType").getNodeValue();
+		
+		// verify name of constant
+		assertEquals(nameAttr, structName);
+		
+		// verify type of constant
+		assertEquals(typeAttr, structTypeId);
+		
+		// verify value of constant
+		assertEquals(valueAttr, structTypeName);
+		
+		assertEquals(baseTypeAttr, baseTypeName);
+		
+		Node child = getDescriptionElement(structNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private void checkStructValueProperties(Node structNode, String structName, String fieldId, String fieldName, 
+		String type, String isPrimitiveType, String isArray, String dimension, String description)
+	{
+		Node fieldNode = null;
+		
+		NodeList children = structNode.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE && children.item(i).getNodeName() == "field")
+			{
+				Node thisNode = children.item(i);
+				NamedNodeMap attrs = thisNode.getAttributes();
+				Node valueAttr = attrs.getNamedItem("name");
+				String thisValue = valueAttr.getNodeValue();
+				if(thisValue.compareTo(structName) == 0)
+				{
+					fieldNode = children.item(i);
+					break;
+				}
+			}
+		}
+		
+		// verify that the value node exists
+		assertNotNull(fieldNode);
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(fieldNode, new String[] {"name", "fieldId", "fieldName", "type", "isPrimitiveType",
+			"isArray", "dimension"}));
+
+		//verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(fieldNode, new String[] {"description"}));
+		
+		NamedNodeMap attrs = fieldNode.getAttributes();
+		
+		// verify that no new stuff has snuck into the XML binding
+		// dimension attr is nullable, meaning it might just not be there if isArray = "false"
+		assertEquals(attrs.getLength(), isArray == "false" ? 6 : 7);
+		
+		String fieldIdAttr = attrs.getNamedItem("fieldId").getNodeValue();
+		String fieldNameAttr = attrs.getNamedItem("fieldName").getNodeValue();
+		String typeAttr = attrs.getNamedItem("type").getNodeValue();
+		String isArrayAttr = attrs.getNamedItem("isArray").getNodeValue();
+		
+		Node dimensionNode = attrs.getNamedItem("dimension");
+		String dimensionAttr = dimensionNode == null ? dimension : dimensionNode.getNodeValue();
+		
+		
+		// verify the value of the externmap name
+		assertEquals(fieldIdAttr, fieldId);
+		assertEquals(fieldNameAttr, fieldName);
+		assertEquals(typeAttr, type);
+		assertEquals(isArrayAttr, isArray);
+		assertEquals(dimensionAttr, dimension);
+		
+		Node child = getDescriptionElement(fieldNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private void checkExceptionProperties(Node exceptionNode, String name, String isUnchecked, String exceptionId, 
+			String exceptionName, String baseTypeName, String description)
+	{
+		NamedNodeMap attrs = exceptionNode.getAttributes();
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(exceptionNode, new String[] {"name", "isUnchecked", "typeId", "typeName", "baseType"}));
+
+		//verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(exceptionNode, new String[] {"description", "field"}));
+		
+		// verify that no new stuff has snuck into the XML binding
+		assertEquals(attrs.getLength(), 5);
+		
+		String nameAttr = attrs.getNamedItem("name").getNodeValue();
+		String isUncheckedAttr = attrs.getNamedItem("isUnchecked").getNodeValue();
+		String typeAttr = attrs.getNamedItem("typeId").getNodeValue();
+		String typeName = attrs.getNamedItem("typeName").getNodeValue();
+		String baseTypeAttr = attrs.getNamedItem("baseType").getNodeValue();
+		
+		// verify name of constant
+		assertEquals(nameAttr, name);
+		
+		// verify type of constant
+		assertEquals(isUncheckedAttr, isUnchecked);
+		
+		// verify type of constant
+		assertEquals(typeAttr, exceptionId);
+		
+		// verify value of constant
+		assertEquals(typeName, exceptionName);
+		
+		assertEquals( baseTypeName, baseTypeAttr );
+		
+		Node child = getDescriptionElement(exceptionNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	private void checkExceptionValueProperties(Node exceptionNode, String name, String fieldId, String fieldName, String type, String isArray, String dimension, String description)
+	{
+		Node fieldNode = null;
+		
+		NodeList children = exceptionNode.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE && children.item(i).getNodeName() == "field")
+			{
+				Node thisNode = children.item(i);
+				NamedNodeMap attrs = thisNode.getAttributes();
+				Node valueAttr = attrs.getNamedItem("name");
+				String thisValue = valueAttr.getNodeValue();
+				if(thisValue.compareTo(name) == 0)
+				{
+					fieldNode = children.item(i);
+					break;
+				}
+			}
+		}
+			
+		// verify that the value node exists
+		assertNotNull(fieldNode);
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(fieldNode, new String[] {"name", "fieldId", "fieldName", "type", "isArray", "dimension"}));
+
+//		verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(fieldNode, new String[] {"description", "field"}));
+	
+		NamedNodeMap attrs = fieldNode.getAttributes();
+		
+		// verify that no new stuff has snuck into the XML binding
+		// dimension attr is nullable, meaning it might just not be there if isArray = "false"
+		assertEquals(attrs.getLength(), isArray == "false" ? 5 : 6);
+		
+		String fieldIdAttr = attrs.getNamedItem("fieldId").getNodeValue();
+		String fieldNameAttr = attrs.getNamedItem("fieldName").getNodeValue();
+		String typeAttr = attrs.getNamedItem("type").getNodeValue();
+		String isArrayAttr = attrs.getNamedItem("isArray").getNodeValue();
+		
+		Node dimensionNode = attrs.getNamedItem("dimension");
+		String dimensionAttr = dimensionNode == null ? dimension : dimensionNode.getNodeValue();
+		
+		assertEquals(fieldIdAttr, fieldId);
+		assertEquals(fieldNameAttr, fieldName);
+		assertEquals(typeAttr, type);
+		assertEquals(isArrayAttr, isArray);
+		assertEquals(dimensionAttr, dimension);
+		
+		Node child = getDescriptionElement(fieldNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+
+	private void checkMethodProperties(Node methodNode, String name, String methodId, String methodName, String pool, String isOneway, 
+			String direction, String timeout, String description, String result)
+	{
+		NamedNodeMap attrs = methodNode.getAttributes();
+		boolean isResultMessage = false;
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(methodNode, new String[] {"name", "typeId", "typeName", "asyncReceiverMode", "isOneway", "messageDirection", "timeout",
+				"responseField"}));
+
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(methodNode, new String[] {"description", "exception", "authorize", "field", "result"}));
+	
+		// verify that no new stuff has snuck into the XML binding
+		isResultMessage = name.startsWith("_result");
+		
+		assertEquals(isResultMessage? 8 : 6, attrs.getLength());
+		
+		String nameAttr = attrs.getNamedItem("name").getNodeValue();
+		String typeIdAttr = attrs.getNamedItem("typeId").getNodeValue();
+		String typeNameAttr = attrs.getNamedItem("typeName").getNodeValue();
+		String poolAttr = attrs.getNamedItem("asyncReceiverMode").getNodeValue();
+		String isOnewayAttr = attrs.getNamedItem("isOneway").getNodeValue();
+		String directionAttr = attrs.getNamedItem("messageDirection").getNodeValue();
+		String timeoutAttr = "";
+		String resultAttr = "";
+		
+		if ( isResultMessage )
+		{
+			timeoutAttr = attrs.getNamedItem("timeout").getNodeValue();
+			resultAttr = attrs.getNamedItem("responseField").getNodeValue();
+		}
+		
+		// verify name of method
+		assertEquals(nameAttr, name);
+		
+		// verify type of method
+		assertEquals(typeIdAttr, methodId);
+		
+		// verify value of method
+		assertEquals(typeNameAttr, methodName);
+		
+		// verify value of pool
+		assertEquals(poolAttr, pool);
+		
+		// verify value of isOneway
+		assertEquals(isOnewayAttr, isOneway);
+		
+		// verify value of isOneway
+		assertEquals(directionAttr, direction);
+		
+		// verify value of isOneway
+		if ( isResultMessage )
+		{
+			assertEquals(timeoutAttr, timeout);
+			assertEquals(resultAttr, result);
+		}
+		Node child = getDescriptionElement(methodNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private void checkAuthorize(Node methodNode, String authorizeMethodName)
+	{
+		Node child = getAuthorizeElement(methodNode);
+		
+		if(authorizeMethodName == null)
+		{
+			assertNull(child);
+		}
+		else
+		{
+			// verify that no unknown attr exist
+			assertTrue(onlyAttrsOfName(child, new String[] {"methodName"}));
+
+			// verify that no unknown child nodes exist
+			assertTrue(onlyChildNodesOfName(child, new String[] {}));
+		
+			String authorizeAttr = child.getAttributes().getNamedItem("methodName").getNodeValue();
+			
+			assertEquals(authorizeAttr, authorizeMethodName);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	
+	private void checkResult(Node methodNode, String fieldId, String fieldName, String type, 
+		String isPrimitiveType, String isArray, String dimension, String description)
+	{
+		Node resultNode = getResultElement(methodNode);
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(resultNode, new String[] {"fieldId", "fieldName", "type", "isPrimitiveType", "isArray", "dimension"}));
+
+		// verify that the value node exists
+		assertNotNull(resultNode);
+		
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(resultNode, new String[] {"description"}));
+	
+		NamedNodeMap attrs = resultNode.getAttributes();
+		
+		// verify that no new stuff has snuck into the XML binding
+		
+		// this is special case of a oneway message, so we should only have 'type=void' and 'isArray=true' specified.
+		String fieldIdAttr = null;
+		String fieldNameAttr = null;
+		
+		if(fieldId == null)
+		{
+			assertEquals(attrs.getLength(), 2);
+			
+		}
+		else // dimension attr is nullable, meaning it might just not be there if isArray = "false"
+		{
+			fieldIdAttr = attrs.getNamedItem("fieldId").getNodeValue();
+			fieldNameAttr = attrs.getNamedItem("fieldName").getNodeValue();
+			
+			assertEquals(attrs.getLength(), isArray == "false" ? 5 : 6);
+		}
+		
+		String typeAttr = attrs.getNamedItem("type").getNodeValue();
+		String isArrayAttr = attrs.getNamedItem("isArray").getNodeValue();
+
+		Node dimensionNode = attrs.getNamedItem("dimension");
+		String dimensionAttr = dimensionNode == null ? dimension : dimensionNode.getNodeValue();
+		
+		assertEquals(fieldIdAttr, fieldId);
+		assertEquals(fieldNameAttr, fieldName);
+		assertEquals(typeAttr, type);
+		assertEquals(isArrayAttr, isArray);
+		assertEquals(dimensionAttr, dimension);
+		
+		Node child = getDescriptionElement(resultNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private void checkMethodFieldProperties(Node methodNode, String name, String fieldId, String fieldName, String type, 
+			String isPrimitiveType, String isArray, String dimension, String description)
+	{
+		Node fieldNode = null;
+		
+		NodeList children = methodNode.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE && children.item(i).getNodeName() == "field")
+			{
+				Node thisNode = children.item(i);
+				NamedNodeMap attrs = thisNode.getAttributes();
+				Node valueAttr = attrs.getNamedItem("name");
+				String thisValue = valueAttr.getNodeValue();
+				if(thisValue.compareTo(name) == 0)
+				{
+					fieldNode = children.item(i);
+					break;
+				}
+			}
+		}
+		
+		// verify that the value node exists
+		assertNotNull(fieldNode);
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(fieldNode, new String[] {"name", "fieldId", "fieldName", "type", 
+				"isPrimitiveType", "isArray", "dimension" }));
+
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(fieldNode, new String[] {"description"}));
+	
+		NamedNodeMap attrs = fieldNode.getAttributes();
+		
+		// verify that no new stuff has snuck into the XML binding
+		// dimension attr is nullable, meaning it might just not be there if isArray = "false"
+		assertEquals(attrs.getLength(), isArray == "false" ? 6 : 7);
+		
+		String fieldIdAttr = attrs.getNamedItem("fieldId").getNodeValue();
+		String fieldNameAttr = attrs.getNamedItem("fieldName").getNodeValue();
+		String typeAttr = attrs.getNamedItem("type").getNodeValue();
+		String isArrayAttr = attrs.getNamedItem("isArray").getNodeValue();
+		String isPrimitiveTypeAttr = attrs.getNamedItem("isPrimitiveType").getNodeValue();
+		
+		Node dimensionNode = attrs.getNamedItem("dimension");
+		String dimensionAttr = dimensionNode == null ? dimension : dimensionNode.getNodeValue();
+		
+		assertEquals(fieldIdAttr, fieldId);
+		assertEquals(fieldNameAttr, fieldName);
+		assertEquals(typeAttr, type);
+		assertEquals(isArrayAttr, isArray);
+		assertEquals(dimensionAttr, dimension);
+		assertEquals( isPrimitiveType, isPrimitiveTypeAttr );
+		
+		Node child = getDescriptionElement(fieldNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private Node getDescriptionElement(Node node)
+	{
+		NodeList children = node.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			short nodeType = children.item(i).getNodeType();
+			String nodeName = children.item(i).getNodeName();
+			if(nodeType == Node.ELEMENT_NODE && nodeName == "description")
+			{
+				return children.item(i);
+			}
+		}
+		return null;
+	}
+	
+	private Node getAuthorizeElement(Node node)
+	{
+		NodeList children = node.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			short nodeType = children.item(i).getNodeType();
+			String nodeName = children.item(i).getNodeName();
+			if(nodeType == Node.ELEMENT_NODE && nodeName == "authorize")
+			{
+				return children.item(i);
+			}
+		}
+		return null;
+	}
+	
+	private Node getResultElement(Node node)
+	{
+		NodeList children = node.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			short nodeType = children.item(i).getNodeType();
+			String nodeName = children.item(i).getNodeName();
+			if(nodeType == Node.ELEMENT_NODE && nodeName == "result")
+			{
+				return children.item(i);
+			}
+		}
+		return null;
+	}
+	
+	private int getChildElementCount(Node node)
+	{
+		int count = 0;
+		
+		NodeList children = node.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE)
+			{
+				count++;
+			}
+		}
+		
+		return count;
+	}
+	
+	private boolean onlyChildNodesOfName(Node node, String[] elementNamesToCheck)
+	{
+		NodeList children = node.getChildNodes();
+		
+		boolean hasValidChildren = true;
+		
+		for(int i = 0; i < children.getLength(); i++)
+		{
+		
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE)
+			{
+				String elementName = children.item(i).getNodeName();
+				
+				boolean matches = false;
+				for (String element : elementNamesToCheck)
+				{
+					if(0 == elementName.compareTo(element) )
+					{
+						matches = true;
+						break;
+					}
+				}
+				
+				if(matches == false)
+				{
+					hasValidChildren = false;
+					break;
+				}
+			}	
+		}
+		
+		return hasValidChildren;
+	}
+	
+	private boolean onlyAttrsOfName(Node node, String[] attrNamesToCheck)
+	{
+		NamedNodeMap attrs = node.getAttributes();
+		
+		boolean hasValidAttrs = true;
+		
+		for(int i = 0; i < attrs.getLength(); i++)
+		{
+			String attrName = attrs.item(i).getNodeName();
+			
+			boolean matches = false;
+			for (String element : attrNamesToCheck)
+			{
+				if(0 == attrName.compareTo(element) )
+				{
+					matches = true;
+					break;
+				}
+			}
+			
+			if(matches == false)
+			{
+				hasValidAttrs = false;
+				break;
+			}
+			
+		}
+		
+		return hasValidAttrs;
+	}
+}
diff --git a/tests/src/test/java/org/apache/etch/tests/TestMainTest1Client.java b/tests/src/test/java/org/apache/etch/tests/TestMainTest1Client.java
new file mode 100644
index 0000000..858df62
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/TestMainTest1Client.java
@@ -0,0 +1,1124 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.concurrent.Semaphore;
+
+import org.apache.etch.bindings.java.util.StrIntHashMap;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+
+/**
+ * @author rebarraz
+ *
+ */
+public class TestMainTest1Client
+{
+	// Settings
+	//--------------------------------------------------------------------------
+
+	// Instance of the class.
+	private ImplTest1Client myMainTestClient;
+
+	// Instances of arguments types
+	private Boolean			myBool;
+	private Byte			myByte;
+	private Short			myShort;
+	private Integer 		myInt;
+	private Long			myLong;
+	private Float			myFloat;
+	private Double  		myDouble;
+	private Object			myObj;
+	private String			myString;
+	private StrIntHashMap	myMap;
+	private org.apache.etch.tests.Test1.E1 myE1;
+	private org.apache.etch.tests.Test1.S1 myS1;
+	private org.apache.etch.tests.Test1.S2 myS2;
+	private org.apache.etch.tests.Test1.S3 myS3;
+	private org.apache.etch.tests.Test1.S4 myS4;
+	private boolean[]		myBools;
+	private byte[]			myBytes;
+	private short[]			myShorts;
+	private int[]			myInts;
+	private long[]			myLongs;
+	private float[]			myFloats;
+	private double[]		myDoubles;
+	private Object[]		myObjs;
+	private String[]		myStrings;
+	private StrIntHashMap[]	myMaps;
+	private org.apache.etch.tests.Test1.E1[] myE1s;
+	private org.apache.etch.tests.Test1.S1[] myS1s;
+	private org.apache.etch.tests.Test1.S2[] myS2s;
+
+
+	// Maintenance
+	// -------------------------------------------------------------------------
+
+	/**
+	 * @throws java.lang.Exception
+	 */
+	@Before
+	public void setUp()
+		throws Exception
+	{
+		myMainTestClient = new ImplTest1Client( null );
+	}
+
+
+	// Tests
+	//--------------------------------------------------------------------------
+
+	/**
+	 */
+	
+	@Test
+	public void classInheritance()
+	{
+		assertTrue( myMainTestClient instanceof ImplTest1Client );
+		assertTrue( myMainTestClient instanceof BaseTest1Client );
+	}
+	
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void nothingMethod()
+	{
+		myMainTestClient.nothing();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void incrMethod()
+	{
+		myInt = myMainTestClient.incr(myInt);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void addMethod()
+	{
+		myInt = myMainTestClient.add(myInt, myInt);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void subMethod()
+	{
+		myInt = myMainTestClient.sub(myInt, myInt);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void sumMethod()
+	{
+		myInt = myMainTestClient.sum(myInts);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void transMethod()
+	{
+		myInt = myMainTestClient.trans(myE1, myInt);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void distMethod()
+	{
+		myDouble = myMainTestClient.dist(myS1, myS1);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void fillMethod()
+	{
+		myInts = myMainTestClient.fill(myInt, myInt);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void fillObjectMethod()
+	{
+		myObjs = myMainTestClient.fillObject(myInt, myObj);
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void blowMethod()
+		throws Exception
+	{
+		myMainTestClient.blow(myString, myInt);
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void beetsMethod()
+		throws Exception
+	{
+		myInt = myMainTestClient.beets(myE1);
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void throwExcp5Method()
+		throws Exception
+	{
+		myMainTestClient.throwExcp5(myString, myInt, myObj);
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void throwExcp6Method()
+		throws Exception
+	{
+		myMainTestClient.throwExcp6(myString, myInt, myObjs);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_booleanMethod()
+	{
+		myBool = myMainTestClient.p_boolean(myBool);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_boolean_arrayMethod()
+	{
+		myBools = myMainTestClient.p_boolean_array(myBools);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_byteMethod()
+	{
+		myByte = myMainTestClient.p_byte(myByte);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_byte_arrayMethod()
+	{
+		myBytes = myMainTestClient.p_byte_array(myBytes);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_shortMethod()
+	{
+		myShort = myMainTestClient.p_short(myShort);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_short_arrayMethod()
+	{
+		myShorts = myMainTestClient.p_short_array(myShorts);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_intMethod()
+	{
+		myInt = myMainTestClient.p_int(myInt);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_int_arrayMethod()
+	{
+		myInts = myMainTestClient.p_int_array(myInts);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_longMethod()
+	{
+		myLong = myMainTestClient.p_long(myLong);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_long_arrayMethod()
+	{
+		myLongs = myMainTestClient.p_long_array(myLongs);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_floatMethod()
+	{
+		myFloat = myMainTestClient.p_float(myFloat);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_float_arrayMethod()
+	{
+		myFloats = myMainTestClient.p_float_array(myFloats);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_doubleMethod()
+	{
+		myDouble = myMainTestClient.p_double(myDouble);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_double_arrayMethod()
+	{
+		myDoubles = myMainTestClient.p_double_array(myDoubles);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_stringMethod()
+	{
+		myString = myMainTestClient.p_string(myString);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_string_arrayMethod()
+	{
+		myStrings = myMainTestClient.p_string_array(myStrings);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_E1Method()
+	{
+		myE1 = myMainTestClient.p_E1(myE1);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_E1_arrayMethod()
+	{
+		myE1s = myMainTestClient.p_E1_array(myE1s);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_S1Method()
+	{
+		 myS1 = myMainTestClient.p_S1(myS1);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_S1_arrayMethod()
+	{
+		 myS1s = myMainTestClient.p_S1_array(myS1s);
+
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_S2Method()
+	{
+		myS2 = myMainTestClient.p_S2(myS2);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_S2_arrayMethod()
+	{
+		myS2s = myMainTestClient.p_S2_array(myS2s);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_BlobMethod()
+	{
+		myMap = myMainTestClient.p_Blob(myMap);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_Blob_ArrayMethod()
+	{
+		myMaps = myMainTestClient.p_Blob_array(myMaps);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_objectMethod()
+	{
+		myObj = myMainTestClient.p_object(myObj);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_object_arrayMethod()
+	{
+		myMainTestClient.p_object_array(null);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_object_structMethod()
+	{
+		myS3 = myMainTestClient.p_object_struct(myS3);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void p_object_struct_arrayMethod()
+	{
+		myS4 = myMainTestClient.p_object_struct_array(myS4);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void alwaysWordsMethod()
+	{
+		myInt = myMainTestClient.alwaysWorks();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void isTrueMethod()
+	{
+		myBool = myMainTestClient.isTrue();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void alwaysFailsMethod()
+	{
+		myMainTestClient.alwaysFails();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void isFalseMethod()
+	{
+		myBool = myMainTestClient.isFalse();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void m1Method()
+	{
+		myMainTestClient.m1();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void can_m1Method()
+	{
+		myBool = myMainTestClient.can_m1();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void m2Method()
+	{
+		myMainTestClient.m2();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void can_m2Method()
+	{
+		myBool = myMainTestClient.can_m2(null);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void m3Method()
+	{
+		myMainTestClient.m3();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void can_m3Method()
+	{
+		myBool = myMainTestClient.can_m3(null);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void m4Method()
+	{
+		myMainTestClient.m4();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void can_m4Method()
+	{
+		myBool = myMainTestClient.can_m4(myBool);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void m5Method()
+	{
+		myMainTestClient.m5();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void can_m5Method()
+	{
+		myBool = myMainTestClient.can_m5(myByte);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void m7Method()
+	{
+		myMainTestClient.m7();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void can_m7Method()
+	{
+		myBool = myMainTestClient.can_m7(myInt);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void m8Method()
+	{
+		myMainTestClient.m8();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void can_m8Method()
+	{
+		myBool = myMainTestClient.can_m8(myLong);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void m9Method()
+	{
+		myMainTestClient.m9();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void can_m9Method()
+	{
+		myBool = myMainTestClient.can_m9(myFloat);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void m10Method()
+	{
+		myMainTestClient.m10();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void can_m10Method()
+	{
+		myBool = myMainTestClient.can_m10(myDouble);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void m11Method()
+	{
+		myMainTestClient.m11();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void can_m11Method()
+	{
+		myBool = myMainTestClient.can_m11(myString);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void m12Method()
+	{
+		myMainTestClient.m12();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void can_m12Method()
+	{
+		myBool = myMainTestClient.can_m12(myInt);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void m13Method()
+	{
+		myMainTestClient.m13(myInt);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void can_m13Method()
+	{
+		myBool = myMainTestClient.can_m13(myInt);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void m14Method()
+	{
+		myMainTestClient.m14(myS1);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void can_m14Method()
+	{
+		myBool = myMainTestClient.can_m14(myInt);
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void m15Method()
+	{
+		myMainTestClient.m15();
+	}
+
+	/**
+	 */
+	@Test
+	(expected = UnsupportedOperationException.class)
+	public void can_m15Method()
+	{
+		myBool = myMainTestClient.can_m15(myE1);
+	}
+
+	/**
+	 * Test to make sure the main method can run (at all).
+	 */
+/*	@Test
+	public void mainMethod()
+	{
+		final ClientThread m = new ClientThread();
+		m.run();
+
+		try
+		{
+			m.join(4000);
+		}
+		catch (final Exception e)
+		{
+		}
+
+		if (m.hasErrors())
+			fail();
+
+	}
+	*/
+
+	/**
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void mainServiceListenerAndClient()
+		throws Exception
+	{
+		final Lock lock = new Lock();
+
+		final ThreadClient client = new ThreadClient(lock);
+		final ThreadListener listener = new ThreadListener(lock);
+
+		listener.start();
+		client.start();
+
+		// Wait for test to finish.
+		lock.getLock(3);
+		lock.releaseLock(3);
+
+		if (client.hasErrors() || listener.hasErrors())
+		{
+			Assert.fail();
+		}
+	}
+
+
+	// Helpers
+	//--------------------------------------------------------------------------
+
+	/**
+	 * Prints exception info to stderr in a most descriptive way.
+	 * @param e the exception to print
+	 */
+	public static void printException(final Exception e)
+	{
+		e.printStackTrace(System.err);
+	}
+
+//	/**
+//	 * Simple thread class for calling main WITHOUT a listener.
+//	 */
+//	private static class ClientThread extends Thread
+//	{
+//		/**
+//		 * false until unexpected stuff goes down
+//		 */
+//		private boolean myHasErrors;
+//
+//		/**
+//		 * No errors to begin with.
+//		 */
+//		public ClientThread()
+//		{
+//			myHasErrors = false;
+//		}
+//
+//		/**
+//		 * Go at it.
+//		 */
+//		@Override
+//		public void run()
+//		{
+//			try
+//			{
+//				MainTest1Client.main(new String[] {});
+//			}
+//			catch (ConnectException e1)
+//			{
+//			}
+//			catch (InterruptedException e2)
+//			{
+//			}
+//			catch (Exception e3)
+//			{
+//				// Unexpected
+//				System.out.println("WHAT!???");
+//				printException(e3);
+//				myHasErrors = true;
+//			}
+//		}
+//
+//		/**
+//		 * Were any errors encountered?
+//		 * @return true if an error was encountered, false otherwise.
+//		 */
+//		public boolean hasErrors()
+//		{
+//			return this.myHasErrors;
+//		}
+//	}
+
+
+	/**
+	 * Painfully simple locking mechanism for ordering multithreaded blocks.
+	 */
+	private static class Lock
+	{
+		/**
+		 * Counter for simple (manual) ordering mechanism.
+		 */
+		private int myCount;
+
+		/**
+		 * Binary semaphore. The -real- lock.
+		 */
+		private Semaphore mySemaphore;
+
+		/**
+		 * Start the count at 0 with the lock available and no errors recorded.
+		 */
+		public Lock()
+		{
+			myCount = 0;
+			mySemaphore = new Semaphore(1);
+		}
+
+		/**
+		 * Blocks until this lock can be grabbed by the count.
+		 * @param c
+		 */
+		public void getLock(final int c)
+		{
+			while(c > myCount)
+			{
+				try
+				{
+					Thread.sleep( 10 );
+				}
+				catch ( InterruptedException e )
+				{
+					// ignore
+				}
+			}
+
+			try
+			{
+				mySemaphore.acquire();
+			}
+			catch(final Exception e)
+			{
+				// Won't happen thanks to atomic release.
+			}
+		}
+
+		/**
+		 * Releases the lock if this lock is held.
+		 * @param c
+		 */
+		public synchronized void releaseLock(final int c)
+		{
+			if (c == myCount && mySemaphore.availablePermits() == 0)
+			{
+				mySemaphore.release();
+				++myCount;
+			}
+		}
+	}
+
+	/**
+	 * Thread used to run the MainServiceClient.
+	 */
+	private static class ThreadClient extends Thread
+	{
+		/**
+		 * Shared lock.
+		 */
+		private Lock ourLock;
+
+		/**
+		 * Record when an error occurs with client.
+		 */
+		private boolean myHasErrors;
+
+		/**
+		 * Share the lock and start with no errors in sight.
+		 * @param l the lock
+		 */
+		public ThreadClient(final Lock l)
+		{
+			ourLock = l;
+			myHasErrors = false;
+		}
+
+		/**
+		 * Start client.
+		 */
+		@Override
+		public void run()
+		{
+			// 0. Wait for the listener to start his engine.
+
+			// 1. Start the client.  Let it start, connect, and die gracefully.
+			ourLock.getLock(1);
+			try
+			{
+				MainTest1Client.main( new String[] {} );
+			}
+			catch (final Exception e)
+			{
+				// SHOULDN'T HAPPEN!
+				TestMainTest1Client.printException(e);
+
+				myHasErrors = true;
+			}
+			ourLock.releaseLock(1);
+
+			// 2. The listener dies.
+		}
+
+		/**
+		 * Were any errors encountered?
+		 * @return true if an error was encountered, false otherwise.
+		 */
+		public boolean hasErrors()
+		{
+			return myHasErrors;
+		}
+	}
+
+	/**
+	 * Turn the Listener into a simple thread that just listens.
+	 */
+	private static class SimpleThreadListener extends Thread
+	{
+		/**
+		 * Record when an error happens with the listener.
+		 */
+		private boolean myHasErrors;
+
+		/**
+		 * No errors in sight.
+		 */
+		public SimpleThreadListener()
+		{
+			myHasErrors = false;
+		}
+
+		/**
+		 * Listen.
+		 */
+		@Override
+		public void run()
+		{
+			try
+			{
+				MainTest1Listener.main( new String[] {} );
+			}
+			catch (final Exception e)
+			{
+				// SHOULDN'T HAPPEN!
+				TestMainTest1Client.printException(e);
+
+				myHasErrors = true;
+			}
+		}
+
+		/**
+		 * Were any errors encountered?
+		 * @return true if an error was encountered, false otherwise.
+		 */
+		public boolean hasErrors()
+		{
+			return myHasErrors;
+		}
+	}
+
+	/**
+	 * Thread for running and controlling the MainServiceListener.
+	 */
+	private static class ThreadListener extends Thread
+	{
+		/**
+		 * Share the lock.
+		 */
+		private Lock ourLock;
+
+		/**
+		 * Record if an error happens with the listener.
+		 */
+		private boolean myHasErrors;
+
+		/**
+		 * Share the lock and start off with no errors in sight.
+		 * @param l the lock
+		 */
+		public ThreadListener(final Lock l)
+		{
+			ourLock = l;
+			myHasErrors = false;
+		}
+
+		/**
+		 * Start the listener, let it wait as some water runs through the pipes.
+		 * Then, signal to the client to start. Wait for the client to signal
+		 * it's death. Finally, cleanup the listener.
+		 */
+		@Override
+		public void run()
+		{
+			// 0. Start the Listener.
+			ourLock.getLock(0);
+			final SimpleThreadListener listener = new SimpleThreadListener();
+			listener.start();
+			ourLock.releaseLock(0);
+
+			// 1. Meanwhile, back on the ranch... A new Client is born. And
+			// killed.  Long live the client!
+
+			// 2. Harshly stop the listener and ignore its whining.
+			ourLock.getLock(2);
+			try
+			{
+				myHasErrors = listener.hasErrors();
+				listener.wait(1);
+			}
+			catch(final Exception e)
+			{
+				// Do nothing. We beat the listener into submission.
+			}
+			ourLock.releaseLock(2);
+		}
+
+		/**
+		 * Were any errors encountered?
+		 * @return true if an error was encountered, false otherwise.
+		 */
+		public boolean hasErrors()
+		{
+			return myHasErrors;
+		}
+	}
+}
diff --git a/tests/src/test/java/org/apache/etch/tests/TestMainTest1Listener.java b/tests/src/test/java/org/apache/etch/tests/TestMainTest1Listener.java
new file mode 100644
index 0000000..67b2567
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/TestMainTest1Listener.java
@@ -0,0 +1,126 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+/**
+ * Tests for proper generation of a Main[Service]Listeners.
+ */
+public class TestMainTest1Listener
+{
+	// Tests
+	//--------------------------------------------------------------------------
+
+//	/**
+//	 * Run the Listener.
+//	 */
+/*	@Test
+	public void mainMethod()
+	{
+		ListenerThread m = new ListenerThread();
+		m.run();
+
+		try
+		{
+			m.join(1000);
+		}
+		catch (Exception e)
+		{
+		}
+
+		if (m.hasErrors())
+			fail();
+	}
+	*/
+
+	/**
+	 * Call newTestServer.
+	 */
+	@Test
+	public void newTestServerMethod()
+	{
+		MainTest1Listener m = new MainTest1Listener();
+		Object o = m.newTest1Server(null);
+		assertNotNull( o );
+		assertTrue( o instanceof ImplTest1Server );
+		assertTrue( o instanceof BaseTest1Server );
+	}
+
+	// Helpers
+	//--------------------------------------------------------------------------
+
+//	/**
+//	 * Prints exception info to stderr in a most descriptive way.
+//	 * @param e the exception to print
+//	 */
+//	private static void printException(final Exception e)
+//	{
+//		e.printStackTrace(System.err);
+//	}
+
+//	/**
+//	 * Simple thread class for calling main and having all of Thread's methods.
+//	 */
+//	private static class ListenerThread extends Thread
+//	{
+//		/**
+//		 * false until an unexpected exception occurs.
+//		 */
+//		private boolean myHasErrors;
+//
+//		/**
+//		 * Start off with no errors.
+//		 */
+//		public ListenerThread()
+//		{
+//			myHasErrors = false;
+//		}
+//
+//		/**
+//		 * Go at it.
+//		 */
+//		public void run()
+//		{
+//			try
+//			{
+//				MainTestListener.main(null);
+//			}
+//			catch (Exception e)
+//			{
+//				printException(e);
+//				myHasErrors = true;
+//			}
+//		}
+//
+//		/**
+//		 * Were any errors encountered?
+//		 * @return true if an error was encountered, false otherwise.
+//		 */
+//		public boolean hasErrors()
+//		{
+//			return this.myHasErrors;
+//		}
+//	}
+}
diff --git a/tests/src/test/java/org/apache/etch/tests/TestMixin.java b/tests/src/test/java/org/apache/etch/tests/TestMixin.java
new file mode 100644
index 0000000..588fa03
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/TestMixin.java
@@ -0,0 +1,350 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.msg.ValueFactory;
+import org.apache.etch.bindings.java.support.DefaultValueFactory;
+import org.apache.etch.tests.Bar.BarData;
+import org.apache.etch.tests.Baz.BazData;
+import org.apache.etch.tests.Foo.FooData;
+import org.junit.Test;
+
+
+/** Test of mixin */
+@SuppressWarnings("unused")
+public class TestMixin
+{
+	/** @throws Exception */
+	@Test
+	public void testBaz() throws Exception
+	{
+		BazData bazData = null;
+		
+		Baz baz = null;
+		if (baz != null)
+		{
+			baz.baz1( bazData );
+		}
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void testBazClient() throws Exception
+	{
+		BazData bazData = null;
+		
+		BazClient bazClient = null;
+		if (bazClient != null)
+		{
+			bazClient.baz1( bazData );
+			bazClient.baz3( bazData );
+		}
+		
+		Baz baz = bazClient;
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void testBazServer() throws Exception
+	{
+		BazData bazData = null;
+		
+		BazServer bazServer = null;
+		if (bazServer != null)
+		{
+			bazServer.baz1( bazData );
+			bazServer.baz2( bazData );
+		}
+		
+		Baz baz = bazServer;
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void testBar() throws Exception
+	{
+		BarData barData = null;
+		BazData bazData = null;
+		
+		Bar bar = null;
+		if (bar != null)
+		{
+			bar.bar1( barData );
+			bar.baz1( bazData );
+		}
+		
+		Baz baz = bar;
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void testBarClient() throws Exception
+	{
+		BarData barData = null;
+		BazData bazData = null;
+		
+		BarClient barClient = null;
+		if (barClient != null)
+		{
+			barClient.bar1( barData );
+			barClient.bar3( barData );
+			barClient.baz1( bazData );
+			barClient.baz3( bazData );
+		}
+
+		BazClient bazClient = barClient;
+		Bar bar = barClient;
+		Baz baz = barClient;
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void testBarServer() throws Exception
+	{
+		BarData barData = null;
+		BazData bazData = null;
+		
+		BarServer barServer = null;
+		if (barServer != null)
+		{
+			barServer.bar1( barData );
+			barServer.bar2( barData );
+			barServer.baz1( bazData );
+			barServer.baz2( bazData );
+		}
+
+		BazServer bazServer = barServer;
+		Bar bar = barServer;
+		Baz baz = barServer;
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void testFoo() throws Exception
+	{
+		FooData fooData = null;
+		BarData barData = null;
+		BazData bazData = null;
+		
+		Foo foo = null;
+		if (foo != null)
+		{
+			foo.foo1( fooData );
+			foo.bar1( barData );
+			foo.baz1( bazData );
+		}
+		
+		Bar bar = foo;
+		Baz baz = foo;
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void testFooClient() throws Exception
+	{
+		FooData fooData = null;
+		BarData barData = null;
+		BazData bazData = null;
+		
+		FooClient fooClient = null;
+		if (fooClient != null)
+		{
+			fooClient.foo1( fooData );
+			fooClient.foo3( fooData );
+			fooClient.bar1( barData );
+			fooClient.bar3( barData );
+			fooClient.baz1( bazData );
+			fooClient.baz3( bazData );
+		}
+		
+		BarClient barClient = fooClient;
+		BazClient bazClient = fooClient;
+		Foo foo = fooClient;
+		Bar bar = fooClient;
+		Baz baz = fooClient;
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void testFooServer() throws Exception
+	{
+		FooData fooData = null;
+		BarData barData = null;
+		BazData bazData = null;
+		
+		FooServer fooServer = null;
+		if (fooServer != null)
+		{
+			fooServer.foo1( fooData );
+			fooServer.foo2( fooData );
+			fooServer.bar1( barData );
+			fooServer.bar2( barData );
+			fooServer.baz1( bazData );
+			fooServer.baz2( bazData );
+		}
+		
+		BarServer barServer = fooServer;
+		BazServer bazServer = fooServer;
+		Foo foo = fooServer;
+		Bar bar = fooServer;
+		Baz baz = fooServer;
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void testValueFactoryBazGetTypes() throws Exception
+	{
+		DefaultValueFactory vf = new ValueFactoryBaz( "tcp:" );
+		Set<Type> atypes = vf.getTypes();
+		
+		Set<Type> etypes = new HashSet<Type>();
+		etypes.add( vf.get_mt__Etch_RuntimeException() );
+		etypes.add( vf.get_mt__Etch_List() );
+		etypes.add( vf.get_mt__Etch_Map() );
+		etypes.add( vf.get_mt__Etch_Set() );
+		etypes.add( vf.get_mt__Etch_Datetime() );
+		etypes.add( vf.get_mt__Etch_AuthException() );
+		etypes.add( vf.get_mt__Etch_AuthException() );
+		etypes.add( vf.get_mt__exception() );
+		
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_BazTable );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_BazData );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz1 );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz1 );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz2 );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz2 );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz3 );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz3 );
+		
+		assertEquals( etypes, atypes );
+		for (Type type: etypes )
+			testGetType( vf, type );
+	}
+	
+	private void testGetType( ValueFactory vf, Type type )
+	{
+		assertSame( type, vf.getType( type.getId() ) );
+		assertSame( type, vf.getType( type.getName() ) );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void testValueFactoryBarGetTypes() throws Exception
+	{
+		DefaultValueFactory vf = new ValueFactoryBar( "tcp:" );
+		Set<Type> atypes = vf.getTypes();
+		
+		Set<Type> etypes = new HashSet<Type>();
+		etypes.add( vf.get_mt__Etch_RuntimeException() );
+		etypes.add( vf.get_mt__Etch_List() );
+		etypes.add( vf.get_mt__Etch_Map() );
+		etypes.add( vf.get_mt__Etch_Set() );
+		etypes.add( vf.get_mt__Etch_Datetime() );
+		etypes.add( vf.get_mt__Etch_AuthException() );
+		etypes.add( vf.get_mt__exception() );
+		
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_BazTable );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_BazData );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz1 );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz1 );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz2 );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz2 );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz3 );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz3 );
+		
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar_BarTable );
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar_BarData );
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar_bar1 );
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar__result_bar1 );
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar_bar2 );
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar__result_bar2 );
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar_bar3 );
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar__result_bar3 );
+		
+		assertEquals( etypes, atypes );
+		for (Type type: etypes )
+			testGetType( vf, type );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void testValueFactoryFooGetTypes() throws Exception
+	{
+		DefaultValueFactory vf = new ValueFactoryFoo( "tcp:" );
+		Set<Type> atypes = vf.getTypes();
+		
+		Set<Type> etypes = new HashSet<Type>();
+		etypes.add( vf.get_mt__Etch_RuntimeException() );
+		etypes.add( vf.get_mt__Etch_List() );
+		etypes.add( vf.get_mt__Etch_Map() );
+		etypes.add( vf.get_mt__Etch_Set() );
+		etypes.add( vf.get_mt__Etch_Datetime() );
+		etypes.add( vf.get_mt__Etch_AuthException() );
+		etypes.add( vf.get_mt__exception() );
+
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_BazTable );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_BazData );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz1 );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz1 );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz2 );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz2 );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz_baz3 );
+		etypes.add( ValueFactoryBaz._mt_org_apache_etch_tests_Baz__result_baz3 );
+
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar_BarTable );
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar_BarData );
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar_bar1 );
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar__result_bar1 );
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar_bar2 );
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar__result_bar2 );
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar_bar3 );
+		etypes.add( ValueFactoryBar._mt_org_apache_etch_tests_Bar__result_bar3 );
+
+		etypes.add( ValueFactoryFoo._mt_org_apache_etch_tests_Foo_FooTable );
+		etypes.add( ValueFactoryFoo._mt_org_apache_etch_tests_Foo_FooData );
+		etypes.add( ValueFactoryFoo._mt_org_apache_etch_tests_Foo_foo1 );
+		etypes.add( ValueFactoryFoo._mt_org_apache_etch_tests_Foo__result_foo1 );
+		etypes.add( ValueFactoryFoo._mt_org_apache_etch_tests_Foo_foo2 );
+		etypes.add( ValueFactoryFoo._mt_org_apache_etch_tests_Foo__result_foo2 );
+		etypes.add( ValueFactoryFoo._mt_org_apache_etch_tests_Foo_foo3 );
+		etypes.add( ValueFactoryFoo._mt_org_apache_etch_tests_Foo__result_foo3 );
+		
+		assertEquals( etypes, atypes );
+		for (Type type: etypes )
+			testGetType( vf, type );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void duplicatesAreTheSame() throws Exception
+	{
+		assertEquals( new ValueFactoryBaz( "tcp:" ).getTypes(), new ValueFactoryBaz( "tcp:" ).getTypes() );
+		assertEquals( new ValueFactoryBar( "tcp:" ).getTypes(), new ValueFactoryBar( "tcp:" ).getTypes() );
+		assertEquals( new ValueFactoryFoo( "tcp:" ).getTypes(), new ValueFactoryFoo( "tcp:" ).getTypes() );
+	}
+}
diff --git a/tests/src/test/java/org/apache/etch/tests/TestMixinXml.java b/tests/src/test/java/org/apache/etch/tests/TestMixinXml.java
new file mode 100644
index 0000000..f7f61af
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/TestMixinXml.java
@@ -0,0 +1,942 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.junit.After;
+import org.junit.Before;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+/** */
+public class TestMixinXml 
+{
+
+	Document document;
+
+	/** @throws Exception */
+	@Before
+	public void setUp() throws Exception {
+		// Load Test.xml into DOM
+		DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+		//String userDir = System.getProperty("user.dir");
+		try
+		{
+			File f = new File("tests/target/generated-sources/main/etch/xml/org/apache/etch/tests/Foo.xml");
+			
+			document = builder.parse(f);
+		}
+		catch(Exception e)
+		{
+			System.out.println("Unable to load Test.xml document: " + e);
+			System.out.println("Current dir is "+new File("." ).getAbsolutePath() );
+			assertTrue( false );
+		}
+	}
+
+	/** @throws Exception */
+	@After
+	public void tearDown() throws Exception {
+		// unload Test.xml 
+		document = null;
+	}
+
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void testModule() throws Exception
+	{
+		NodeList list = document.getElementsByTagName("module");
+		
+		assertEquals(list.getLength(), 1);
+		
+		String moduleName = list.item(0).getAttributes().getNamedItem("name").getNodeValue();
+		assertEquals(moduleName, "org.apache.etch.tests");
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(list.item(0), new String[] {"name"}));
+		
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(list.item(0), new String[] {"description", "service"}));
+		
+		Node child = getDescriptionElement(list.item(0));
+		assertNull(child);
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void testService() throws Exception
+	{
+		NodeList list = document.getElementsByTagName("service");
+		
+		assertEquals(list.getLength(), 1);
+		
+		String serviceName = list.item(0).getAttributes().getNamedItem("name").getNodeValue();
+		assertEquals(serviceName, "Foo");
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(list.item(0), new String[] {"name"}));
+			
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(list.item(0), new String[] {"description", "consts", "externs", "enums", "structs", "exceptions", "methods"}));
+		
+		Node child = getDescriptionElement(list.item(0));
+		assertNull(child);
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void testConsts() throws Exception
+	{
+		// verify consts
+		NodeList list = document.getElementsByTagName("const");
+		
+		// no consts
+		assertEquals(list.getLength(), 0);
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void testExterns() throws Exception
+	{
+		// verify consts
+		NodeList list = document.getElementsByTagName("extern");
+		
+		assertEquals(list.getLength(), 3);
+		
+		int nodeCount = 0;
+		
+		Node externNode = list.item(nodeCount++);
+		
+		checkExternProperties(externNode, "FooTable", "-1404806234", "org.apache.etch.tests.Foo.FooTable");
+		checkExternMapProperties(externNode, "java", "org.apache.etch.bindings.java.util.StrStrHashMap", "", "org.apache.etch.bindings.java.util.StrStrHashMapSerializer",  "");
+		
+		externNode = list.item( nodeCount++ );
+		checkExternProperties(externNode, "BazTable", "729647100", "org.apache.etch.tests.Baz.BazTable");
+		checkExternMapProperties(externNode, "java", "org.apache.etch.bindings.java.util.StrStrHashMap", "", "org.apache.etch.bindings.java.util.StrStrHashMapSerializer",  "");
+		
+		externNode = list.item( nodeCount++ );
+		checkExternProperties(externNode, "BarTable", "-278631412", "org.apache.etch.tests.Bar.BarTable");
+		checkExternMapProperties(externNode, "java", "org.apache.etch.bindings.java.util.StrStrHashMap", "", "org.apache.etch.bindings.java.util.StrStrHashMapSerializer",  "");
+	}
+		
+	/** @throws Exception */
+	@org.junit.Test
+	public void testEnums() throws Exception
+	{
+		// verify enums
+		NodeList list = document.getElementsByTagName("enum");
+		
+		assertEquals(list.getLength(), 0);
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void testStructs() throws Exception
+	{
+		// verify structs
+		NodeList list = document.getElementsByTagName("struct");
+		
+		assertEquals(list.getLength(), 3);
+		
+		int nodeCount = 0;
+		
+		Node structNode = list.item(nodeCount++);
+		
+		checkStructProperties(structNode, "FooData", "-86983438", "org.apache.etch.tests.Foo.FooData", "null", null);
+		checkStructValueProperties(structNode, "code", "-325551150", "code", "int", "true", "false", null, null);
+		checkStructValueProperties(structNode, "fooTable", "-900628371", "fooTable", "org.apache.etch.tests.Foo.FooTable", "false", "false", null, null);
+		checkStructValueProperties(structNode, "barData", "-780728328", "barData", "org.apache.etch.tests.Bar.BarData", "false", "false", null, null);
+		checkStructValueProperties(structNode, "bazData", "-254148608", "bazData", "org.apache.etch.tests.Baz.BazData", "false", "false", null, null);
+		
+		
+		
+		structNode = list.item(nodeCount++);
+		
+		checkStructProperties(structNode, "BazData", "467213084", "org.apache.etch.tests.Baz.BazData", "null", null);
+		checkStructValueProperties(structNode, "code", "-325551150", "code", "int", "false", "false", null, null);
+		checkStructValueProperties(structNode, "bazTable", "2073680920", "bazTable", "org.apache.etch.tests.Baz.BazTable", "false", "false", null, null);
+		
+		structNode = list.item(nodeCount++);
+		
+		checkStructProperties(structNode, "BarData", "1671967500", "org.apache.etch.tests.Bar.BarData", "null", null);
+		checkStructValueProperties(structNode, "code", "-325551150", "code", "int", "false", "false", null, null);
+		checkStructValueProperties(structNode, "barTable", "-902376928", "barTable", "org.apache.etch.tests.Bar.BarTable", "false", "false", null, null);
+		checkStructValueProperties(structNode, "bazData", "-254148608", "bazData", "org.apache.etch.tests.Baz.BazData", "false", "false", null, null);
+		
+		
+		
+	}
+		
+	/** @throws Exception */
+	@org.junit.Test
+	public void textExceptions() throws Exception
+	{
+		// verify exceptions
+		NodeList exceptionsNodeList = document.getElementsByTagName("exceptions");
+		
+		assertEquals(exceptionsNodeList.getLength(), 1);
+		
+		Node exceptionsNode = exceptionsNodeList.item(0);
+		
+		ArrayList<Node>list = new ArrayList<Node>();
+			
+		NodeList exceptionsNodeChildren = exceptionsNode.getChildNodes();
+		for(int i = 0; i < exceptionsNodeChildren.getLength(); i++)
+		{
+			if(exceptionsNodeChildren.item(i).getNodeName() == "exception")
+			{
+				list.add(exceptionsNodeChildren.item(i));
+			}
+		}
+		
+		
+		assertEquals(list.size(), 0);
+		
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void testMethods() throws Exception
+	{
+		// verify methods
+		NodeList list = document.getElementsByTagName("method");
+		
+		assertEquals(18, list.getLength() );
+		
+		int nodeCount = 0;
+		
+		Node methodNode = list.item(nodeCount++);
+		
+		
+		checkMethodProperties(methodNode, "foo1", "2107096233", "org.apache.etch.tests.Foo.foo1", "none", "false", "both", null, null, null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "fooData", "-1798637973", "fooData", 
+				"org.apache.etch.tests.Foo.FooData", "false", "false", null, null);
+		checkResult(methodNode, "222044908", "org.apache.etch.tests.Foo._result_foo1", "boolean", "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_foo1", "222044908", "org.apache.etch.tests.Foo._result_foo1", 
+				"none", "true", "both", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result",
+				"boolean", "true", "false", null, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "foo2", "2107096234", "org.apache.etch.tests.Foo.foo2", "none", "false", "server", null, 
+				null, null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "fooData", "-1798637973", "fooData", 
+				"org.apache.etch.tests.Foo.FooData", "false", "false", null, null);
+		checkResult(methodNode, "222044909", "org.apache.etch.tests.Foo._result_foo2", "boolean", "true",  "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_foo2", "222044909", "org.apache.etch.tests.Foo._result_foo2", 
+				"none", "true", "client", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result",
+				"boolean", "true", "false", null, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "foo3", "2107096235", "org.apache.etch.tests.Foo.foo3", "none", "false", "client", null, null, null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "fooData", "-1798637973", "fooData", 
+				"org.apache.etch.tests.Foo.FooData", "false", "false", null, null);
+		checkResult(methodNode, "222044910", "org.apache.etch.tests.Foo._result_foo3", "boolean",  "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_foo3", "222044910", "org.apache.etch.tests.Foo._result_foo3", 
+				"none", "true", "server", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result",
+				"boolean", "true", "false", null, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "baz1", "1844117247", "org.apache.etch.tests.Baz.baz1", "none", "false", "both", null, "Method Baz1 *", null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "bazData", "-254148608", "bazData", 
+				"org.apache.etch.tests.Baz.BazData", "false", "false", null, null);
+		checkResult(methodNode, "-1773449406", "org.apache.etch.tests.Baz._result_baz1", "boolean",  "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_baz1", "-1773449406", "org.apache.etch.tests.Baz._result_baz1", 
+				"none", "true", "both", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result",
+				"boolean", "true", "false", null, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "baz2", "1844117248", "org.apache.etch.tests.Baz.baz2", "none", "false", "server", null, "Method Baz2 *", null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "bazData", "-254148608", "bazData", 
+				"org.apache.etch.tests.Baz.BazData", "false", "false", null, null);
+		checkResult(methodNode, "-1773449405", "org.apache.etch.tests.Baz._result_baz2", "boolean",  "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_baz2", "-1773449405", "org.apache.etch.tests.Baz._result_baz2", 
+				"none", "true", "client", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result",
+				"boolean", "true", "false", null, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "baz3", "1844117249", "org.apache.etch.tests.Baz.baz3", "none", "false", "client", null, "Method Baz3 *", null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "bazData", "-254148608", "bazData", 
+				"org.apache.etch.tests.Baz.BazData", "false", "false", null, null);
+		checkResult(methodNode, "-1773449404", "org.apache.etch.tests.Baz._result_baz3", "boolean",  "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_baz3", "-1773449404", "org.apache.etch.tests.Baz._result_baz3", 
+				"none", "true", "server", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result",
+				"boolean", "true", "false", null, null);
+		
+		
+		
+		
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "bar1", "-1132465393", "org.apache.etch.tests.Bar.bar1", "none", "false", "both", null, "Method Bar1 *", null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "barData", "-780728328", "barData", 
+				"org.apache.etch.tests.Bar.BarData", "false", "false", null, null);
+		checkResult(methodNode, "37892946", "org.apache.etch.tests.Bar._result_bar1", "boolean",  "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_bar1", "37892946", "org.apache.etch.tests.Bar._result_bar1", 
+				"none", "true", "both", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result",
+				"boolean", "true", "false", null, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "bar2", "-1132465392", "org.apache.etch.tests.Bar.bar2", "none", "false", "server", null, "Method Bar2 *", null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "barData", "-780728328", "barData", 
+				"org.apache.etch.tests.Bar.BarData", "false", "false", null, null);
+		checkResult(methodNode, "37892947", "org.apache.etch.tests.Bar._result_bar2", "boolean",  "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_bar2", "37892947", "org.apache.etch.tests.Bar._result_bar2", 
+				"none", "true", "client", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result",
+				"boolean", "true", "false", null, null);
+		
+		methodNode = list.item(nodeCount++);
+
+		checkMethodProperties(methodNode, "bar3", "-1132465391", "org.apache.etch.tests.Bar.bar3", "none", "false", "client", null, "Method Bar3 *", null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "barData", "-780728328", "barData", 
+				"org.apache.etch.tests.Bar.BarData", "false", "false", null, null);
+		checkResult(methodNode, "37892948", "org.apache.etch.tests.Bar._result_bar3", "boolean",  "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_bar3", "37892948", "org.apache.etch.tests.Bar._result_bar3", 
+				"none", "true", "server", "0", null, "result");
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "result", "-2130379326", "result",
+				"boolean", "true", "false", null, null);
+		
+	}
+	
+	private void checkExternProperties(Node node, String externName, String typeId, String typeName) throws Exception
+	{
+		NamedNodeMap attrs = node.getAttributes();
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(node, new String[] {"name", "typeId", "typeName"}));
+
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(node, new String[] {"externmap"}));
+
+		// verify that no new stuff has snuck into the XML binding
+		assertEquals(attrs.getLength(), 3);
+		
+		String nameAttr = attrs.getNamedItem("name").getNodeValue();
+		String typeIdAttr = attrs.getNamedItem("typeId").getNodeValue();
+		String typeNameAttr = attrs.getNamedItem("typeName").getNodeValue();
+		
+		assertEquals(nameAttr, externName);
+		assertEquals(typeIdAttr, typeId);
+		assertEquals(typeNameAttr, typeName);
+	}
+	
+	private void checkExternMapProperties(Node node, String language, String name, String nImport, String serializer, String sImport)
+	{
+		Node languageNode = null;
+		
+		NodeList children = node.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE && children.item(i).getNodeName() == "externmap")
+			{
+				Node thisNode = children.item(i);
+				NamedNodeMap attrs = thisNode.getAttributes();
+				Node languageAttr = attrs.getNamedItem("language");
+				String thisLanguage = languageAttr.getNodeValue();
+				if(thisLanguage.compareTo(language) == 0)
+				{
+					languageNode = children.item(i);
+					break;
+				}
+			}
+		}
+		
+		// verify that the language node exists
+		assertNotNull(languageNode);
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(languageNode, new String[] {"language", "name", "nImport", "serializer", "sImport"}));
+
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(languageNode, new String[] {"description"}));
+
+		NamedNodeMap attrs = languageNode.getAttributes();
+		
+		// verify that no new stuff has snuck into the XML binding
+		assertEquals(attrs.getLength(), 5);
+		
+		String nameAttr = attrs.getNamedItem("name").getNodeValue();
+		String nImportAttr = attrs.getNamedItem("nImport").getNodeValue();
+		String serializerAttr = attrs.getNamedItem("serializer").getNodeValue();
+		String sImportAttr = attrs.getNamedItem("sImport").getNodeValue();
+		
+		// verify the value of the externmap name
+		assertEquals(nameAttr, name);
+		
+		// verify the value of the externmap nImport
+		assertEquals(nImportAttr, nImport);
+		
+		// verify the value of the externmap serializer
+		assertEquals(serializerAttr, serializer);
+		
+		// verify the value of the externmap sImport
+		assertEquals(sImportAttr, sImport);
+		
+		// verify that no new children nodes have snuck in
+		assertEquals(getChildElementCount(languageNode), 0);
+	}
+	
+	private void checkStructProperties(Node structNode, String structName, String structTypeId, 
+			String structTypeName, String baseTypeName, String description)
+	{
+		NamedNodeMap attrs = structNode.getAttributes();
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(structNode, new String[] {"name", "typeId", "typeName", "baseType"}));
+
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(structNode, new String[] {"description", "field"}));
+
+		// verify that no new stuff has snuck into the XML binding
+		assertEquals(attrs.getLength(), 4);
+		
+		String nameAttr = attrs.getNamedItem("name").getNodeValue();
+		String typeAttr = attrs.getNamedItem("typeId").getNodeValue();
+		String valueAttr = attrs.getNamedItem("typeName").getNodeValue();
+		String baseTypeAttr = attrs.getNamedItem("baseType").getNodeValue();
+		
+		// verify name of constant
+		assertEquals(nameAttr, structName);
+		
+		// verify type of constant
+		assertEquals(typeAttr, structTypeId);
+		
+		// verify value of constant
+		assertEquals(valueAttr, structTypeName);
+		
+		assertEquals(baseTypeAttr, baseTypeName);
+		
+		Node child = getDescriptionElement(structNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private void checkStructValueProperties(Node structNode, String structName, String fieldId, String fieldName, 
+		String type, String isPrimitiveType, String isArray, String dimension, String description)
+	{
+		Node fieldNode = null;
+		
+		NodeList children = structNode.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE && children.item(i).getNodeName() == "field")
+			{
+				Node thisNode = children.item(i);
+				NamedNodeMap attrs = thisNode.getAttributes();
+				Node valueAttr = attrs.getNamedItem("name");
+				String thisValue = valueAttr.getNodeValue();
+				if(thisValue.compareTo(structName) == 0)
+				{
+					fieldNode = children.item(i);
+					break;
+				}
+			}
+		}
+		
+		// verify that the value node exists
+		assertNotNull(fieldNode);
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(fieldNode, new String[] {"name", "fieldId", "fieldName", "type", "isPrimitiveType",
+			"isArray", "dimension"}));
+
+		//verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(fieldNode, new String[] {"description"}));
+		
+		NamedNodeMap attrs = fieldNode.getAttributes();
+		
+		// verify that no new stuff has snuck into the XML binding
+		// dimension attr is nullable, meaning it might just not be there if isArray = "false"
+		assertEquals(attrs.getLength(), isArray == "false" ? 6 : 7);
+		
+		String fieldIdAttr = attrs.getNamedItem("fieldId").getNodeValue();
+		String fieldNameAttr = attrs.getNamedItem("fieldName").getNodeValue();
+		String typeAttr = attrs.getNamedItem("type").getNodeValue();
+		String isArrayAttr = attrs.getNamedItem("isArray").getNodeValue();
+		
+		Node dimensionNode = attrs.getNamedItem("dimension");
+		String dimensionAttr = dimensionNode == null ? dimension : dimensionNode.getNodeValue();
+		
+		
+		// verify the value of the externmap name
+		assertEquals(fieldIdAttr, fieldId);
+		assertEquals(fieldNameAttr, fieldName);
+		assertEquals(typeAttr, type);
+		assertEquals(isArrayAttr, isArray);
+		assertEquals(dimensionAttr, dimension);
+		
+		Node child = getDescriptionElement(fieldNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private void checkMethodProperties(Node methodNode, String name, String methodId, String methodName, String pool, String isOneway, 
+			String direction, String timeout, String description, String result )
+	{
+		NamedNodeMap attrs = methodNode.getAttributes();
+		boolean isResultMessage = false;
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(methodNode, new String[] {"name", "typeId", "typeName", "asyncReceiverMode", "isOneway", "messageDirection", "timeout",
+				"responseField"}));
+
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(methodNode, new String[] {"description", "exception", "authorize", "field", "result"}));
+	
+		// verify that no new stuff has snuck into the XML binding
+		isResultMessage = name.startsWith("_result");
+		
+		assertEquals(isResultMessage? 8 : 6, attrs.getLength());
+		
+		String nameAttr = attrs.getNamedItem("name").getNodeValue();
+		String typeIdAttr = attrs.getNamedItem("typeId").getNodeValue();
+		String typeNameAttr = attrs.getNamedItem("typeName").getNodeValue();
+		String poolAttr = attrs.getNamedItem("asyncReceiverMode").getNodeValue();
+		String isOnewayAttr = attrs.getNamedItem("isOneway").getNodeValue();
+		String directionAttr = attrs.getNamedItem("messageDirection").getNodeValue();
+		String timeoutAttr = "";
+		String resultAttr = "";
+		
+		if ( isResultMessage )
+		{
+			timeoutAttr = attrs.getNamedItem("timeout").getNodeValue();
+			resultAttr = attrs.getNamedItem("responseField").getNodeValue();
+		}
+		
+		// verify name of method
+		assertEquals(nameAttr, name);
+		
+		// verify type of method
+		assertEquals(typeIdAttr, methodId);
+		
+		// verify value of method
+		assertEquals(typeNameAttr, methodName);
+		
+		// verify value of pool
+		assertEquals(poolAttr, pool);
+		
+		// verify value of isOneway
+		assertEquals(isOnewayAttr, isOneway);
+		
+		// verify value of isOneway
+		assertEquals(directionAttr, direction);
+		
+		// verify value of isOneway
+		if ( isResultMessage )
+		{
+			assertEquals(timeoutAttr, timeout);
+			assertEquals(resultAttr, result);
+		}
+		Node child = getDescriptionElement(methodNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private void checkAuthorize(Node methodNode, String authorizeMethodName)
+	{
+		Node child = getAuthorizeElement(methodNode);
+		
+		if(authorizeMethodName == null)
+		{
+			assertNull(child);
+		}
+		else
+		{
+			// verify that no unknown attr exist
+			assertTrue(onlyAttrsOfName(child, new String[] {"methodName"}));
+
+			// verify that no unknown child nodes exist
+			assertTrue(onlyChildNodesOfName(child, new String[] {}));
+		
+			String authorizeAttr = child.getAttributes().getNamedItem("methodName").getNodeValue();
+			
+			assertEquals(authorizeAttr, authorizeMethodName);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private void checkResult(Node methodNode, String fieldId, String fieldName, String type, 
+		String isPrimitiveType, String isArray, String dimension, String description)
+	{
+		Node resultNode = getResultElement(methodNode);
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(resultNode, new String[] {"fieldId", "fieldName", "type", "isPrimitiveType", "isArray", "dimension"}));
+
+		// verify that the value node exists
+		assertNotNull(resultNode);
+		
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(resultNode, new String[] {"description"}));
+	
+		NamedNodeMap attrs = resultNode.getAttributes();
+		
+		// verify that no new stuff has snuck into the XML binding
+		
+		// this is special case of a oneway message, so we should only have 'type=void' and 'isArray=true' specified.
+		String fieldIdAttr = null;
+		String fieldNameAttr = null;
+		
+		if(fieldId == null)
+		{
+			assertEquals(attrs.getLength(), 2);
+			
+		}
+		else // dimension attr is nullable, meaning it might just not be there if isArray = "false"
+		{
+			fieldIdAttr = attrs.getNamedItem("fieldId").getNodeValue();
+			fieldNameAttr = attrs.getNamedItem("fieldName").getNodeValue();
+			
+			assertEquals(attrs.getLength(), isArray == "false" ? 5 : 6);
+		}
+		
+		String typeAttr = attrs.getNamedItem("type").getNodeValue();
+		String isArrayAttr = attrs.getNamedItem("isArray").getNodeValue();
+
+		Node dimensionNode = attrs.getNamedItem("dimension");
+		String dimensionAttr = dimensionNode == null ? dimension : dimensionNode.getNodeValue();
+		
+		assertEquals(fieldIdAttr, fieldId);
+		assertEquals(fieldNameAttr, fieldName);
+		assertEquals(typeAttr, type);
+		assertEquals(isArrayAttr, isArray);
+		assertEquals(dimensionAttr, dimension);
+		
+		Node child = getDescriptionElement(resultNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private void checkMethodFieldProperties(Node methodNode, String name, String fieldId, String fieldName, String type, 
+			String isPrimitiveType, String isArray, String dimension, String description)
+	{
+		Node fieldNode = null;
+		
+		NodeList children = methodNode.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE && children.item(i).getNodeName() == "field")
+			{
+				Node thisNode = children.item(i);
+				NamedNodeMap attrs = thisNode.getAttributes();
+				Node valueAttr = attrs.getNamedItem("name");
+				String thisValue = valueAttr.getNodeValue();
+				if(thisValue.compareTo(name) == 0)
+				{
+					fieldNode = children.item(i);
+					break;
+				}
+			}
+		}
+		
+		// verify that the value node exists
+		assertNotNull(fieldNode);
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(fieldNode, new String[] {"name", "fieldId", "fieldName", "type", 
+				"isPrimitiveType", "isArray", "dimension" }));
+
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(fieldNode, new String[] {"description"}));
+	
+		NamedNodeMap attrs = fieldNode.getAttributes();
+		
+		// verify that no new stuff has snuck into the XML binding
+		// dimension attr is nullable, meaning it might just not be there if isArray = "false"
+		assertEquals(attrs.getLength(), isArray == "false" ? 6 : 7);
+		
+		String fieldIdAttr = attrs.getNamedItem("fieldId").getNodeValue();
+		String fieldNameAttr = attrs.getNamedItem("fieldName").getNodeValue();
+		String typeAttr = attrs.getNamedItem("type").getNodeValue();
+		String isArrayAttr = attrs.getNamedItem("isArray").getNodeValue();
+		String isPrimitiveTypeAttr = attrs.getNamedItem("isPrimitiveType").getNodeValue();
+		
+		Node dimensionNode = attrs.getNamedItem("dimension");
+		String dimensionAttr = dimensionNode == null ? dimension : dimensionNode.getNodeValue();
+		
+		assertEquals(fieldIdAttr, fieldId);
+		assertEquals(fieldNameAttr, fieldName);
+		assertEquals(typeAttr, type);
+		assertEquals(isArrayAttr, isArray);
+		assertEquals(dimensionAttr, dimension);
+		assertEquals( isPrimitiveType, isPrimitiveTypeAttr );
+		
+		Node child = getDescriptionElement(fieldNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private Node getDescriptionElement(Node node)
+	{
+		NodeList children = node.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			short nodeType = children.item(i).getNodeType();
+			String nodeName = children.item(i).getNodeName();
+			if(nodeType == Node.ELEMENT_NODE && nodeName == "description")
+			{
+				return children.item(i);
+			}
+		}
+		return null;
+	}
+	
+	private Node getAuthorizeElement(Node node)
+	{
+		NodeList children = node.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			short nodeType = children.item(i).getNodeType();
+			String nodeName = children.item(i).getNodeName();
+			if(nodeType == Node.ELEMENT_NODE && nodeName == "authorize")
+			{
+				return children.item(i);
+			}
+		}
+		return null;
+	}
+	
+	private Node getResultElement(Node node)
+	{
+		NodeList children = node.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			short nodeType = children.item(i).getNodeType();
+			String nodeName = children.item(i).getNodeName();
+			if(nodeType == Node.ELEMENT_NODE && nodeName == "result")
+			{
+				return children.item(i);
+			}
+		}
+		return null;
+	}
+	
+	private int getChildElementCount(Node node)
+	{
+		int count = 0;
+		
+		NodeList children = node.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE)
+			{
+				count++;
+			}
+		}
+		
+		return count;
+	}
+	
+	private boolean onlyChildNodesOfName(Node node, String[] elementNamesToCheck)
+	{
+		NodeList children = node.getChildNodes();
+		
+		boolean hasValidChildren = true;
+		
+		for(int i = 0; i < children.getLength(); i++)
+		{
+		
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE)
+			{
+				String elementName = children.item(i).getNodeName();
+				
+				boolean matches = false;
+				for (String element : elementNamesToCheck)
+				{
+					if(0 == elementName.compareTo(element) )
+					{
+						matches = true;
+						break;
+					}
+				}
+				
+				if(matches == false)
+				{
+					hasValidChildren = false;
+					break;
+				}
+			}	
+		}
+		
+		return hasValidChildren;
+	}
+	
+	private boolean onlyAttrsOfName(Node node, String[] attrNamesToCheck)
+	{
+		NamedNodeMap attrs = node.getAttributes();
+		
+		boolean hasValidAttrs = true;
+		
+		for(int i = 0; i < attrs.getLength(); i++)
+		{
+			String attrName = attrs.item(i).getNodeName();
+			
+			boolean matches = false;
+			for (String element : attrNamesToCheck)
+			{
+				if(0 == attrName.compareTo(element) )
+				{
+					matches = true;
+					break;
+				}
+			}
+			
+			if(matches == false)
+			{
+				hasValidAttrs = false;
+				break;
+			}
+			
+		}
+		
+		return hasValidAttrs;
+	}
+}
diff --git a/tests/src/test/java/org/apache/etch/tests/TestRemoteTest1DotJava.java b/tests/src/test/java/org/apache/etch/tests/TestRemoteTest1DotJava.java
new file mode 100644
index 0000000..973cc8b
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/TestRemoteTest1DotJava.java
@@ -0,0 +1,1542 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.reflect.Array;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.support.DeliveryService;
+import org.apache.etch.bindings.java.support.Mailbox;
+import org.apache.etch.bindings.java.transport.SessionMessage;
+import org.apache.etch.tests.Test1.E1;
+import org.apache.etch.tests.Test1.Excp1;
+import org.apache.etch.tests.Test1.Excp3;
+import org.apache.etch.tests.Test1.Excp4;
+import org.apache.etch.tests.Test1.S1;
+import org.apache.etch.tests.Test1.S2;
+import org.apache.etch.util.core.Who;
+
+
+/** Test of RemoteTest1 */
+public class TestRemoteTest1DotJava
+{
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_nothing() throws Exception
+	{
+		test.nothing();
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_nothing,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_nothing,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_nothing.getTimeout() );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_incr1() throws Exception
+	{
+		svc.xresult = 2;
+		assertEquals( 2, test.incr( 1 ) );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_incr,
+			new Field[] { ValueFactoryTest1._mf_x },
+			new Object[] { 1 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_incr,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_incr.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_incr2() throws Exception
+	{
+		svc.xresult = 3;
+		assertEquals( 3, test.incr( 2 ) );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_incr,
+			new Field[] { ValueFactoryTest1._mf_x },
+			new Object[] { 2 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_incr,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_incr.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_incr3() throws Exception
+	{
+		svc.xresult = -1;
+		assertEquals( -1, test.incr( -2 ) );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_incr,
+			new Field[] { ValueFactoryTest1._mf_x },
+			new Object[] { -2 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_incr,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_incr.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_sub1() throws Exception
+	{
+		svc.xresult = 5;
+		assertEquals( 5, test.sub( 7, 2 ) );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sub,
+			new Field[] { ValueFactoryTest1._mf_x, ValueFactoryTest1._mf_y },
+			new Object[] { 7, 2 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sub,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sub.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_sub2() throws Exception
+	{
+		svc.xresult = 8;
+		assertEquals( 8, test.sub( 23, 15 ) );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sub,
+			new Field[] { ValueFactoryTest1._mf_x, ValueFactoryTest1._mf_y },
+			new Object[] { 23, 15 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sub,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sub.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_sub3() throws Exception
+	{
+		svc.xresult = -5;
+		assertEquals( -5, test.sub( 2, 7 ) );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sub,
+			new Field[] { ValueFactoryTest1._mf_x, ValueFactoryTest1._mf_y },
+			new Object[] { 2, 7 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sub,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sub.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_sum() throws Exception
+	{
+		svc.xresult = 24;
+		int[] arg = { 1, 2, 3, 7, 11 };
+		assertEquals( 24, test.sum( arg ) );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sum,
+			new Field[] { ValueFactoryTest1._mf_x },
+			new Object[] { arg },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sum,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sum.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_trans1() throws Exception
+	{
+		svc.xresult = 2;
+		assertEquals( 2, test.trans( E1.A, 5 ) ); // divide by 2
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_trans,
+			new Field[] { ValueFactoryTest1._mf_e, ValueFactoryTest1._mf_x },
+			new Object[] { E1.A, 5 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_trans2() throws Exception
+	{
+		svc.xresult = 10;
+		assertEquals( 10, test.trans( E1.B, 5 ) ); // mul by 2
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_trans,
+			new Field[] { ValueFactoryTest1._mf_e, ValueFactoryTest1._mf_x },
+			new Object[] { E1.B, 5 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_trans3() throws Exception
+	{
+		svc.xresult = 12;
+		assertEquals( 12, test.trans( E1.C, 5 ) ); // add 7
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_trans,
+			new Field[] { ValueFactoryTest1._mf_e, ValueFactoryTest1._mf_x },
+			new Object[] { E1.C, 5 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_dist1() throws Exception
+	{
+		svc.xresult = Math.sqrt( 3 );
+		S1 arg1 =  new S1( 1, 1, 1 );
+		S1 arg2 = new S1( 0, 0, 0 );
+		assertEquals( Math.sqrt( 3 ), test.dist( arg1, arg2 ) );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_dist,
+			new Field[] { ValueFactoryTest1._mf_a, ValueFactoryTest1._mf_b },
+			new Object[] { arg1, arg2 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_dist,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_dist.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_dist2() throws Exception
+	{
+		svc.xresult = Math.sqrt( 35 );
+		S1 arg1 = new S1( 1, 2, 3 );
+		S1 arg2 = new S1( 6, 5, 4 );
+		assertEquals( Math.sqrt( 35 ), test.dist( arg1, arg2 ) );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_dist,
+			new Field[] { ValueFactoryTest1._mf_a, ValueFactoryTest1._mf_b },
+			new Object[] { arg1, arg2 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_dist,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_dist.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_dist3() throws Exception
+	{
+		svc.xresult = Math.sqrt( 56 );
+		S1 arg1 = new S1( 1, 2, 3 );
+		S1 arg2 = new S1( -1, -2, -3 );
+		assertEquals( Math.sqrt( 56 ), test.dist( arg1, arg2 ) );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_dist,
+			new Field[] { ValueFactoryTest1._mf_a, ValueFactoryTest1._mf_b },
+			new Object[] { arg1, arg2 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_dist,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_dist.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_fill1() throws Exception
+	{
+		svc.xresult = new int[] {};
+		int[] x = test.fill( 0, 1 );
+		assertEquals( 0, x.length );
+		for (int i: x)
+			assertEquals( 1, i );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_fill,
+			new Field[] { ValueFactoryTest1._mf_n, ValueFactoryTest1._mf_x },
+			new Object[] { 0, 1 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fill,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fill.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_fill2() throws Exception
+	{
+		svc.xresult = new int[] { 2 };
+		int[] x = test.fill( 1, 2 );
+		assertEquals( 1, x.length );
+		for (int i: x)
+			assertEquals( 2, i );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_fill,
+			new Field[] { ValueFactoryTest1._mf_n, ValueFactoryTest1._mf_x },
+			new Object[] { 1, 2 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fill,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fill.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_fill3() throws Exception
+	{
+		svc.xresult = new int[] { 3, 3 };
+		int[] x = test.fill( 2, 3 );
+		assertEquals( 2, x.length );
+		for (int i: x)
+			assertEquals( 3, i );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_fill,
+			new Field[] { ValueFactoryTest1._mf_n, ValueFactoryTest1._mf_x },
+			new Object[] { 2, 3 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fill,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fill.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_blow1() throws Exception
+	{
+		try
+		{
+			svc.xresult = new Excp1( "foo", 2 );
+			test.blow( "foo", 2 );
+			fail( "blow did not throw" );
+		}
+		catch( Excp1 e )
+		{
+			assertEquals( "foo", e.msg );
+			assertEquals( 2, e.code );
+		}
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_blow,
+			new Field[] { ValueFactoryTest1._mf_msg, ValueFactoryTest1._mf_code },
+			new Object[] { "foo", 2 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_blow,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_blow.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_blow2() throws Exception
+	{
+		try
+		{
+			svc.xresult = new Excp1( "bar", 3 );
+			test.blow( "bar", 3 );
+			fail( "blow did not throw" );
+		}
+		catch( Excp1 e )
+		{
+			assertEquals( "bar", e.msg );
+			assertEquals( 3, e.code );
+		}
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_blow,
+			new Field[] { ValueFactoryTest1._mf_msg, ValueFactoryTest1._mf_code },
+			new Object[] { "bar", 3 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_blow,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_blow.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_beets1() throws Exception
+	{
+		svc.xresult = 5;
+		assertEquals( 5, test.beets( E1.A ) );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets,
+			new Field[] { ValueFactoryTest1._mf_e },
+			new Object[] { E1.A },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_beets2() throws Exception
+	{
+		try
+		{
+			svc.xresult = new Excp3();
+			test.beets( E1.B );
+			fail( "beets did not throw" );
+		}
+		catch ( Excp3 e )
+		{
+			assertTrue( true );
+		}
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets,
+			new Field[] { ValueFactoryTest1._mf_e },
+			new Object[] { E1.B },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_beets3() throws Exception
+	{
+		try
+		{
+			svc.xresult = new Excp4();
+			test.beets( E1.C );
+			fail( "beets did not throw" );
+		}
+		catch ( Excp4 e )
+		{
+			assertTrue( true );
+		}
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets,
+			new Field[] { ValueFactoryTest1._mf_e },
+			new Object[] { E1.C },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_beets4() throws Exception
+	{
+		svc.xresult = null;
+		assertNull( test.beets( null ) );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets.getTimeout() );
+	}
+
+	/////////////
+	// BOOLEAN //
+	/////////////
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_boolean_null() throws Exception
+	{
+		Boolean a = null;
+		svc.xresult = a;
+		Boolean r = test.p_boolean( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_boolean,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_boolean() throws Exception
+	{
+		Boolean a = true;
+		svc.xresult = a;
+		Boolean r = test.p_boolean( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_boolean,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_boolean_array_null() throws Exception
+	{
+		boolean[] a = null;
+		svc.xresult = a;
+		boolean[] r = test.p_boolean_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_boolean_array,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean_array.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_boolean_array() throws Exception
+	{
+		boolean x = false;
+		boolean y = true;
+		boolean[] a = { x, y };
+		svc.xresult = a;
+		boolean[] r = test.p_boolean_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_boolean_array,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean_array.getTimeout() );
+	}
+
+	//////////
+	// BYTE //
+	//////////
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_byte_null() throws Exception
+	{
+		Byte a = null;
+		svc.xresult = a;
+		Byte r = test.p_byte( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_byte,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_byte() throws Exception
+	{
+		Byte a = 1;
+		svc.xresult = a;
+		Byte r = test.p_byte( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_byte,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_byte_array_null() throws Exception
+	{
+		byte[] a = null;
+		svc.xresult = a;
+		byte[] r = test.p_byte_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_byte_array,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte_array.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_byte_array() throws Exception
+	{
+		byte x = 12;
+		byte y = 23;
+		byte[] a = { x, y };
+		svc.xresult = a;
+		byte[] r = test.p_byte_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_byte_array,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte_array.getTimeout() );
+	}
+
+	///////////
+	// SHORT //
+	///////////
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_short_null() throws Exception
+	{
+		Short a = null;
+		svc.xresult = a;
+		Short r = test.p_short( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_short,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_short() throws Exception
+	{
+		Short a = 1234;
+		svc.xresult = a;
+		Short r = test.p_short( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_short,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_short_array_null() throws Exception
+	{
+		short[] a = null;
+		svc.xresult = a;
+		short[] r = test.p_short_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_short_array,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short_array.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_short_array() throws Exception
+	{
+		short x = 1234;
+		short y = 2345;
+		short[] a = { x, y };
+		svc.xresult = a;
+		short[] r = test.p_short_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_short_array,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short_array.getTimeout() );
+	}
+
+	/////////
+	// INT //
+	/////////
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_int_null() throws Exception
+	{
+		Integer a = null;
+		svc.xresult = a;
+		Integer r = test.p_int( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_int,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_int() throws Exception
+	{
+		Integer a = 12345678;
+		svc.xresult = a;
+		Integer r = test.p_int( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_int,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_int_array_null() throws Exception
+	{
+		int[] a = null;
+		svc.xresult = a;
+		int[] r = test.p_int_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_int_array,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int_array.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_int_array() throws Exception
+	{
+		int x = 12345678;
+		int y = 23456789;
+		int[] a = { x, y };
+		svc.xresult = a;
+		int[] r = test.p_int_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_int_array,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int_array.getTimeout() );
+	}
+
+	//////////
+	// LONG //
+	//////////
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_long_null() throws Exception
+	{
+		Long a = null;
+		svc.xresult = a;
+		Long r = test.p_long( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_long,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_long() throws Exception
+	{
+		Long a = 1234567812345678L;
+		svc.xresult = a;
+		Long r = test.p_long( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_long,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_long_array_null() throws Exception
+	{
+		long[] a = null;
+		svc.xresult = a;
+		long[] r = test.p_long_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_long_array,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long_array.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_long_array() throws Exception
+	{
+		long x = 1234567812345678L;
+		long y = 2345678923456789L;
+		long[] a = { x, y };
+		svc.xresult = a;
+		long[] r = test.p_long_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_long_array,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long_array.getTimeout() );
+	}
+
+	///////////
+	// FLOAT //
+	///////////
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_float_null() throws Exception
+	{
+		Float a = null;
+		svc.xresult = a;
+		Float r = test.p_float( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_float,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_float() throws Exception
+	{
+		Float a = 123.456f;
+		svc.xresult = a;
+		Float r = test.p_float( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_float,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_float_array_null() throws Exception
+	{
+		float[] a = null;
+		svc.xresult = a;
+		float[] r = test.p_float_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_float_array,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float_array.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_float_array() throws Exception
+	{
+		float x = 123.456f;
+		float y = 234.567f;
+		float[] a = { x, y };
+		svc.xresult = a;
+		float[] r = test.p_float_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_float_array,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float_array.getTimeout() );
+	}
+
+	////////////
+	// DOUBLE //
+	////////////
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_double_null() throws Exception
+	{
+		Double a = null;
+		svc.xresult = a;
+		Double r = test.p_double( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_double,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_double() throws Exception
+	{
+		Double a = 12345678.12345678;
+		svc.xresult = a;
+		Double r = test.p_double( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_double,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_double_array_null() throws Exception
+	{
+		double[] a = null;
+		svc.xresult = a;
+		double[] r = test.p_double_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_double_array,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double_array.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_double_array() throws Exception
+	{
+		double x = 12345678.12345678;
+		double y = 23456789.23456789;
+		double[] a = { x, y };
+		svc.xresult = a;
+		double[] r = test.p_double_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_double_array,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double_array.getTimeout() );
+	}
+
+	////////////
+	// STRING //
+	////////////
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_string_null() throws Exception
+	{
+		String a = null;
+		svc.xresult = a;
+		String r = test.p_string( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_string,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_string() throws Exception
+	{
+		String a = "abc";
+		svc.xresult = a;
+		String r = test.p_string( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_string,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_string_array_null() throws Exception
+	{
+		String[] a = null;
+		svc.xresult = a;
+		String[] r = test.p_string_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_string_array,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string_array.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_string_array() throws Exception
+	{
+		String x = "abc";
+		String y = "bcd";
+		String[] a = { x, y };
+		svc.xresult = a;
+		String[] r = test.p_string_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_string_array,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string_array.getTimeout() );
+	}
+	
+	////////////
+	// OBJECT //
+	////////////
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_object_null() throws Exception
+	{
+		Object a = null;
+		svc.xresult = a;
+		Object r = test.p_object( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_object,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_object() throws Exception
+	{
+		Object a = "abc";
+		svc.xresult = a;
+		Object r = test.p_object( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_object,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_object1() throws Exception
+	{
+		Object a1 = 23;
+		svc.xresult = a1;
+		Object r1 = test.p_object( a1 );
+		assertObjectEquals( a1, r1 );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_object,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a1 },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_object_array_null() throws Exception
+	{
+		String[] a = null;
+		svc.xresult = a;
+		String[] r = test.p_string_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_string_array,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string_array.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_object_array() throws Exception
+	{
+		Object x = "abc";
+		Object y = "bcd";
+		Object[] a = { x, y };
+		svc.xresult = a;
+		Object[] r = test.p_object_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_object_array,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object_array.getTimeout() );		
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_object_array1() throws Exception
+	{
+		Object x = 22;
+		Object y = 33;
+		Object[] a = { x, y };
+		svc.xresult = a;
+		Object[] r = test.p_object_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_object_array,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object_array.getTimeout() );		
+	}
+	
+	
+
+	////////
+	// E1 //
+	////////
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_E1_null() throws Exception
+	{
+		E1 a = null;
+		svc.xresult = a;
+		E1 r = test.p_E1( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_E1,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_E1() throws Exception
+	{
+		E1 a = E1.A;
+		svc.xresult = a;
+		E1 r = test.p_E1( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_E1,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_E1_array_null() throws Exception
+	{
+		E1[] a = null;
+		svc.xresult = a;
+		E1[] r = test.p_E1_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_E1_array,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1_array.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_E1_array() throws Exception
+	{
+		E1 x = E1.A;
+		E1 y = E1.B;
+		E1[] a = { x, y };
+		svc.xresult = a;
+		E1[] r = test.p_E1_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_E1_array,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1_array.getTimeout() );
+	}
+
+	////////
+	// S1 //
+	////////
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_S1_null() throws Exception
+	{
+		S1 a = null;
+		svc.xresult = a;
+		S1 r = test.p_S1( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S1,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_S1() throws Exception
+	{
+		S1 a = new S1( 1, 2, 3 );
+		svc.xresult = a;
+		S1 r = test.p_S1( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S1,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_S1_array_null() throws Exception
+	{
+		S1[] a = null;
+		svc.xresult = a;
+		S1[] r = test.p_S1_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S1_array,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1_array.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_S1_array() throws Exception
+	{
+		S1 x = new S1( 1, 2, 3 );
+		S1 y = new S1( 2, 3, 4 );
+		S1[] a = { x, y };
+		svc.xresult = a;
+		S1[] r = test.p_S1_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S1_array,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1_array.getTimeout() );
+	}
+
+	////////
+	// S2 //
+	////////
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_S2_null() throws Exception
+	{
+		S2 a = null;
+		svc.xresult = a;
+		S2 r = test.p_S2( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S2,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_S2() throws Exception
+	{
+		S2 a = new S2( new S1( 1, 2, 3 ), new S1( 2, 3, 4 ), E1.A );
+		svc.xresult = a;
+		S2 r = test.p_S2( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S2,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_S2_array_null() throws Exception
+	{
+		S2[] a = null;
+		svc.xresult = a;
+		S2[] r = test.p_S2_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S2_array,
+			new Field[] {},
+			new Object[] {},
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2_array.getTimeout() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_p_S2_array() throws Exception
+	{
+		S2 x = new S2( new S1( 1, 2, 3 ), new S1( 2, 3, 4 ), E1.A );
+		S2 y = new S2( new S1( 2, 3, 4 ), new S1( 3, 4, 5 ), E1.B );
+		S2[] a = { x, y };
+		svc.xresult = a;
+		S2[] r = test.p_S2_array( a );
+		assertObjectEquals( a, r );
+		check( What.CALL,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S2_array,
+			new Field[] { ValueFactoryTest1._mf_a },
+			new Object[] { a },
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2_array,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2_array.getTimeout() );
+	}
+
+	///////////////////
+	// UTILITY STUFF //
+	///////////////////
+
+	/**
+	 * @param a
+	 * @param b
+	 */
+	private void assertObjectEquals( Object a, Object b )
+	{
+		if (a == b)
+			return;
+		
+		if (a == null || b == null)
+		{
+			fail( "a == null || b == null" );
+			return;
+		}
+		
+		assertSame( a.getClass(), b.getClass() );
+		
+		if (a.getClass().isArray() && b.getClass().isArray())
+		{
+			assertArrayEquals( a, b );
+			return;
+		}
+		
+		assertEquals( a, b );
+	}
+	
+	/**
+	 * @param a
+	 * @param b
+	 */
+	private void assertArrayEquals( Object a, Object b )
+	{
+		int n = Array.getLength( a );
+		assertEquals( n, Array.getLength( b ) );
+		for (int i = 0; i < n; i++)
+			assertObjectEquals( Array.get( a, i ), Array.get( b, i ) );
+	}
+
+	private void check( What what, Type type, Field[] fields, Object[] objects,
+		Type resultType, int timeout )
+	{
+		assertSame( "what", what, svc.what );
+		assertSame( "type", type, svc.xmsg.type() );
+		
+		int n = fields.length;
+		assertEquals( "objects.length", n, objects.length );
+		assertEquals( "msg.size", n, svc.xmsg.size() );
+//		System.out.println("size = " + svc.xmsg.size());
+		
+		for (int i = 0; i < n; i++)
+		{
+			Field f = fields[i];
+			assertEquals( "object_"+i, objects[i], svc.xmsg.get( f ) );
+		}
+		
+		assertSame( "resultType", resultType, svc.xresponseType );
+		assertSame( "responseField", ValueFactoryTest1._mf_result, svc.xresponseField );
+		assertEquals( "timeout", timeout, svc.xtimeout );
+	}
+	
+	/** type of call */
+	public enum What
+	{
+		/** */
+		SEND,
+		/** */
+		CALL,
+		/** */
+		SHUTDOWNOUTPUT,
+		/** */
+		BEGINCALL
+	}
+	
+	private final MyDeliveryService svc = new MyDeliveryService();
+	
+	private final Test1 test = new RemoteTest1( svc, new ValueFactoryTest1( "tcp:" ) );
+
+	/** */
+	public static class MyDeliveryService implements DeliveryService
+	{
+		/** */
+		public What what;
+		/** */
+		public Message xmsg;
+		/** */
+		public Type xresponseType;
+		/** */
+		public Field xresponseField;
+		/** */
+		public Integer xtimeout;
+		/** */
+		public Object xresult;
+		/** */
+		public Mailbox xmb;
+
+		/** */
+		public void clear()
+		{
+			what = null;
+			xmsg = null;
+			xresponseType = null;
+			xresponseField = null;
+			xtimeout = null;
+			xresult = null;
+		}
+
+		public void transportMessage( Who recipient, Message msg )
+			throws Exception
+		{
+			assertNull( what );
+			what = What.SEND;
+			xmsg = msg;
+		}
+
+		public Mailbox begincall( Message msg )
+		{
+			assertNull( what );
+			what = What.BEGINCALL;
+			xmsg = msg;
+			xmb = new MyMailbox();
+			return xmb;
+		}
+		
+		public Object endcall( Mailbox mb, Type responseType ) throws Exception
+		{
+			assertSame( What.BEGINCALL, what );
+			assertSame( xmb, mb );
+			what = What.CALL;
+			xmb = null;
+			xresponseType = responseType;
+			xresponseField = responseType.getResponseField();
+			xtimeout = responseType.getTimeout();
+			if (xresult instanceof Exception)
+				throw (Exception) xresult;
+			return xresult;
+		}
+
+		public Object transportQuery( Object query ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void transportControl( Object control, Object value ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void transportNotify( Object event ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean sessionMessage( Who sender, Message msg )
+			throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Object sessionQuery( Object query ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void sessionControl( Object control, Object value )
+			throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void sessionNotify( Object event ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public SessionMessage getSession()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void setSession( SessionMessage session )
+		{
+			throw new UnsupportedOperationException();
+		}
+	}
+	
+	static class MyMailbox implements Mailbox
+	{
+		public boolean closeDelivery()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean closeRead() throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Long getMessageId()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean isClosed()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean isEmpty()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean isFull()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean message( Who sender, Message msg ) throws Exception
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Element read() throws InterruptedException
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Element read( int maxDelay ) throws InterruptedException
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void registerNotify( Notify notify, Object state, int maxDelay )
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void unregisterNotify( Notify notify )
+		{
+			throw new UnsupportedOperationException();
+		}
+	}
+}
diff --git a/tests/src/test/java/org/apache/etch/tests/TestStubTest1DotJava.java b/tests/src/test/java/org/apache/etch/tests/TestStubTest1DotJava.java
new file mode 100644
index 0000000..060d71a
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/TestStubTest1DotJava.java
@@ -0,0 +1,593 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.etch.bindings.java.msg.Message;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.bindings.java.support.DeliveryService;
+import org.apache.etch.bindings.java.support.Mailbox;
+import org.apache.etch.bindings.java.support.Pool;
+import org.apache.etch.bindings.java.support._Etch_AuthException;
+import org.apache.etch.bindings.java.transport.SessionMessage;
+import org.apache.etch.util.core.Who;
+
+
+/** Test of StubTest1 */
+public class TestStubTest1DotJava 
+{
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_nothing() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_nothing,
+			vf );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_nothing );
+		assertEquals( 0, src.xreply.size() );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_incr1() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_incr, vf );
+		msg.put( ValueFactoryTest1._mf_x, 3 );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_incr );
+		assertEquals( 1, src.xreply.size() );
+		assertEquals( 4, src.xreply.get( ValueFactoryTest1._mf_result ) );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_incr2() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_incr, vf );
+		// msg.put( ValueFactoryTest1._mf_x, 3 ); -- cause an exception
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_incr );
+		assertEquals( 1, src.xreply.size() );
+		Object o = src.xreply.get( ValueFactoryTest1._mf_result );
+		assertTrue( o instanceof RuntimeException ); // because incr is not
+		// declared to throw
+		// anything
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_sub() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sub, vf );
+		msg.put( ValueFactoryTest1._mf_x, 7 );
+		msg.put( ValueFactoryTest1._mf_y, 3 );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sub );
+		assertEquals( 1, src.xreply.size() );
+		assertEquals( 4, src.xreply.get( ValueFactoryTest1._mf_result ) );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_sum() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sum, vf );
+		msg.put( ValueFactoryTest1._mf_x, new int[]
+		{
+			1, 2, 3, 7, 11
+		} );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sum );
+		assertEquals( 1, src.xreply.size() );
+		assertEquals( 24, src.xreply.get( ValueFactoryTest1._mf_result ) );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_trans1() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_trans,
+			vf );
+		msg.put( ValueFactoryTest1._mf_e, Test1.E1.A );
+		msg.put( ValueFactoryTest1._mf_x, 5 );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans );
+		assertEquals( 1, src.xreply.size() );
+		assertEquals( 2, src.xreply.get( ValueFactoryTest1._mf_result ) );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_trans2() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_trans,
+			vf );
+		msg.put( ValueFactoryTest1._mf_e, Test1.E1.B );
+		msg.put( ValueFactoryTest1._mf_x, 5 );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans );
+		assertEquals( 1, src.xreply.size() );
+		assertEquals( 10, src.xreply.get( ValueFactoryTest1._mf_result ) );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_trans3() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_trans,
+			vf );
+		msg.put( ValueFactoryTest1._mf_e, Test1.E1.C );
+		msg.put( ValueFactoryTest1._mf_x, 5 );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans );
+		assertEquals( 1, src.xreply.size() );
+		assertEquals( 12, src.xreply.get( ValueFactoryTest1._mf_result ) );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_dist1() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_dist, vf );
+		msg.put( ValueFactoryTest1._mf_a, new Test1.S1( 1, 1, 1 ) );
+		msg.put( ValueFactoryTest1._mf_b, new Test1.S1( 0, 0, 0 ) );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_dist );
+		assertEquals( 1, src.xreply.size() );
+		assertEquals( Math.sqrt( 3 ), src.xreply
+			.get( ValueFactoryTest1._mf_result ) );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_dist2() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_dist, vf );
+		msg.put( ValueFactoryTest1._mf_a, new Test1.S1( 1, 2, 3 ) );
+		msg.put( ValueFactoryTest1._mf_b, new Test1.S1( 6, 5, 4 ) );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_dist );
+		assertEquals( 1, src.xreply.size() );
+		assertEquals( Math.sqrt( 35 ), src.xreply
+			.get( ValueFactoryTest1._mf_result ) );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_fill() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_fill, vf );
+		msg.put( ValueFactoryTest1._mf_n, 4 );
+		msg.put( ValueFactoryTest1._mf_x, 3 );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fill );
+		assertEquals( 1, src.xreply.size() );
+		int[] x = (int[]) src.xreply.get( ValueFactoryTest1._mf_result );
+		assertNotNull( x );
+		assertEquals( 4, x.length );
+		for (int y : x)
+			assertEquals( 3, y );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_blow() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_blow, vf );
+		msg.put( ValueFactoryTest1._mf_msg, "foo" );
+		msg.put( ValueFactoryTest1._mf_code, 23 );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_blow );
+		assertEquals( 1, src.xreply.size() );
+		Test1.Excp1 e = (Test1.Excp1) src.xreply
+			.get( ValueFactoryTest1._mf_result );
+		assertNotNull( e );
+		assertEquals( "foo", e.msg );
+		assertEquals( 23, e.code );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_beets1() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets,
+			vf );
+		msg.put( ValueFactoryTest1._mf_e, Test1.E1.A );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets );
+		assertEquals( 1, src.xreply.size() );
+		Object o = src.xreply.get( ValueFactoryTest1._mf_result );
+		assertEquals( 5, o );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_beets2() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets,
+			vf );
+		msg.put( ValueFactoryTest1._mf_e, Test1.E1.B );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets );
+		assertEquals( 1, src.xreply.size() );
+		Object o = src.xreply.get( ValueFactoryTest1._mf_result );
+		assertEquals( Test1.Excp3.class, o.getClass() );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_beets3() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets,
+			vf );
+		msg.put( ValueFactoryTest1._mf_e, Test1.E1.C );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets );
+		assertEquals( 1, src.xreply.size() );
+		Object o = src.xreply.get( ValueFactoryTest1._mf_result );
+		assertEquals( Test1.Excp4.class, o.getClass() );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_beets4() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets,
+			vf );
+		msg.put( ValueFactoryTest1._mf_e, null );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets );
+		assertEquals( 0, src.xreply.size() );
+		Object o = src.xreply.get( ValueFactoryTest1._mf_result );
+		assertNull( o );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_isTrue() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_isTrue,
+			vf );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_isTrue );
+		assertEquals( 1, src.xreply.size() );
+		Object o = src.xreply.get( ValueFactoryTest1._mf_result );
+		assertEquals( true, o );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_isFalse() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_isFalse,
+			vf );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_isFalse );
+		assertEquals( 1, src.xreply.size() );
+		Object o = src.xreply.get( ValueFactoryTest1._mf_result );
+		assertEquals( false, o );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_alwaysWorks() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_alwaysWorks,
+			vf );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_alwaysWorks );
+		assertEquals( 1, src.xreply.size() );
+		Object o = src.xreply.get( ValueFactoryTest1._mf_result );
+		assertEquals( 23, o );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_alwaysFails() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_alwaysFails,
+			vf );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_alwaysFails );
+		assertEquals( 1, src.xreply.size() );
+		Object o = src.xreply.get( ValueFactoryTest1._mf_result );
+		assertTrue( o instanceof _Etch_AuthException );
+		_Etch_AuthException e = (_Etch_AuthException) o;
+		assertEquals( "stub could not authorize alwaysFails using isFalse",
+			e.msg );
+	}
+	 
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_fillObjectInt() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_fillObject,
+			vf );
+		msg.put( ValueFactoryTest1._mf_n, 3 );
+		msg.put( ValueFactoryTest1._mf_o, 9 );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fillObject );
+		assertEquals( 1, src.xreply.size() );
+		Object[] o = (Object[]) src.xreply.get( ValueFactoryTest1._mf_result );
+		assertNotNull( o );
+		assertEquals( 3, o.length );
+		for (Object n : o)
+			assertEquals( 9, n );
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_fillObjectStr() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_fillObject,
+			vf );
+		msg.put( ValueFactoryTest1._mf_n, 3 );
+		msg.put( ValueFactoryTest1._mf_o, "raw" );
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fillObject );
+		assertEquals( 1, src.xreply.size() );
+		Object[] o = (Object[]) src.xreply.get( ValueFactoryTest1._mf_result );
+		assertNotNull( o );
+		assertEquals( 3, o.length );
+		for (Object n : o)
+			assertEquals( "raw", n );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_throwExcp5() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_throwExcp5,
+			vf );
+		msg.put(ValueFactoryTest1._mf_msg,"raw");
+		msg.put(ValueFactoryTest1._mf_code,9);
+		msg.put(ValueFactoryTest1._mf_value,"Exception with object as param");
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_throwExcp5 );
+		assertEquals( 1, src.xreply.size() );
+		Object o = src.xreply.get( ValueFactoryTest1._mf_result );
+		assertTrue( o instanceof Test1.Excp5 );
+		Test1.Excp5 e = (Test1.Excp5) o;
+		assertEquals( e.msg, "raw" );
+		assertEquals( e.code, 9 );
+		assertEquals( e.x, "Exception with object as param" );
+		
+	}
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_throwExcp6() throws Exception
+	{
+		Message msg = new Message(
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_throwExcp6,
+			vf );
+		msg.put(ValueFactoryTest1._mf_msg,"raw");
+		msg.put(ValueFactoryTest1._mf_code,99);
+		msg.put( ValueFactoryTest1._mf_value, method_fillObjectHelper(5,"Exception with array of object as param"));
+		stub.sessionMessage( null, msg );
+		// check the result.
+		src.xreply
+			.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_throwExcp6 );
+		assertEquals( 1, src.xreply.size() );
+		Object o = src.xreply.get( ValueFactoryTest1._mf_result );
+		assertTrue( o instanceof Test1.Excp6 );
+		Test1.Excp6 e = (Test1.Excp6) o;
+		assertEquals( e.msg, "raw" );
+		assertEquals( e.code, 99 );
+		Object[] objArr = e.x ;
+		assertNotNull( objArr );
+		assertEquals( 5, objArr.length );
+		for (Object n : objArr)
+			assertEquals( "Exception with array of object as param", n );
+		
+	}
+	
+	// Helper method to fill an object array of size sz with Object Value
+	
+	private Object[] method_fillObjectHelper (int sz, Object value)
+	{
+		Object[] myObject = test.fillObject( sz, value );
+		
+		for ( int i = 0; i < sz; i++ ) 
+		{
+			myObject[i] = value;
+		}	
+		return myObject;
+	}
+
+	private final FakeTest1 test = new FakeTest1();
+
+	private final ValueFactoryTest1 vf = new ValueFactoryTest1( "tcp:" );
+
+	private final Pool pool = new Pool()
+	{
+		public void run( PoolRunnable runnable )
+		{
+			try
+			{
+				runnable.run();
+			}
+			catch ( Exception e )
+			{
+				throw new RuntimeException( e );
+			}
+		}
+	};
+
+	private final MyMessageSource src = new MyMessageSource();
+	private final StubTest1<Test1> stub = new StubTest1<Test1>( src, test, pool, pool );
+	
+	/** a fake MessageSource for testing */
+	public static class MyMessageSource implements DeliveryService
+	{
+		/** */
+		public Message xreply;
+
+		public void transportMessage( Who recipient, Message msg ) throws Exception
+		{
+			assertNull( recipient );
+			assertNull( xreply );
+			xreply = msg;
+		}
+
+		public Mailbox begincall( Message msg ) throws Exception
+		{
+			// ignore
+			return null;
+		}
+
+		public Object endcall( Mailbox mb, Type responseType ) throws Exception
+		{
+			// ignore
+			return null;
+		}
+
+		public boolean sessionMessage( Who sender, Message msg )
+			throws Exception
+		{
+			// ignore
+			return false;
+		}
+
+		public void sessionControl( Object control, Object value )
+			throws Exception
+		{
+			// ignore
+			
+		}
+
+		public void sessionNotify( Object event ) throws Exception
+		{
+			// ignore
+			
+		}
+
+		public Object sessionQuery( Object query ) throws Exception
+		{
+			// ignore
+			return null;
+		}
+
+		public SessionMessage getSession()
+		{
+			// ignore
+			return null;
+		}
+
+		public void setSession( SessionMessage session )
+		{
+			// ignore
+			
+		}
+
+		public void transportControl( Object control, Object value )
+			throws Exception
+		{
+			// ignore
+			
+		}
+
+		public void transportNotify( Object event ) throws Exception
+		{
+			// ignore
+			
+		}
+
+		public Object transportQuery( Object query ) throws Exception
+		{
+			// ignore
+			return null;
+		}
+	}
+}
diff --git a/tests/src/test/java/org/apache/etch/tests/TestTest1DotJava.java b/tests/src/test/java/org/apache/etch/tests/TestTest1DotJava.java
new file mode 100644
index 0000000..fd31422
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/TestTest1DotJava.java
@@ -0,0 +1,751 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/** Test of Test1 */
+public class TestTest1DotJava
+{
+	/** @throws Exception */
+	@org.junit.Test
+	public void const_booleans() throws Exception
+	{
+		assertFalse( Test1.BOOL1 );
+		assertTrue( Test1.BOOL2 );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void const_bytes() throws Exception
+	{
+		assertEquals( Byte.MIN_VALUE, Test1.BYTE1 );
+		assertEquals( (byte) -1, Test1.BYTE2 );
+		assertEquals( (byte) 0, Test1.BYTE3 );
+		assertEquals( (byte) 1, Test1.BYTE4 );
+		assertEquals( Byte.MAX_VALUE, Test1.BYTE5 );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void const_shorts() throws Exception
+	{
+		assertEquals( Short.MIN_VALUE, Test1.SHORT1 );
+		assertEquals( (short) -1, Test1.SHORT2 );
+		assertEquals( (short) 0, Test1.SHORT3 );
+		assertEquals( (short) 1, Test1.SHORT4 );
+		assertEquals( Short.MAX_VALUE, Test1.SHORT5 );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void const_ints() throws Exception
+	{
+		assertEquals( Integer.MIN_VALUE, Test1.INT1 );
+		assertEquals( -1, Test1.INT2 );
+		assertEquals( 0, Test1.INT3 );
+		assertEquals( 1, Test1.INT4 );
+		assertEquals( Integer.MAX_VALUE, Test1.INT5 );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void const_longs() throws Exception
+	{
+		assertEquals( Long.MIN_VALUE, Test1.LONG1 );
+		assertEquals( (long) -1, Test1.LONG2 );
+		assertEquals( (long) 0, Test1.LONG3 );
+		assertEquals( (long) 1, Test1.LONG4 );
+		assertEquals( Long.MAX_VALUE, Test1.LONG5 );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void const_floats() throws Exception
+	{
+		assertEquals( Float.MIN_VALUE, Test1.FLOAT1 );
+		assertEquals( (float) -1, Test1.FLOAT2 );
+		assertEquals( (float) 0, Test1.FLOAT3 );
+		assertEquals( (float) 1, Test1.FLOAT4 );
+		assertEquals( Float.MAX_VALUE, Test1.FLOAT5 );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void const_doubles() throws Exception
+	{
+		assertEquals( Double.MIN_VALUE, Test1.DOUBLE1 );
+		assertEquals( (double) -1, Test1.DOUBLE2 );
+		assertEquals( (double) 0, Test1.DOUBLE3 );
+		assertEquals( (double) 1, Test1.DOUBLE4 );
+		assertEquals( Double.MAX_VALUE, Test1.DOUBLE5 );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void const_strings() throws Exception
+	{
+		assertEquals( "", Test1.STRING1 );
+		assertEquals( "a", Test1.STRING2 );
+		assertEquals( "abc", Test1.STRING3 );
+		assertEquals( "a\tb\tc\r\n", Test1.STRING4 );
+		assertEquals( "x x", Test1.STRING5 );
+		assertEquals( "x\u00bfx", Test1.STRING6 );
+		assertEquals( "x\u03a9x", Test1.STRING7 );
+		assertEquals( "x\\x", Test1.STRING8 );
+		assertEquals( "x'x", Test1.STRING9 );
+		assertEquals( "x\"x", Test1.STRING10 );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void enum_E1() throws Exception
+	{
+		assertEquals( 3, Test1.E1.values().length );
+		assertNotNull( Test1.E1.A );
+		assertNotNull( Test1.E1.B );
+		assertNotNull( Test1.E1.C );
+		assertSame( Test1.E1.A, Test1.E1.valueOf( "A" ) );
+		assertSame( Test1.E1.B, Test1.E1.valueOf( "B" ) );
+		assertSame( Test1.E1.C, Test1.E1.valueOf( "C" ) );
+		assertEquals( 0, Test1.E1.A.ordinal() );
+		assertEquals( 1, Test1.E1.B.ordinal() );
+		assertEquals( 2, Test1.E1.C.ordinal() );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void struct_S1() throws Exception
+	{
+		Test1.S1 s = new Test1.S1( 1, 2, 3 );
+		assertEquals( 1, s.x );
+		assertEquals( 2, s.y );
+		assertEquals( 3, s.z );
+		
+		s = new Test1.S1( null, null, null );
+		assertNull( s.x );
+		assertNull( s.y );
+		assertNull( s.z );
+		
+		s = new Test1.S1();
+		assertNull( s.x );
+		assertNull( s.y );
+		assertNull( s.z );
+		
+		s.x = 4;
+		s.y = 5;
+		s.z = 6;
+		
+		assertEquals( 4, s.x );
+		assertEquals( 5, s.y );
+		assertEquals( 6, s.z );
+		
+		s.x = null;
+		assertNull( s.x );
+		
+		s.x = 7;
+		assertEquals( 7, s.x );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void except_Excp1() throws Exception
+	{
+		Test1.Excp1 e = new Test1.Excp1( "foo", 23 );
+		assertEquals( "foo", e.msg );
+		assertEquals( 23, e.code );
+		
+		e = new Test1.Excp1( null, null );
+		assertNull( e.msg );
+		assertNull( e.code );
+		
+		e = new Test1.Excp1();
+		assertNull( e.msg );
+		assertNull( e.code );
+		
+		e.msg = "bar";
+		e.code = 24;
+		
+		assertEquals( "bar", e.msg );
+		assertEquals( 24, e.code );
+		
+		e.msg = null;
+		e.code = null;
+		
+		assertNull( e.msg );
+		assertNull( e.code );
+
+		Throwable t = e;
+		assertTrue( t instanceof Exception );
+		assertFalse( t instanceof RuntimeException );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void except_Excp2() throws Exception
+	{
+		Test1.Excp2 e = new Test1.Excp2();
+
+		Throwable t = e;
+		assertTrue( t instanceof Exception );
+		assertTrue( t instanceof RuntimeException );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void except_Excp3() throws Exception
+	{
+		Test1.Excp3 e = new Test1.Excp3();
+
+		Throwable t = e;
+		assertTrue( t instanceof Exception );
+		assertTrue( t instanceof RuntimeException );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void except_Excp4() throws Exception
+	{
+		Test1.Excp4 e = new Test1.Excp4();
+
+		Throwable t = e;
+		assertTrue( t instanceof Exception );
+		assertFalse( t instanceof RuntimeException );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_nothing() throws Exception
+	{
+		test.nothing();
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_incr1() throws Exception
+	{
+		assertEquals( 2, test.incr( 1 ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_incr2() throws Exception
+	{
+		assertEquals( 3, test.incr( 2 ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_incr3() throws Exception
+	{
+		assertEquals( -1, test.incr( -2 ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_sub1() throws Exception
+	{
+		assertEquals( 5, test.sub( 7, 2 ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_sub2() throws Exception
+	{
+		assertEquals( 8, test.sub( 23, 15 ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_sub3() throws Exception
+	{
+		assertEquals( -5, test.sub( 2, 7 ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_sum() throws Exception
+	{
+		assertEquals( 24, test.sum( new int[] { 1, 2, 3, 7, 11 } ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_trans1() throws Exception
+	{
+		assertEquals( 2, test.trans( Test1.E1.A, 5 ) ); // divide by 2
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_trans2() throws Exception
+	{
+		assertEquals( 10, test.trans( Test1.E1.B, 5 ) ); // mul by 2
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_trans3() throws Exception
+	{
+		assertEquals( 12, test.trans( Test1.E1.C, 5 ) ); // add 7
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_dist1() throws Exception
+	{
+		assertEquals( Math.sqrt( 3 ), test.dist( new Test1.S1( 1, 1, 1 ), new Test1.S1( 0, 0, 0 ) ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_dist2() throws Exception
+	{
+		assertEquals( Math.sqrt( 35 ), test.dist( new Test1.S1( 1, 2, 3 ), new Test1.S1( 6, 5, 4 ) ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_dist3() throws Exception
+	{
+		assertEquals( Math.sqrt( 56 ), test.dist( new Test1.S1( 1, 2, 3 ), new Test1.S1( -1, -2, -3 ) ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_fill1() throws Exception
+	{
+		int[] x = test.fill( 0, 1 );
+		assertEquals( 0, x.length );
+		for (int i: x)
+			assertEquals( 1, i );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_fill2() throws Exception
+	{
+		int[] x = test.fill( 1, 2 );
+		assertEquals( 1, x.length );
+		for (int i: x)
+			assertEquals( 2, i );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_fill3() throws Exception
+	{
+		int[] x = test.fill( 2, 3 );
+		assertEquals( 2, x.length );
+		for (int i: x)
+			assertEquals( 3, i );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_fillObject() throws Exception
+	{
+		int sz = 10;
+		
+		// All const types
+		method_fillObjectHelper( sz, Test1.BOOL1 );	
+		method_fillObjectHelper( sz, Test1.BYTE5 );
+		method_fillObjectHelper( sz, Test1.SHORT5 );	
+		method_fillObjectHelper( sz, Test1.INT5 );
+		method_fillObjectHelper( sz, Test1.LONG5 );	
+		method_fillObjectHelper( sz, Test1.FLOAT5 );
+		method_fillObjectHelper( sz, Test1.DOUBLE5 );	
+		method_fillObjectHelper( sz, Test1.STRING3 );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_blow1() throws Exception
+	{
+		try
+		{
+			test.blow( "foo", 2 );
+			fail( "blow did not throw" );
+		}
+		catch( Test1.Excp1 e )
+		{
+			assertEquals( "foo", e.msg );
+			assertEquals( 2, e.code );
+		}
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_blow2() throws Exception
+	{
+		try
+		{
+			test.blow( "bar", 3 );
+			fail( "blow did not throw" );
+		}
+		catch( Test1.Excp1 e )
+		{
+			assertEquals( "bar", e.msg );
+			assertEquals( 3, e.code );
+		}
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_beets1() throws Exception
+	{
+		assertEquals( 5, test.beets( Test1.E1.A ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_beets2() throws Exception
+	{
+		try
+		{
+			test.beets( Test1.E1.B );
+			fail( "beets did not throw" );
+		}
+		catch ( Test1.Excp3 e )
+		{
+			assertTrue( true );
+		}
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_beets3() throws Exception
+	{
+		try
+		{
+			test.beets( Test1.E1.C );
+			fail( "beets did not throw" );
+		}
+		catch ( Test1.Excp4 e )
+		{
+			assertTrue( true );
+		}
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_beets4() throws Exception
+	{
+		assertNull( test.beets( null ) );
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void struct_S3() throws Exception
+	{
+		testS3Helper( "boolean", Test1.BOOL2 );
+		testS3Helper( "byte", Test1.BYTE5 );
+		testS3Helper( "short", Test1.SHORT5 );
+		testS3Helper( "int", Test1.INT5 );
+		testS3Helper( "long", Test1.LONG5 );
+		testS3Helper( "float", Test1.FLOAT5 );
+		testS3Helper( "double", Test1.DOUBLE5 );
+		testS3Helper( "string", Test1.STRING3 );		
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void struct_S4() throws Exception
+	{		
+		int sz = 10;
+		
+		testS4Helper(sz, "boolean", Test1.BOOL2 );
+		testS4Helper(sz, "byte", Test1.BYTE5 );
+		testS4Helper(sz, "short", Test1.SHORT5 );
+		testS4Helper(sz, "int", Test1.INT5 );
+		testS4Helper(sz, "long", Test1.LONG5 );
+		testS4Helper(sz, "float", Test1.FLOAT5 );
+		testS4Helper(sz, "double", Test1.DOUBLE5 );
+		testS4Helper(sz, "string", Test1.STRING3 );		
+
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void except_Excp5() throws Exception
+	{
+		int code = 500;
+		String msg = "Excp5";
+		
+		testExcp5Helper (msg, code, Test1.BOOL1);
+		testExcp5Helper (msg, code, Test1.BYTE5);
+		testExcp5Helper (msg, code, Test1.SHORT5);
+		testExcp5Helper (msg, code, Test1.INT5);
+		testExcp5Helper (msg, code, Test1.LONG5);
+		testExcp5Helper (msg, code, Test1.FLOAT5);
+		testExcp5Helper (msg, code, Test1.DOUBLE5);
+		testExcp5Helper (msg, code, Test1.STRING3);		
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void except_Excp6() throws Exception
+	{
+		int sz = 10;
+		int code = 500;
+		String msg = "Excp6";
+		
+		testExcp6Helper( sz, msg, code, Test1.BOOL1 );
+		testExcp6Helper( sz, msg, code, Test1.BYTE5 );
+		testExcp6Helper( sz, msg, code, Test1.SHORT5 );
+		testExcp6Helper( sz, msg, code, Test1.INT5 );
+		testExcp6Helper( sz, msg, code, Test1.LONG5 );
+		testExcp6Helper( sz, msg, code, Test1.FLOAT5 );
+		testExcp6Helper( sz, msg, code, Test1.DOUBLE5 );
+		testExcp6Helper( sz, msg, code, Test1.STRING3 );		
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_throwExcp5() throws Exception
+	{
+		String msg = "throwExcp5";
+		int code = 500;
+
+		method_throwExcp5Helper( msg, code, Test1.BOOL1 );
+		method_throwExcp5Helper( msg, code, Test1.BYTE5 );
+		method_throwExcp5Helper( msg, code, Test1.SHORT5 );
+		method_throwExcp5Helper( msg, code, Test1.INT5 );
+		method_throwExcp5Helper( msg, code, Test1.LONG5 );
+		method_throwExcp5Helper( msg, code, Test1.FLOAT5 );
+		method_throwExcp5Helper( msg, code, Test1.DOUBLE5 );
+		method_throwExcp5Helper( msg, code, Test1.STRING3 );		
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void method_throwExcp6() throws Exception
+	{
+		String msg = "throwExcp6";
+		int code = 500;
+		int sz = 10;
+
+		method_throwExcp6Helper( sz, msg, code, Test1.BOOL1 );
+		method_throwExcp6Helper( sz, msg, code, Test1.BYTE5 );
+		method_throwExcp6Helper( sz, msg, code, Test1.SHORT5 );
+		method_throwExcp6Helper( sz, msg, code, Test1.INT5 );
+		method_throwExcp6Helper( sz, msg, code, Test1.LONG5 );
+		method_throwExcp6Helper( sz, msg, code, Test1.FLOAT5 );
+		method_throwExcp6Helper( sz, msg, code, Test1.DOUBLE5 );
+		method_throwExcp6Helper( sz, msg, code, Test1.STRING3 );		
+
+	}
+	
+	//
+	// Utility methods
+	//
+	
+	private void testS3Helper( String type, Object value )
+	{
+		Test1.S3 s = new Test1.S3( type, value );
+		assertEquals( type, s.tipe );
+		assertEquals( value, s.x );
+		
+		s = new Test1.S3( null, null );
+		assertNull( s.tipe );
+		assertNull( s.x );
+		
+		s = new Test1.S3();
+		assertNull( s.tipe );
+		assertNull( s.x );
+		
+		s.tipe = type;
+		s.x = value;	
+		assertEquals( type, s.tipe );
+		assertEquals( value, s.x );
+		
+		s.x = null;
+		assertNull( s.x );
+		
+		s.x = value;
+		assertEquals( value, s.x );
+	}
+
+	/*
+	 * jacapps 10-OCT-2007
+	 * 
+	 * testS4Helper - Fill an S4 struct with a values for the type 
+	 * and Object array and verify the values.
+	 * 
+	 * @param sz - The number of elements in the Object array
+	 * @param type - The type of the data to be put in Object array
+	 * @param value - The value of type to fill the array with
+	 * 
+	 */
+	private void testS4Helper( int sz, String type, Object value )
+	{
+		Object[] myObject = test.fillObject( sz, value );
+		
+		Test1.S4 s = new Test1.S4( type, myObject );
+		assertEquals( type, s.tipe );
+		assertEquals( sz, myObject.length );
+		
+		for (Object element : myObject)
+		{
+			assertEquals( value, element );
+		}
+	}
+
+	private void testExcp5Helper (String msg, int code, Object value)
+	{
+		Test1.Excp5 e = new Test1.Excp5( msg, code, value );
+		assertEquals( msg, e.msg );
+		assertEquals( code, e.code );
+		assertEquals( value, e.x);
+		
+		e = new Test1.Excp5( null, null, null );
+		assertNull( e.msg );
+		assertNull( e.code );
+		assertNull( e.x);
+
+		e = new Test1.Excp5();
+		assertNull( e.msg );
+		assertNull( e.code );
+		assertNull( e.x );
+		
+		e.msg = msg;
+		e.code = code;
+		e.x = value;
+		
+		assertEquals( msg, e.msg );
+		assertEquals( code, e.code );
+		assertEquals( value, e.x );
+		
+		e.msg = null;
+		e.code = null;
+		e.x = null;
+		
+		assertNull( e.msg );
+		assertNull( e.code );
+		assertNull( e.x );		
+
+		Throwable t = e;
+		assertTrue( t instanceof Exception );
+		assertFalse( t instanceof RuntimeException );
+	}
+	
+	private void testExcp6Helper (int sz, String msg, int code, Object value )
+	{
+		Object[] myObject = test.fillObject( sz, value );
+		
+		Test1.Excp6 e = new Test1.Excp6( msg, code, myObject );
+		assertEquals( msg, e.msg );
+		assertEquals( code, e.code );
+
+		for (Object element : myObject)
+		{
+			assertEquals( value, element );
+		}
+		
+		e = new Test1.Excp6( null, null, null );
+		assertNull( e.msg );
+		assertNull( e.code );
+		assertNull( e.x );
+
+		e = new Test1.Excp6();
+		assertNull( e.msg );
+		assertNull( e.code );
+		assertNull( e.x );
+		
+		e.msg = msg;
+		e.code = code;
+		e.x = myObject;
+		
+		assertEquals( msg, e.msg );
+		assertEquals( code, e.code );
+		
+		for (Object element : myObject)
+		{
+			assertEquals( value, element );
+		}
+		
+		e.msg = null;
+		e.code = null;
+		e.x = null;
+		
+		assertNull( e.msg );
+		assertNull( e.code );
+		assertNull( e.x );		
+
+		Throwable t = e;
+		assertTrue( t instanceof Exception );
+		assertFalse( t instanceof RuntimeException );
+	}
+	
+	private void method_throwExcp5Helper (String msg, int code, Object value)
+	{
+		try
+		{
+			test.throwExcp5( msg, code, value );
+			fail( "throwExcp5 did not throw" );
+		}
+		catch( Test1.Excp5 e )
+		{
+			assertEquals( msg, e.msg );
+			assertEquals( code, e.code );
+			assertEquals( value, e.x );
+		}
+	}
+	
+	private void method_throwExcp6Helper (int sz, String msg, int code, Object value)
+	{
+		Object[] myObject = test.fillObject( sz, value );
+		
+		try
+		{
+			test.throwExcp6( msg, code, myObject );
+			fail( "throwExcp5 did not throw" );
+		}
+		catch( Test1.Excp6 e )
+		{
+			assertEquals( msg, e.msg );
+			assertEquals( code, e.code );
+			
+			for ( int i = 0; i < myObject.length; i++ ) 
+			{
+				assertEquals( value, e.x[i] );
+			}
+		}
+	}
+	
+	private void method_fillObjectHelper (int sz, Object value)
+	{
+		Object[] myObject = test.fillObject( sz, value );
+		
+		for (Object element : myObject)
+		{
+			assertEquals( value, element );
+		}	
+	}
+
+	private final Test1 test = new FakeTest1();
+}
diff --git a/tests/src/test/java/org/apache/etch/tests/TestTest1Helper.java b/tests/src/test/java/org/apache/etch/tests/TestTest1Helper.java
new file mode 100644
index 0000000..59bb894
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/TestTest1Helper.java
@@ -0,0 +1,73 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.bindings.java.support.TransportFactory;
+import org.apache.etch.bindings.java.transport.TcpTransportFactory;
+import org.apache.etch.util.core.io.Transport;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+/** Test of Test1Helper */
+public class TestTest1Helper
+{
+	private static ServerFactory listener;
+	
+	/** @throws Exception */
+	@BeforeClass
+	public static void init() throws Exception
+	{
+		TransportFactory.define( "rohit", new TcpTransportFactory() );
+		
+		String uri = "rohit://0.0.0.0:4040";
+		
+		listener = Test1Helper.newListener( uri, null, new MainTest1Listener() );
+		
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void test() throws Exception
+	{
+		String uri = "rohit://localhost:4040";
+
+		RemoteTest1Server server = Test1Helper.newServer( uri, null, new MainTest1Client() );
+		server._startAndWaitUp( 4000 );
+
+		// TODO nothing to do but wait for server to really be up.
+		Thread.sleep( 1000 );
+	
+		server._stopAndWaitDown( 4000 );
+		server = null;
+	}
+	
+	/** @throws Exception */
+	@AfterClass
+	public static void fini() throws Exception
+	{
+		listener.transportControl( Transport.STOP_AND_WAIT_DOWN, 0 );
+		listener = null;
+	}
+}
diff --git a/tests/src/test/java/org/apache/etch/tests/TestValueFactoryTest1DotJava.java b/tests/src/test/java/org/apache/etch/tests/TestValueFactoryTest1DotJava.java
new file mode 100644
index 0000000..af78936
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/TestValueFactoryTest1DotJava.java
@@ -0,0 +1,1136 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Set;
+
+import org.apache.etch.bindings.java.msg.Field;
+import org.apache.etch.bindings.java.msg.StructValue;
+import org.apache.etch.bindings.java.msg.Type;
+import org.apache.etch.tests.Test1.E1;
+import org.apache.etch.tests.Test1.Excp1;
+import org.apache.etch.tests.Test1.Excp2;
+import org.apache.etch.tests.Test1.Excp3;
+import org.apache.etch.tests.Test1.Excp4;
+import org.apache.etch.tests.Test1.Excp5;
+import org.apache.etch.tests.Test1.Excp6;
+import org.apache.etch.tests.Test1.S1;
+import org.apache.etch.tests.Test1.S2;
+import org.apache.etch.tests.Test1.S3;
+import org.apache.etch.tests.Test1.S4;
+
+
+/** Test of ValueFactoryTest1 */
+public class TestValueFactoryTest1DotJava
+{
+	private ValueFactoryTest1 vf = new ValueFactoryTest1( "tcp:" );
+	
+	/** */
+	@org.junit.Test
+	public void test_E1()
+	{
+		// type //
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_E1,
+		
+		// fields //
+		
+		ValueFactoryTest1._mf_A,
+		ValueFactoryTest1._mf_B,
+		ValueFactoryTest1._mf_C );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_E1_export()
+	{
+		testEnumExport( E1.A,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_E1,
+			ValueFactoryTest1._mf_A );
+		
+		testEnumExport( E1.B,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_E1,
+			ValueFactoryTest1._mf_B );
+		
+		testEnumExport( E1.C,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_E1,
+			ValueFactoryTest1._mf_C );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_E1_import()
+	{
+		testEnumImport( E1.A,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_E1,
+			ValueFactoryTest1._mf_A );
+		
+		testEnumImport( E1.B,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_E1,
+			ValueFactoryTest1._mf_B );
+		
+		testEnumImport( E1.C,
+			ValueFactoryTest1._mt_org_apache_etch_tests_Test1_E1,
+			ValueFactoryTest1._mf_C );
+	}
+
+	/** */
+	@org.junit.Test
+	public void test_S1()
+	{
+		// type //
+
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S1,
+		
+		// fields //
+		
+		ValueFactoryTest1._mf_x,
+		ValueFactoryTest1._mf_y,
+		ValueFactoryTest1._mf_z );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_S1_export()
+	{
+		StructValue sv = vf.exportCustomValue( new S1( 19, 23, 29 ) );
+		sv.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S1 );
+		assertEquals( 3, sv.size() );
+		assertEquals( 19, sv.get( ValueFactoryTest1._mf_x ) );
+		assertEquals( 23, sv.get( ValueFactoryTest1._mf_y ) );
+		assertEquals( 29, sv.get( ValueFactoryTest1._mf_z ) );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_S1_import()
+	{
+		StructValue sv = new StructValue( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S1, vf );
+		sv.put( ValueFactoryTest1._mf_x, 101 );
+		sv.put( ValueFactoryTest1._mf_y, 103 );
+		sv.put( ValueFactoryTest1._mf_z, 107 );
+		S1 s = (S1) vf.importCustomValue( sv );
+		assertEquals( 101, s.x );
+		assertEquals( 103, s.y );
+		assertEquals( 107, s.z );
+	}
+
+	/** */
+	@org.junit.Test
+	public void test_S2()
+	{
+		// type //
+
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S2,
+		
+		// fields //
+		
+		ValueFactoryTest1._mf_a,
+		ValueFactoryTest1._mf_b,
+		ValueFactoryTest1._mf_c );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_S2_export()
+	{
+		S1 a = new S1( 21, 22, 23 );
+		S1 b = new S1( 31, 32, 33 );
+		E1 c = E1.A;
+		
+		StructValue sv = vf.exportCustomValue( new S2( a, b, c ) );
+		sv.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S2 );
+		assertEquals( 3, sv.size() );
+		
+		assertSame( a, sv.get( ValueFactoryTest1._mf_a ) );
+		assertSame( b, sv.get( ValueFactoryTest1._mf_b ) );
+		assertSame( c, sv.get( ValueFactoryTest1._mf_c ) );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_S2_import()
+	{
+		StructValue sv = new StructValue( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S2, vf );
+		
+		sv.put( ValueFactoryTest1._mf_a, new S1( 21, 22, 23 ) );
+		sv.put( ValueFactoryTest1._mf_b, new S1( 31, 32, 33 ) );
+		sv.put( ValueFactoryTest1._mf_c, E1.A );
+		
+		S2 s = (S2) vf.importCustomValue( sv );
+		assertEquals( 21, s.a.x );
+		assertEquals( 22, s.a.y );
+		assertEquals( 23, s.a.z );
+		assertEquals( 31, s.b.x );
+		assertEquals( 32, s.b.y );
+		assertEquals( 33, s.b.z );
+		assertEquals( E1.A, s.c );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_S3()
+	{
+		// type //
+
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S3,
+		
+		// fields //
+		
+		ValueFactoryTest1._mf_tipe,
+		ValueFactoryTest1._mf_x );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_S3_export()
+	{		
+		testS3Export("boolean", Test1.BOOL1);
+		testS3Export("byte", Test1.BYTE5);
+		testS3Export("short", Test1.SHORT5);
+		testS3Export("int", Test1.INT5);
+		testS3Export("long", Test1.LONG5);
+		testS3Export("float", Test1.FLOAT5);
+		testS3Export("double", Test1.DOUBLE5);
+		testS3Export("string", Test1.STRING3);
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_S3_import()
+	{
+		testS3Import("boolean", Test1.BOOL1);
+		testS3Import("byte", Test1.BYTE5);
+		testS3Import("short", Test1.SHORT5);
+		testS3Import("int", Test1.INT5);
+		testS3Import("long", Test1.LONG5);
+		testS3Import("float", Test1.FLOAT5);
+		testS3Import("double", Test1.DOUBLE5);
+		testS3Import("string", Test1.STRING3);
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_S4()
+	{
+		// type //
+
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S4,
+		
+		// fields //
+		ValueFactoryTest1._mf_tipe,
+		ValueFactoryTest1._mf_x );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_S4_export()
+	{	
+		Object[] boolObject = new Object[] {Test1.BOOL1, Test1.BOOL2};
+		Object[] byteObject = new Object[] {Test1.BYTE1, Test1.BYTE2, Test1.BYTE3, Test1.BYTE4, Test1.BYTE5};
+		Object[] shortObject = new Object[] {Test1.SHORT1, Test1.SHORT2, Test1.SHORT3, Test1.SHORT4, Test1.SHORT5};
+		Object[] intObject = new Object[]{Test1.INT1, Test1.INT2, Test1.INT3, Test1.INT4, Test1.INT5};
+		Object[] longObject = new Object[] {Test1.LONG1, Test1.LONG2, Test1.LONG3, Test1.LONG4, Test1.LONG5};
+		Object[] floatObject = new Object[]{Test1.FLOAT1, Test1.FLOAT2, Test1.FLOAT3, Test1.FLOAT4, Test1.FLOAT5};
+		Object[] doubleObject = new Object[] {Test1.DOUBLE1, Test1.DOUBLE2, Test1.DOUBLE3, Test1.DOUBLE4, Test1.DOUBLE5};
+		Object[] stringObject = new Object []{Test1.STRING1, Test1.STRING2, Test1.STRING3, Test1.STRING4, Test1.STRING5};
+
+		testS4Export("boolean", boolObject);
+		testS4Export("byte", byteObject);
+		testS4Export("short", shortObject);
+		testS4Export("int", intObject);
+		testS4Export("long", longObject);
+		testS4Export("float", floatObject);
+		testS4Export("double", doubleObject);
+		testS4Export("string", stringObject);
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_S4_import()
+	{
+		Object[] boolObject = new Object[] {Test1.BOOL1, Test1.BOOL2};
+		Object[] byteObject = new Object[] {Test1.BYTE1, Test1.BYTE2, Test1.BYTE3, Test1.BYTE4, Test1.BYTE5};
+		Object[] shortObject = new Object[] {Test1.SHORT1, Test1.SHORT2, Test1.SHORT3, Test1.SHORT4, Test1.SHORT5};
+		Object[] intObject = new Object[]{Test1.INT1, Test1.INT2, Test1.INT3, Test1.INT4, Test1.INT5};
+		Object[] longObject = new Object[] {Test1.LONG1, Test1.LONG2, Test1.LONG3, Test1.LONG4, Test1.LONG5};
+		Object[] floatObject = new Object[]{Test1.FLOAT1, Test1.FLOAT2, Test1.FLOAT3, Test1.FLOAT4, Test1.FLOAT5};
+		Object[] doubleObject = new Object[] {Test1.DOUBLE1, Test1.DOUBLE2, Test1.DOUBLE3, Test1.DOUBLE4, Test1.DOUBLE5};
+		Object[] stringObject = new Object []{Test1.STRING1, Test1.STRING2, Test1.STRING3, Test1.STRING4, Test1.STRING5};
+
+		testS4Import("boolean", boolObject);
+		testS4Import("byte", byteObject);
+		testS4Import("short", shortObject);
+		testS4Import("int", intObject);
+		testS4Import("long", longObject);
+		testS4Import("float", floatObject);
+		testS4Import("double", doubleObject);
+		testS4Import("string", stringObject);
+	}	
+	
+	/** */
+	@org.junit.Test
+	public void test_excps()
+	{
+		// type //
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp1,
+			ValueFactoryTest1._mf_msg,
+			ValueFactoryTest1._mf_code );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp2 );
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp3 );
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp4 );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp5,
+			ValueFactoryTest1._mf_msg,
+			ValueFactoryTest1._mf_code,
+			ValueFactoryTest1._mf_x );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp6,
+			ValueFactoryTest1._mf_msg,
+			ValueFactoryTest1._mf_code,
+			ValueFactoryTest1._mf_x );
+		
+		// fields //
+		
+//		ValueFactoryTest1._mf_msg );
+//		ValueFactoryTest1._mf_code );
+//		ValueFactoryTest1._mf_x );	
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_excps_export()
+	{
+		Object[] boolObject = new Object[] {Test1.BOOL1, Test1.BOOL2};
+		Object[] byteObject = new Object[] {Test1.BYTE1, Test1.BYTE2, Test1.BYTE3, Test1.BYTE4, Test1.BYTE5};
+		Object[] shortObject = new Object[] {Test1.SHORT1, Test1.SHORT2, Test1.SHORT3, Test1.SHORT4, Test1.SHORT5};
+		Object[] intObject = new Object[]{Test1.INT1, Test1.INT2, Test1.INT3, Test1.INT4, Test1.INT5};
+		Object[] longObject = new Object[] {Test1.LONG1, Test1.LONG2, Test1.LONG3, Test1.LONG4, Test1.LONG5};
+		Object[] floatObject = new Object[]{Test1.FLOAT1, Test1.FLOAT2, Test1.FLOAT3, Test1.FLOAT4, Test1.FLOAT5};
+		Object[] doubleObject = new Object[] {Test1.DOUBLE1, Test1.DOUBLE2, Test1.DOUBLE3, Test1.DOUBLE4, Test1.DOUBLE5};
+		Object[] stringObject = new Object []{Test1.STRING1, Test1.STRING2, Test1.STRING3, Test1.STRING4, Test1.STRING5};
+
+		String msg = "Exception";
+		int code = 500;
+		
+		StructValue sv = vf.exportCustomValue( new Excp1( "abc", 23 ) );
+		sv.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp1 );
+		assertEquals( 2, sv.size() );
+		assertEquals( "abc", sv.get( ValueFactoryTest1._mf_msg ) );
+		assertEquals( 23, sv.get( ValueFactoryTest1._mf_code ) );
+		
+		sv = vf.exportCustomValue( new Excp2() );
+		sv.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp2 );
+		assertEquals( 0, sv.size() );
+		
+		sv = vf.exportCustomValue( new Excp3() );
+		sv.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp3 );
+		assertEquals( 0, sv.size() );
+		
+		sv = vf.exportCustomValue( new Excp4() );
+		sv.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp4 );
+		assertEquals( 0, sv.size() );
+		
+		// Import exception with object as param
+		testExcp5Export(msg, code, Test1.BOOL2);
+		testExcp5Export(msg, code, Test1.BYTE5);
+		testExcp5Export(msg, code, Test1.SHORT5);
+		testExcp5Export(msg, code, Test1.INT5);
+		testExcp5Export(msg, code, Test1.LONG5);
+		testExcp5Export(msg, code, Test1.FLOAT5);
+		testExcp5Export(msg, code, Test1.DOUBLE5);
+		testExcp5Export(msg, code, Test1.STRING3);	
+		
+		// Import exception with array of object as param
+		testExcp6Export(msg, code, boolObject);
+		testExcp6Export(msg, code, byteObject);
+		testExcp6Export(msg, code, shortObject);
+		testExcp6Export(msg, code, intObject);
+		testExcp6Export(msg, code, longObject);
+		testExcp6Export(msg, code, floatObject);
+		testExcp6Export(msg, code, doubleObject);
+		testExcp6Export(msg, code, stringObject);	
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_excps_import()
+	{
+		Object[] boolObject = new Object[] {Test1.BOOL1, Test1.BOOL2};
+		Object[] byteObject = new Object[] {Test1.BYTE1, Test1.BYTE2, Test1.BYTE3, Test1.BYTE4, Test1.BYTE5};
+		Object[] shortObject = new Object[] {Test1.SHORT1, Test1.SHORT2, Test1.SHORT3, Test1.SHORT4, Test1.SHORT5};
+		Object[] intObject = new Object[]{Test1.INT1, Test1.INT2, Test1.INT3, Test1.INT4, Test1.INT5};
+		Object[] longObject = new Object[] {Test1.LONG1, Test1.LONG2, Test1.LONG3, Test1.LONG4, Test1.LONG5};
+		Object[] floatObject = new Object[]{Test1.FLOAT1, Test1.FLOAT2, Test1.FLOAT3, Test1.FLOAT4, Test1.FLOAT5};
+		Object[] doubleObject = new Object[] {Test1.DOUBLE1, Test1.DOUBLE2, Test1.DOUBLE3, Test1.DOUBLE4, Test1.DOUBLE5};
+		Object[] stringObject = new Object []{Test1.STRING1, Test1.STRING2, Test1.STRING3, Test1.STRING4, Test1.STRING5};
+
+		String msg = "Exception";
+		int code = 500;
+		
+		StructValue sv = new StructValue( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp1, vf );
+		sv.put( ValueFactoryTest1._mf_msg, "def" );
+		sv.put( ValueFactoryTest1._mf_code, 29 );
+		Excp1 e1 = (Excp1) vf.importCustomValue( sv );
+		assertEquals( "def", e1.msg );
+		assertEquals( 29, e1.code );
+		e1 = null;
+		
+		sv = new StructValue( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp2, vf );
+		Excp2 e2 = (Excp2) vf.importCustomValue( sv );
+		assertNotNull( e2 );
+		e2 = null;
+		
+		sv = new StructValue( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp3, vf );
+		Excp3 e3 = (Excp3) vf.importCustomValue( sv );
+		assertNotNull( e3 );
+		e3 = null;
+		
+		sv = new StructValue( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp4, vf );
+		Excp4 e4 = (Excp4) vf.importCustomValue( sv );
+		assertNotNull( e4 );
+		e4 = null;
+		
+		// Import exception with object as param
+		testExcp5Import(msg, code, Test1.BOOL2);
+		testExcp5Import(msg, code, Test1.BYTE5);
+		testExcp5Import(msg, code, Test1.SHORT5);
+		testExcp5Import(msg, code, Test1.INT5);
+		testExcp5Import(msg, code, Test1.LONG5);
+		testExcp5Import(msg, code, Test1.FLOAT5);
+		testExcp5Import(msg, code, Test1.DOUBLE5);
+		testExcp5Import(msg, code, Test1.STRING3);	
+		
+		// Import exception with array of object as param
+		testExcp6Import(msg, code, boolObject);
+		testExcp6Import(msg, code, byteObject);
+		testExcp6Import(msg, code, shortObject);
+		testExcp6Import(msg, code, intObject);
+		testExcp6Import(msg, code, longObject);
+		testExcp6Import(msg, code, floatObject);
+		testExcp6Import(msg, code, doubleObject);
+		testExcp6Import(msg, code, stringObject);	
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_nothing()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_nothing,
+			ValueFactoryTest1._mf__messageId );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_nothing,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+			ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_incr()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_incr,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_x );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_incr,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_sub()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sub,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_x,
+		ValueFactoryTest1._mf_y );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sub,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_sum()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_sum,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_x );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_sum,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_trans()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_trans,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_e,
+		ValueFactoryTest1._mf_x );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_trans,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_dist()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_dist,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a,
+		ValueFactoryTest1._mf_b );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_dist,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_fill()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_fill,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_n,
+		ValueFactoryTest1._mf_x );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fill,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_fillObject()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_fillObject,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_n,
+		ValueFactoryTest1._mf_o );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_fillObject,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_blow()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_blow,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_msg,
+		ValueFactoryTest1._mf_code );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_blow,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_beets()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_beets,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_e );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_beets,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_throwExcp5()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_throwExcp5,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_msg,
+		ValueFactoryTest1._mf_code,
+		ValueFactoryTest1._mf_value );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_throwExcp5,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_throwExcp6()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_throwExcp5,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_msg,
+		ValueFactoryTest1._mf_code,
+		ValueFactoryTest1._mf_value );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_throwExcp6,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+
+	/** */
+	@org.junit.Test
+	public void test_method_p_boolean()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_boolean,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_boolean_array()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_boolean_array,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_boolean_array,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_byte()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_byte,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_byte_array()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_byte_array,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_byte_array,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_short()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_short,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_short_array()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_short_array,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_short_array,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_int()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_int,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_int_array()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_int_array,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_int_array,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_long()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_long,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_long_array()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_long_array,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_long_array,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_float()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_float,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_float_array()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_float_array,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_float_array,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_double()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_double,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_double_array()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_double_array,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_double_array,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_string()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_string,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_string_array()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_string_array,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_string_array,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_E1()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_E1,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_E1_array()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_E1_array,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_E1_array,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_S1()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S1,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_S1_array()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S1_array,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S1_array,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_S2()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S2,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_S2_array()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_S2_array,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_S2_array,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_Blob()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_Blob,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_Blob,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_Blob_array()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_Blob_array,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_Blob_array,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_object()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_object,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_object_array()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_object_array,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object_array,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/** */
+	@org.junit.Test
+	public void test_method_p_object_struct()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_object_struct,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object_struct,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+
+	/** */
+	@org.junit.Test
+	public void test_method_p_object_struct_array()
+	{
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_p_object_struct_array,
+			ValueFactoryTest1._mf__messageId,
+		ValueFactoryTest1._mf_a );
+		
+		checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1__result_p_object_struct_array,
+			ValueFactoryTest1._mf__messageId,
+			ValueFactoryTest1._mf__inReplyTo,
+		ValueFactoryTest1._mf_result );
+	}
+	
+	/////////////////////
+	// UTILITY METHODS //
+	/////////////////////
+	
+	private void checkType( Type type, Field... fields )
+	{
+		assertNotNull( type );
+		assertSame( Type.class, type.getClass() );
+		assertSame( type, vf.getType( type.getId() ) );
+		
+		Set<Field> tfields = type.getFields();
+
+		if (fields != null)
+		{
+			assertEquals( fields.length, tfields.size() );
+			
+			for (Field f: fields)
+			{
+				assertNotNull( type.getValidator( f ) );
+				assertSame( f, type.getField( f.getId() ) );
+				assertSame( f, type.getField( f.getName() ) );
+			}
+		}
+		else
+		{
+			assertEquals( 0, tfields.size() );
+		}
+	}
+
+	private void testEnumExport( E1 e, Type t, Field f )
+	{
+		StructValue sv = vf.exportCustomValue( e );
+		sv.checkType( t );
+		assertEquals( 1, sv.size() );
+		assertTrue( (Boolean) sv.get( f ) );
+	}
+	
+	private void testEnumImport( E1 e, Type t, Field f )
+	{
+		StructValue sv = new StructValue( t, vf );
+		sv.put(  f, true );
+		E1 a = (E1) vf.importCustomValue( sv );
+		assertSame( e, a );
+	}
+	
+	private void testS3Export(String s, Object value)
+	{
+		StructValue sv = vf.exportCustomValue( new S3( s,value ) );
+		sv.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S3 );
+		assertEquals( 2, sv.size() );
+		assertEquals( s, sv.get( ValueFactoryTest1._mf_tipe ) );
+		assertEquals( value, sv.get( ValueFactoryTest1._mf_x ) );
+	}
+	
+	private void testS3Import(String s, Object value)
+	{
+		StructValue sv = new StructValue( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S3, vf );
+		sv.put( ValueFactoryTest1._mf_tipe, s );
+		sv.put( ValueFactoryTest1._mf_x, value );
+		S3 myS3 = (S3) vf.importCustomValue( sv );
+		assertEquals( s, myS3.tipe );
+		assertEquals( value, myS3.x );
+	}	
+	
+	private void testS4Export(String s, Object[] value)
+	{
+		StructValue sv = vf.exportCustomValue( new S4( s,value ) );
+		sv.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S4 );
+		assertEquals( 2, sv.size() );
+		assertEquals( s, sv.get( ValueFactoryTest1._mf_tipe ) );
+		assertEquals( value, sv.get( ValueFactoryTest1._mf_x ) );
+	}
+	
+	private void testS4Import(String s, Object[] value)
+	{
+		StructValue sv = new StructValue( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_S4, vf );
+		sv.put( ValueFactoryTest1._mf_tipe, s );
+		sv.put( ValueFactoryTest1._mf_x, value );
+		S4 myS4 = (S4) vf.importCustomValue( sv );
+		assertEquals( s, myS4.tipe );
+		assertArrayEquals( value, myS4.x );
+	}
+	
+	private void testExcp5Export(String msg, int code, Object value)
+	{
+		StructValue sv = vf.exportCustomValue( new Excp5( msg, code, value ) );
+		sv.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp5 );
+		assertEquals( 3, sv.size() );
+		assertEquals( msg, sv.get( ValueFactoryTest1._mf_msg ) );
+		assertEquals( code, sv.get( ValueFactoryTest1._mf_code ) );
+		assertEquals( value, sv.get( ValueFactoryTest1._mf_x ) );		
+	}
+	
+	private void testExcp5Import(String msg, int code, Object value)
+	{
+		StructValue sv = new StructValue( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp5, vf );
+		sv.put( ValueFactoryTest1._mf_msg, msg );
+		sv.put( ValueFactoryTest1._mf_code, code );
+		sv.put( ValueFactoryTest1._mf_x, value );		
+		Excp5 e = (Excp5) vf.importCustomValue( sv );
+		assertEquals( msg, e.msg );
+		assertEquals( code, e.code );
+		assertEquals( value, e.x );		
+	}	
+	
+	private void testExcp6Export(String msg, int code, Object[] value)
+	{
+		StructValue sv = vf.exportCustomValue( new Excp6( msg, code, value ) );
+		sv.checkType( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp6 );
+		assertEquals( 3, sv.size() );
+		assertEquals( msg, sv.get( ValueFactoryTest1._mf_msg ) );
+		assertEquals( code, sv.get( ValueFactoryTest1._mf_code ) );
+		assertEquals( value, sv.get( ValueFactoryTest1._mf_x ) );		
+	}
+	
+	private void testExcp6Import(String msg, int code, Object[] value)
+	{
+		StructValue sv = new StructValue( ValueFactoryTest1._mt_org_apache_etch_tests_Test1_Excp6, vf );
+		sv.put( ValueFactoryTest1._mf_msg, msg );
+		sv.put( ValueFactoryTest1._mf_code, code );
+		sv.put( ValueFactoryTest1._mf_x, value );		
+		Excp6 e = (Excp6) vf.importCustomValue( sv );
+		assertEquals( msg, e.msg );
+		assertEquals( code, e.code );
+		assertArrayEquals( value, e.x );		
+	}
+}
diff --git a/tests/src/test/java/org/apache/etch/tests/TestXml.java b/tests/src/test/java/org/apache/etch/tests/TestXml.java
new file mode 100644
index 0000000..6ebb5f6
--- /dev/null
+++ b/tests/src/test/java/org/apache/etch/tests/TestXml.java
@@ -0,0 +1,1290 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.tests;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.etch.compiler.EtchGrammarConstants;
+import org.junit.After;
+import org.junit.Before;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+/** */
+public class TestXml {
+
+	Document document;
+
+	/** @throws Exception */
+	@Before
+	public void setUp() throws Exception {
+		// Load Test.xml into DOM
+		DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+		//String userDir = System.getProperty("user.dir");
+		try
+		{
+			File f = new File("tests/target/generated-sources/main/etch/xml/org/apache/etch/tests/Test1.xml");
+			
+			document = builder.parse(f);
+		}
+		catch(Exception e)
+		{
+			System.out.println("Unable to load Test.xml document: " + e);
+			System.out.println("Current dir is "+new File("." ).getAbsolutePath() );
+			assertTrue( false );
+		}
+	}
+
+	/** @throws Exception */
+	@After
+	public void tearDown() throws Exception {
+		// unload Test.xml 
+		document = null;
+	}
+
+
+	/** @throws Exception */
+	@org.junit.Test
+	public void testModule() throws Exception
+	{
+		NodeList list = document.getElementsByTagName("module");
+		
+		assertEquals(list.getLength(), 1);
+		
+		String moduleName = list.item(0).getAttributes().getNamedItem("name").getNodeValue();
+		assertEquals(moduleName, "org.apache.etch.tests");
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(list.item(0), new String[] {"name"}));
+		
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(list.item(0), new String[] {"description", "service"}));
+		
+		
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void testService() throws Exception
+	{
+		NodeList list = document.getElementsByTagName("service");
+		
+		assertEquals(list.getLength(), 1);
+		
+		String serviceName = list.item(0).getAttributes().getNamedItem("name").getNodeValue();
+		assertEquals(serviceName, "Test1");
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(list.item(0), new String[] {"name"}));
+			
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(list.item(0), new String[] { "consts", "externs", "enums", "structs", "exceptions", "methods"}));
+		
+		
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void testConsts() throws Exception
+	{
+		// verify consts
+		NodeList list = document.getElementsByTagName("const");
+		
+		assertEquals(list.getLength(), 42);
+		
+		int nodeCount = 0;
+		
+		checkConstProperties(list.item(nodeCount++), "BOOL1", getTypeName(EtchGrammarConstants.BOOLEAN), "false", null);
+		checkConstProperties(list.item(nodeCount++), "BOOL2", getTypeName(EtchGrammarConstants.BOOLEAN), "true", null);
+	
+		checkConstProperties(list.item(nodeCount++), "BYTE1", getTypeName(EtchGrammarConstants.BYTE), "-128", null);
+		checkConstProperties(list.item(nodeCount++), "BYTE2", getTypeName(EtchGrammarConstants.BYTE), "-1", null);
+		checkConstProperties(list.item(nodeCount++), "BYTE3", getTypeName(EtchGrammarConstants.BYTE), "0", null);
+		checkConstProperties(list.item(nodeCount++), "BYTE4", getTypeName(EtchGrammarConstants.BYTE), "1", null);
+		checkConstProperties(list.item(nodeCount++), "BYTE5", getTypeName(EtchGrammarConstants.BYTE), "127", null);
+		
+		checkConstProperties(list.item(nodeCount++), "SHORT1", getTypeName(EtchGrammarConstants.SHORT), "-32768", null);
+		checkConstProperties(list.item(nodeCount++), "SHORT2", getTypeName(EtchGrammarConstants.SHORT), "-1", null);
+		checkConstProperties(list.item(nodeCount++), "SHORT3", getTypeName(EtchGrammarConstants.SHORT), "0", null);
+		checkConstProperties(list.item(nodeCount++), "SHORT4", getTypeName(EtchGrammarConstants.SHORT), "1", null);
+		checkConstProperties(list.item(nodeCount++), "SHORT5", getTypeName(EtchGrammarConstants.SHORT), "32767", null);
+		
+		checkConstProperties(list.item(nodeCount++), "INT1", getTypeName(EtchGrammarConstants.INT), "-2147483648", null);
+		checkConstProperties(list.item(nodeCount++), "INT2", getTypeName(EtchGrammarConstants.INT), "-1", null);
+		checkConstProperties(list.item(nodeCount++), "INT3", getTypeName(EtchGrammarConstants.INT), "0", null);
+		checkConstProperties(list.item(nodeCount++), "INT4", getTypeName(EtchGrammarConstants.INT), "1", null);
+		checkConstProperties(list.item(nodeCount++), "INT5", getTypeName(EtchGrammarConstants.INT), "2147483647", null);
+		
+		checkConstProperties(list.item(nodeCount++), "LONG1", getTypeName(EtchGrammarConstants.LONG), "-9223372036854775808", null);
+		checkConstProperties(list.item(nodeCount++), "LONG2", getTypeName(EtchGrammarConstants.LONG), "-1", null);
+		checkConstProperties(list.item(nodeCount++), "LONG3", getTypeName(EtchGrammarConstants.LONG), "0", null);
+		checkConstProperties(list.item(nodeCount++), "LONG4", getTypeName(EtchGrammarConstants.LONG), "1", null);
+		checkConstProperties(list.item(nodeCount++), "LONG5", getTypeName(EtchGrammarConstants.LONG), "9223372036854775807", null);
+		
+		checkConstProperties(list.item(nodeCount++), "FLOAT1", getTypeName(EtchGrammarConstants.FLOAT), "1.4e-45", null);
+		checkConstProperties(list.item(nodeCount++), "FLOAT2", getTypeName(EtchGrammarConstants.FLOAT), "-1", null);
+		checkConstProperties(list.item(nodeCount++), "FLOAT3", getTypeName(EtchGrammarConstants.FLOAT), "0", null);
+		checkConstProperties(list.item(nodeCount++), "FLOAT4", getTypeName(EtchGrammarConstants.FLOAT), "1", null);
+		checkConstProperties(list.item(nodeCount++), "FLOAT5", getTypeName(EtchGrammarConstants.FLOAT), "3.4028235e38", null);
+		
+		checkConstProperties(list.item(nodeCount++), "DOUBLE1", getTypeName(EtchGrammarConstants.DOUBLE), "4.9e-324", null);
+		checkConstProperties(list.item(nodeCount++), "DOUBLE2", getTypeName(EtchGrammarConstants.DOUBLE), "-1", null);
+		checkConstProperties(list.item(nodeCount++), "DOUBLE3", getTypeName(EtchGrammarConstants.DOUBLE), "0", null);
+		checkConstProperties(list.item(nodeCount++), "DOUBLE4", getTypeName(EtchGrammarConstants.DOUBLE), "1", null);
+		checkConstProperties(list.item(nodeCount++), "DOUBLE5", getTypeName(EtchGrammarConstants.DOUBLE), "1.7976931348623157e308", null);
+		
+		checkConstProperties(list.item(nodeCount++), "STRING1", getTypeName(EtchGrammarConstants.STRING), "", null);
+		checkConstProperties(list.item(nodeCount++), "STRING2", getTypeName(EtchGrammarConstants.STRING), "a", null);
+		checkConstProperties(list.item(nodeCount++), "STRING3", getTypeName(EtchGrammarConstants.STRING), "abc", null);
+		checkConstProperties(list.item(nodeCount++), "STRING4", getTypeName(EtchGrammarConstants.STRING), "a\tb\tc\r\n", null);
+		checkConstProperties(list.item(nodeCount++), "STRING5", getTypeName(EtchGrammarConstants.STRING), "x\u0020x", null);
+		checkConstProperties(list.item(nodeCount++), "STRING6", getTypeName(EtchGrammarConstants.STRING), "x\u00bfx", null);
+		checkConstProperties(list.item(nodeCount++), "STRING7", getTypeName(EtchGrammarConstants.STRING), "x\u03a9x", null);
+		checkConstProperties(list.item(nodeCount++), "STRING8", getTypeName(EtchGrammarConstants.STRING), "x\\x", null);
+		checkConstProperties(list.item(nodeCount++), "STRING9", getTypeName(EtchGrammarConstants.STRING), "x'x", null);
+		checkConstProperties(list.item(nodeCount++), "STRING10", getTypeName(EtchGrammarConstants.STRING), "x\"x", null);
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void testExterns() throws Exception
+	{
+		// verify consts
+		NodeList list = document.getElementsByTagName("extern");
+		
+		assertEquals(list.getLength(), 1);
+		
+		int nodeCount = 0;
+		
+		
+		
+		Node externNode = list.item(nodeCount++);
+		
+		checkExternProperties(externNode, "Blob", "-1308039838", "org.apache.etch.tests.Test1.Blob");
+		checkExternMapProperties(externNode, "java", "StrIntHashMap", "org.apache.etch.bindings.java.util.StrIntHashMap", "StrIntHashMapSerializer",  "org.apache.etch.bindings.java.util.StrIntHashMapSerializer");
+		checkExternMapProperties(externNode, "csharp", "StrIntHashMap", "Org.Apache.Etch.Bindings.Csharp.Util", "StrIntHashMapSerializer",  "Org.Apache.Etch.Bindings.Csharp.Util");
+	}
+		
+	/** @throws Exception */
+	@org.junit.Test
+	public void testEnums() throws Exception
+	{
+		// verify enums
+		NodeList list = document.getElementsByTagName("enum");
+		
+		assertEquals(list.getLength(), 1);
+		
+		int nodeCount = 0;
+		
+		Node enumNode = list.item(nodeCount++);
+		
+		checkEnumProperties(enumNode, "E1", "874541489", "org.apache.etch.tests.Test1.E1", "blah");
+		checkEnumValueProperties(enumNode, "A", "352988284");
+		checkEnumValueProperties(enumNode, "B", "352988285");
+		checkEnumValueProperties(enumNode, "C", "352988286");
+		
+		
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void testStructs() throws Exception
+	{
+		// verify structs
+		NodeList list = document.getElementsByTagName("struct");
+		
+		assertEquals(list.getLength(), 4);
+		
+		int nodeCount = 0;
+		
+		Node structNode = list.item(nodeCount++);
+		
+		checkStructProperties(structNode, "S1", "875459875", "org.apache.etch.tests.Test1.S1", "null", "blah");
+		checkStructValueProperties(structNode, "x", "352988339", "x", "int", "true", "false", null, "value");
+		checkStructValueProperties(structNode, "y", "352988340", "y", "int", "true", "false", null, "value");
+		checkStructValueProperties(structNode, "z", "352988341", "z", "int", "true", "false", null, "value");
+		
+	
+	}
+		
+	/** @throws Exception */
+	@org.junit.Test
+	public void textExceptions() throws Exception
+	{
+		// verify structs
+		NodeList exceptionsNodeList = document.getElementsByTagName("exceptions");
+		
+		assertEquals(exceptionsNodeList.getLength(), 1);
+		
+		Node exceptionsNode = exceptionsNodeList.item(0);
+		
+		ArrayList<Node>list = new ArrayList<Node>();
+			
+		NodeList exceptionsNodeChildren = exceptionsNode.getChildNodes();
+		for(int i = 0; i < exceptionsNodeChildren.getLength(); i++)
+		{
+			if(exceptionsNodeChildren.item(i).getNodeName() == "exception")
+			{
+				list.add(exceptionsNodeChildren.item(i));
+			}
+		}
+		
+		
+		assertEquals(list.size(), 6);
+		
+		int nodeCount = 0;
+		
+		Node exceptionNode = list.get(nodeCount++);
+		
+		checkExceptionProperties(exceptionNode, "Excp1", "false", "-1446075732", "org.apache.etch.tests.Test1.Excp1", "null", "blah");
+		checkExceptionValueProperties(exceptionNode, "msg", "769750364", "msg", "string", "false", null, "value");
+		checkExceptionValueProperties(exceptionNode, "code", "-325551150", "code", "int", "false", null, "value");
+		
+		
+	}
+	
+	/** @throws Exception */
+	@org.junit.Test
+	public void testMethods() throws Exception
+	{
+		// verify structs
+		NodeList list = document.getElementsByTagName("method");
+		
+		/**
+		 * There are 12 methods, and 11 of them have result/response
+		 * messages => 23 total methods
+		 */
+		assertEquals(150, list.getLength());
+		
+		int nodeCount = 0;
+		
+		Node methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "nothing", "1830690024", "org.apache.etch.tests.Test1.nothing", "free", "false", "both", null, "do absolutely nothing", null);
+		checkAuthorize(methodNode, null);
+		checkResult(methodNode, "793503461", "org.apache.etch.tests.Test1._result_nothing", "void", "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_nothing", "793503461", "org.apache.etch.tests.Test1._result_nothing", 
+				"none", "true", "both", "4000", null, "result");
+		checkAuthorize(methodNode, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "incr", "-914174311", "org.apache.etch.tests.Test1.incr", "queued", "false", "both", null, "Increments a value by one.", null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "x", "352988339", "x", "int", "true", "false", null, "a value");
+		checkResult(methodNode, "-507533604", "org.apache.etch.tests.Test1._result_incr", "int", "true", "false", null, "a value one larger.");
+		
+	/*	methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_incr", "-1982489532", "etch.bindings.xml.compiler.test.Test._result_incr", 
+				"none", "true", "both", "4000", null, "result");
+		checkAuthorize(methodNode, null);
+				
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "sum", "874329470", "etch.bindings.xml.compiler.test.Test.sum", "none", "false", "both", null, null, null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "x", "352988339", "x", "int", "true", "true", "1", null);
+		checkResult(methodNode, "98561147", "etch.bindings.xml.compiler.test.Test._result_sum", "int", "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_sum", "98561147", "etch.bindings.xml.compiler.test.Test._result_sum", 
+				"none", "true", "both", "4000", null, "result");
+		checkAuthorize(methodNode, null);
+				
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "fill", "-1511270800", "etch.bindings.xml.compiler.test.Test.fill", "none", "false", "both", null, null, null);
+		checkAuthorize(methodNode, null);
+		checkMethodFieldProperties(methodNode, "n", "352988329", "n", "int", "true", "false", null, null);
+		checkMethodFieldProperties(methodNode, "x", "352988339", "x", "int", "true", "false", null, null);
+		checkResult(methodNode, "-70000973", "etch.bindings.xml.compiler.test.Test._result_fill", "int", "true", "true", "1", null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_fill", "-70000973", "etch.bindings.xml.compiler.test.Test._result_fill", 
+				"none", "true", "both", "4000", null, "result");
+		checkAuthorize(methodNode, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "alwaysWorks", "899313734", "etch.bindings.xml.compiler.test.Test.alwaysWorks", "none", "false", "both", null, null, null);
+		checkAuthorize(methodNode, "isTrue");
+		checkResult(methodNode, "-253629117", "etch.bindings.xml.compiler.test.Test._result_alwaysWorks", "int", "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_alwaysWorks", "-253629117", "etch.bindings.xml.compiler.test.Test._result_alwaysWorks", 
+				"none", "true", "both", "4000", null, "result");
+		checkAuthorize(methodNode, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "isTrue", "-1995546491", "etch.bindings.xml.compiler.test.Test.isTrue", "none", "false", "both", null, null, null);
+		checkAuthorize(methodNode, null);
+		checkResult(methodNode, "2087745352", "etch.bindings.xml.compiler.test.Test._result_isTrue", "boolean", "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_isTrue", "2087745352", "etch.bindings.xml.compiler.test.Test._result_isTrue", 
+				"none", "true", "both", "4000", null, "result");
+		checkAuthorize(methodNode, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "alwaysFails", "588983161", "etch.bindings.xml.compiler.test.Test.alwaysFails", "none", "true", "both", null, null, null);
+		checkAuthorize(methodNode, "isFalse");
+		checkResult(methodNode);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "isFalse", "1221405260", "etch.bindings.xml.compiler.test.Test.isFalse", "none", "false", "both", null, null, null);
+		checkAuthorize(methodNode, null);
+		checkResult(methodNode, "1152631881", "etch.bindings.xml.compiler.test.Test._result_isFalse", "boolean", "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_isFalse", "1152631881", "etch.bindings.xml.compiler.test.Test._result_isFalse", 
+				"none", "true", "both", "4000", null, "result");
+		checkAuthorize(methodNode, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "m3", "-563514125", "etch.bindings.xml.compiler.test.Test.m3", "none", "false", "both", null, null, null);
+		checkAuthorize(methodNode, "can_m1");
+		checkResult(methodNode, "-1307038026", "etch.bindings.xml.compiler.test.Test._result_m3", "void", "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_m3", "-1307038026", "etch.bindings.xml.compiler.test.Test._result_m3", 
+				"none", "true", "both", "4000", null, "result");
+		checkAuthorize(methodNode, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "can_m1", "-307006048", "etch.bindings.xml.compiler.test.Test.can_m1", "none", "false", "both", null, null, null);
+		checkAuthorize(methodNode, null);
+		checkResult(methodNode, "-518681501", "etch.bindings.xml.compiler.test.Test._result_can_m1", "boolean", "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_can_m1", "-518681501", "etch.bindings.xml.compiler.test.Test._result_can_m1", 
+				"none", "true", "both", "4000", null, "result");
+		checkAuthorize(methodNode, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "m1", "-563514127", "etch.bindings.xml.compiler.test.Test.m1", "none", "false", "client", null, "Test\n1\n2", null);
+		checkAuthorize(methodNode, null);
+		checkException(methodNode, "Excp1", "etch.bindings.xml.compiler.test.Test.Excp1", "Exception test");
+		checkMethodFieldProperties(methodNode, "x", "352988339", "x", "boolean", "true", "false", null, "hi");
+		checkResult(methodNode, "-1307038028", "etch.bindings.xml.compiler.test.Test._result_m1", "void", "true", "false", null, null);
+
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_m1", "-1307038028", "etch.bindings.xml.compiler.test.Test._result_m1", 
+				"none", "true", "server", "4000", null, "result");
+		checkAuthorize(methodNode, null);
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "m2", "-563514126", "etch.bindings.xml.compiler.test.Test.m2", "none", "false", "both", null, "Test\na line is here", null);
+		checkAuthorize(methodNode, null);
+		checkException(methodNode, "Excp1", "etch.bindings.xml.compiler.test.Test.Excp1", "Exception test value again");
+		checkMethodFieldProperties(methodNode, "a", "352988316", "a", "string", "true", "false", null, "test for A parameter");
+		checkMethodFieldProperties(methodNode, "b", "352988317", "b", "string", "true", "true", "1", "test for B parameter");
+		checkResult(methodNode, "-1307038027", "etch.bindings.xml.compiler.test.Test._result_m2", "boolean", "true", "false", null, "There is much to say about void!");
+		
+		methodNode = list.item(nodeCount++);
+		
+		checkMethodProperties(methodNode, "_result_m2", "-1307038027", "etch.bindings.xml.compiler.test.Test._result_m2", 
+				"none", "true", "both", "4000", null, "result");
+		checkAuthorize(methodNode, null); */
+	}
+	
+	
+	private void checkConstProperties(Node node, String constName, String constType, String constValue, String constDescription)
+	{
+		NamedNodeMap attrs = node.getAttributes();
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(node, new String[] {"name", "type", "value"}));
+
+		
+		
+		// verify that no new stuff has snuck into the XML binding
+		assertEquals(attrs.getLength(), 3);
+		
+		String nameAttr = attrs.getNamedItem("name").getNodeValue();
+		String typeAttr = attrs.getNamedItem("type").getNodeValue();
+		String valueAttr = attrs.getNamedItem("value").getNodeValue();
+		
+		// verify name of constant
+		assertEquals(nameAttr, constName);
+		
+		// verify type of constant
+		assertEquals(typeAttr, constType);
+		
+		// verify value of constant
+		assertEquals(constValue, valueAttr);
+		
+	
+	}
+	
+	private void checkExternProperties(Node node, String externName, String typeId, String typeName) throws Exception
+	{
+		NamedNodeMap attrs = node.getAttributes();
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(node, new String[] {"name", "typeId", "typeName"}));
+
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(node, new String[] {"externmap"}));
+
+		// verify that no new stuff has snuck into the XML binding
+		assertEquals(attrs.getLength(), 3);
+		
+		String nameAttr = attrs.getNamedItem("name").getNodeValue();
+		String typeIdAttr = attrs.getNamedItem("typeId").getNodeValue();
+		String typeNameAttr = attrs.getNamedItem("typeName").getNodeValue();
+		
+		assertEquals(nameAttr, externName);
+		assertEquals(typeIdAttr, typeId);
+		assertEquals(typeNameAttr, typeName);
+	}
+	
+	private void checkExternMapProperties(Node node, String language, String name, String nImport, String serializer, String sImport)
+	{
+		Node languageNode = null;
+		
+		NodeList children = node.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE && children.item(i).getNodeName() == "externmap")
+			{
+				Node thisNode = children.item(i);
+				NamedNodeMap attrs = thisNode.getAttributes();
+				Node languageAttr = attrs.getNamedItem("language");
+				String thisLanguage = languageAttr.getNodeValue();
+				if(thisLanguage.compareTo(language) == 0)
+				{
+					languageNode = children.item(i);
+					break;
+				}
+			}
+		}
+		
+		// verify that the language node exists
+		assertNotNull(languageNode);
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(languageNode, new String[] {"language", "name", "nImport", "serializer", "sImport"}));
+
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(languageNode, new String[] {"description"}));
+
+		NamedNodeMap attrs = languageNode.getAttributes();
+		
+		// verify that no new stuff has snuck into the XML binding
+		assertEquals(attrs.getLength(), 5);
+		
+		String nameAttr = attrs.getNamedItem("name").getNodeValue();
+		String nImportAttr = attrs.getNamedItem("nImport").getNodeValue();
+		String serializerAttr = attrs.getNamedItem("serializer").getNodeValue();
+		String sImportAttr = attrs.getNamedItem("sImport").getNodeValue();
+		
+		// verify the value of the externmap name
+		assertEquals(nameAttr, name);
+		
+		// verify the value of the externmap nImport
+		assertEquals(nImportAttr, nImport);
+		
+		// verify the value of the externmap serializer
+		assertEquals(serializerAttr, serializer);
+		
+		// verify the value of the externmap sImport
+		assertEquals(sImportAttr, sImport);
+		
+		// verify that no new children nodes have snuck in
+		assertEquals(getChildElementCount(languageNode), 0);
+	}
+	
+	private void checkEnumProperties(Node enumNode, String enumName, String enumTypeId, String enumTypeName, String description)
+	{
+		NamedNodeMap attrs = enumNode.getAttributes();
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(enumNode, new String[] {"name", "typeId", "typeName"}));
+
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(enumNode, new String[] {"description", "entry"}));
+
+		// verify that no new stuff has snuck into the XML binding
+		assertEquals(attrs.getLength(), 3);
+		
+		String nameAttr = attrs.getNamedItem("name").getNodeValue();
+		String typeAttr = attrs.getNamedItem("typeId").getNodeValue();
+		String valueAttr = attrs.getNamedItem("typeName").getNodeValue();
+		
+		// verify name of constant
+		assertEquals(nameAttr, enumName);
+		
+		// verify type of constant
+		assertEquals(typeAttr, enumTypeId);
+		
+		// verify value of constant
+		assertEquals(valueAttr, enumTypeName);
+		
+		Node child = getDescriptionElement(enumNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+
+	private void checkEnumValueProperties(Node enumNode, String valueName, String valueId)
+	{
+		Node valueNode = null;
+		
+		NodeList children = enumNode.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE && children.item(i).getNodeName() == "entry")
+			{
+				Node thisNode = children.item(i);
+				NamedNodeMap attrs = thisNode.getAttributes();
+				Node valueAttr = attrs.getNamedItem("value");
+				String thisValue = valueAttr.getNodeValue();
+				if(thisValue.compareTo(valueName) == 0)
+				{
+					valueNode = children.item(i);
+					break;
+				}
+			}
+		}
+		
+		// verify that the value node exists
+		assertNotNull(valueNode);
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(valueNode, new String[] {"value", "entryId"}));
+
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(valueNode, new String[] {"description"}));
+
+		NamedNodeMap attrs = valueNode.getAttributes();
+		
+		// verify that no new stuff has snuck into the XML binding
+		assertEquals(attrs.getLength(), 2);
+		
+		String entryIdAttr = attrs.getNamedItem("entryId").getNodeValue();
+		
+		// verify the value of the externmap name
+		assertEquals(entryIdAttr, valueId);
+		
+		
+		// verify that no new children nodes have snuck in
+		assertEquals(getChildElementCount(valueNode), 0);
+	}
+	
+	private void checkStructProperties(Node structNode, String structName, String structTypeId, String structTypeName, String baseType, String description)
+	{
+		NamedNodeMap attrs = structNode.getAttributes();
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(structNode, new String[] {"name", "typeId", "typeName", "baseType"}));
+
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(structNode, new String[] {"description", "field"}));
+
+		// verify that no new stuff has snuck into the XML binding
+		assertEquals(attrs.getLength(), 4);
+		
+		String nameAttr = attrs.getNamedItem("name").getNodeValue();
+		String typeAttr = attrs.getNamedItem("typeId").getNodeValue();
+		String valueAttr = attrs.getNamedItem("typeName").getNodeValue();
+		String baseTypeAttr = attrs.getNamedItem("baseType").getNodeValue();
+		
+		// verify name of constant
+		assertEquals(nameAttr, structName);
+		
+		// verify type of constant
+		assertEquals(typeAttr, structTypeId);
+		
+		// verify value of constant
+		assertEquals(valueAttr, structTypeName);
+		
+		assertEquals(baseTypeAttr, baseType );
+		
+		Node child = getDescriptionElement(structNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private void checkStructValueProperties(Node structNode, String structName, String fieldId, String fieldName, 
+		String type, String isPrimitiveType, String isArray, String dimension, String description)
+	{
+		Node fieldNode = null;
+		
+		NodeList children = structNode.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE && children.item(i).getNodeName() == "field")
+			{
+				Node thisNode = children.item(i);
+				NamedNodeMap attrs = thisNode.getAttributes();
+				Node valueAttr = attrs.getNamedItem("name");
+				String thisValue = valueAttr.getNodeValue();
+				if(thisValue.compareTo(structName) == 0)
+				{
+					fieldNode = children.item(i);
+					break;
+				}
+			}
+		}
+		
+		// verify that the value node exists
+		assertNotNull(fieldNode);
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(fieldNode, new String[] {"name", "fieldId", "fieldName", "type", "isPrimitiveType", "isArray", "dimension"}));
+
+		//verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(fieldNode, new String[] {"description"}));
+		
+		NamedNodeMap attrs = fieldNode.getAttributes();
+		
+		// verify that no new stuff has snuck into the XML binding
+		// dimension attr is nullable, meaning it might just not be there if isArray = "false"
+		assertEquals(attrs.getLength(), isArray == "false" ? 6 : 7);
+		
+		String fieldIdAttr = attrs.getNamedItem("fieldId").getNodeValue();
+		String fieldNameAttr = attrs.getNamedItem("fieldName").getNodeValue();
+		String typeAttr = attrs.getNamedItem("type").getNodeValue();
+		String isArrayAttr = attrs.getNamedItem("isArray").getNodeValue();
+		String isPrimitiveAttr = attrs.getNamedItem( "isPrimitiveType" ).getNodeValue();
+		
+		Node dimensionNode = attrs.getNamedItem("dimension");
+		String dimensionAttr = dimensionNode == null ? dimension : dimensionNode.getNodeValue();
+		
+		
+		// verify the value of the externmap name
+		assertEquals(fieldIdAttr, fieldId);
+		assertEquals(fieldNameAttr, fieldName);
+		assertEquals(typeAttr, type);
+		assertEquals(isArrayAttr, isArray);
+		assertEquals(dimensionAttr, dimension);
+		assertEquals( isPrimitiveAttr, isPrimitiveType );
+		
+		Node child = getDescriptionElement(fieldNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private void checkExceptionProperties(Node exceptionNode, String name, String isUnchecked, String exceptionId, 
+			String exceptionName, String baseTypeName, String description)
+	{
+		NamedNodeMap attrs = exceptionNode.getAttributes();
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(exceptionNode, 
+				new String[] {"name", "isUnchecked", "typeId", "typeName", "baseType"}));
+
+		//verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(exceptionNode, new String[] {"description", "field"}));
+		
+		// verify that no new stuff has snuck into the XML binding
+		assertEquals(attrs.getLength(), 5);
+		
+		String nameAttr = attrs.getNamedItem("name").getNodeValue();
+		String isUncheckedAttr = attrs.getNamedItem("isUnchecked").getNodeValue();
+		String typeAttr = attrs.getNamedItem("typeId").getNodeValue();
+		String typeName = attrs.getNamedItem("typeName").getNodeValue();
+		String baseTypeAttr = attrs.getNamedItem("baseType").getNodeValue();
+		
+		// verify name of constant
+		assertEquals(nameAttr, name);
+		
+		// verify type of constant
+		assertEquals(isUncheckedAttr, isUnchecked);
+		
+		// verify type of constant
+		assertEquals(typeAttr, exceptionId);
+		
+		// verify value of constant
+		assertEquals(typeName, exceptionName);
+		
+		assertEquals( baseTypeAttr, baseTypeName );
+		
+		Node child = getDescriptionElement(exceptionNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private void checkExceptionValueProperties(Node exceptionNode, String name, String fieldId, String fieldName, String type, String isArray, String dimension, String description)
+	{
+		Node fieldNode = null;
+		
+		NodeList children = exceptionNode.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE && children.item(i).getNodeName() == "field")
+			{
+				Node thisNode = children.item(i);
+				NamedNodeMap attrs = thisNode.getAttributes();
+				Node valueAttr = attrs.getNamedItem("name");
+				String thisValue = valueAttr.getNodeValue();
+				if(thisValue.compareTo(name) == 0)
+				{
+					fieldNode = children.item(i);
+					break;
+				}
+			}
+		}
+			
+		// verify that the value node exists
+		assertNotNull(fieldNode);
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(fieldNode, new String[] {"name", "fieldId", "fieldName", "type", "isArray", "dimension"}));
+
+//		verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(fieldNode, new String[] {"description", "field"}));
+	
+		NamedNodeMap attrs = fieldNode.getAttributes();
+		
+		// verify that no new stuff has snuck into the XML binding
+		// dimension attr is nullable, meaning it might just not be there if isArray = "false"
+		assertEquals(attrs.getLength(), isArray == "false" ? 5 : 6);
+		
+		String fieldIdAttr = attrs.getNamedItem("fieldId").getNodeValue();
+		String fieldNameAttr = attrs.getNamedItem("fieldName").getNodeValue();
+		String typeAttr = attrs.getNamedItem("type").getNodeValue();
+		String isArrayAttr = attrs.getNamedItem("isArray").getNodeValue();
+		
+		Node dimensionNode = attrs.getNamedItem("dimension");
+		String dimensionAttr = dimensionNode == null ? dimension : dimensionNode.getNodeValue();
+		
+		assertEquals(fieldIdAttr, fieldId);
+		assertEquals(fieldNameAttr, fieldName);
+		assertEquals(typeAttr, type);
+		assertEquals(isArrayAttr, isArray);
+		assertEquals(dimensionAttr, dimension);
+		
+		Node child = getDescriptionElement(fieldNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+
+	private void checkMethodProperties(Node methodNode, String name, String methodId, String methodName, 
+			String pool, String isOneway, String direction, String timeout, String description, String result)
+	{
+		NamedNodeMap attrs = methodNode.getAttributes();
+		boolean isResultMessage = false;
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(methodNode, new String[] {"name", "typeId", "typeName", "asyncReceiverMode", "isOneway", "messageDirection", "timeout",
+				"responseField"}));
+
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(methodNode, new String[] {"description", "exception", "authorize", "field", "result"}));
+	
+		// verify that no new stuff has snuck into the XML binding
+		isResultMessage = name.startsWith("_result");
+		
+		assertEquals(isResultMessage? 8 : 6, attrs.getLength());
+		
+		String nameAttr = attrs.getNamedItem("name").getNodeValue();
+		String typeIdAttr = attrs.getNamedItem("typeId").getNodeValue();
+		String typeNameAttr = attrs.getNamedItem("typeName").getNodeValue();
+		String poolAttr = attrs.getNamedItem("asyncReceiverMode").getNodeValue();
+		String isOnewayAttr = attrs.getNamedItem("isOneway").getNodeValue();
+		String directionAttr = attrs.getNamedItem("messageDirection").getNodeValue();
+		String timeoutAttr = "";
+		String resultAttr = "";
+		
+		if ( isResultMessage )
+		{
+			timeoutAttr = attrs.getNamedItem("timeout").getNodeValue();
+			resultAttr = attrs.getNamedItem("responseField").getNodeValue();
+		}
+		
+		// verify name of method
+		assertEquals(nameAttr, name);
+		
+		// verify type of method
+		assertEquals(typeIdAttr, methodId);
+		
+		// verify value of method
+		assertEquals(typeNameAttr, methodName);
+		
+		// verify value of pool
+		assertEquals(poolAttr, pool);
+		
+		// verify value of isOneway
+		assertEquals(isOnewayAttr, isOneway);
+		
+		// verify value of isOneway
+		assertEquals(directionAttr, direction);
+		
+		// verify value of isOneway
+		if ( isResultMessage )
+		{
+			assertEquals(timeoutAttr, timeout);
+			assertEquals(resultAttr, result);
+		}
+		Node child = getDescriptionElement(methodNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private void checkAuthorize(Node methodNode, String authorizeMethodName)
+	{
+		Node child = getAuthorizeElement(methodNode);
+		
+		if(authorizeMethodName == null)
+		{
+			assertNull(child);
+		}
+		else
+		{
+			// verify that no unknown attr exist
+			assertTrue(onlyAttrsOfName(child, new String[] {"methodName"}));
+
+			// verify that no unknown child nodes exist
+			assertTrue(onlyChildNodesOfName(child, new String[] {}));
+		
+			String authorizeAttr = child.getAttributes().getNamedItem("methodName").getNodeValue();
+			
+			assertEquals(authorizeAttr, authorizeMethodName);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+//	private void checkException(Node methodNode, String exceptionName, String exceptionType, String description)
+//	{
+//		Node exceptionNode = null;
+//		
+//		NodeList children = methodNode.getChildNodes();
+//		for(int i = 0; i < children.getLength(); i++)
+//		{
+//			if(children.item(i).getNodeType() == Node.ELEMENT_NODE && children.item(i).getNodeName() == "exception")
+//			{
+//				Node thisNode = children.item(i);
+//				NamedNodeMap attrs = thisNode.getAttributes();
+//				Node valueAttr = attrs.getNamedItem("name");
+//				String thisValue = valueAttr.getNodeValue();
+//				if(thisValue.compareTo(exceptionName) == 0)
+//				{
+//					exceptionNode = children.item(i);
+//					break;
+//				}
+//			}
+//		}
+//		
+//		assertEquals( exceptionNode.getAttributes().getNamedItem("type").getNodeValue(), exceptionType );
+//		
+//		// verify that the value node exists
+//		assertNotNull(exceptionNode);
+//		
+//		// verify that no unknown attr exist
+//		assertTrue(onlyAttrsOfName(exceptionNode, new String[] {"name","type"}));
+//
+//		
+//		// verify that no unknown child nodes exist
+//		assertTrue(onlyChildNodesOfName(exceptionNode, new String[] {"description"}));
+//	
+//		Node child = getDescriptionElement(exceptionNode);
+//		
+//		if(description == null)
+//		{
+//			assertNull(child);
+//		}
+//		else
+//		{	
+//			String descriptionValue = child.getTextContent().trim();
+//			assertEquals(descriptionValue, description);
+//			
+//			// verify that no new children on description
+//			assertEquals(getChildElementCount(child), 0);
+//		}
+//		
+//	}
+	
+	private void checkResult(Node methodNode, String fieldId, String fieldName, String type, String isPrimitiveType,
+		String isArray, String dimension, String description)
+	{
+		Node resultNode = getResultElement(methodNode);
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(resultNode, new String[] {"fieldId", "fieldName", "type", "isPrimitiveType", "isArray", "dimension"}));
+
+		// verify that the value node exists
+		assertNotNull(resultNode);
+		
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(resultNode, new String[] {"description"}));
+	
+		NamedNodeMap attrs = resultNode.getAttributes();
+		
+		// verify that no new stuff has snuck into the XML binding
+		
+		// this is special case of a oneway message, so we should only have 'type=void' and 'isArray=true' specified.
+		String fieldIdAttr = null;
+		String fieldNameAttr = null;
+		
+		if(fieldId == null)
+		{
+			assertEquals(attrs.getLength(), 3);
+			
+		}
+		else // dimension attr is nullable, meaning it might just not be there if isArray = "false"
+		{
+			fieldIdAttr = attrs.getNamedItem("fieldId").getNodeValue();
+			fieldNameAttr = attrs.getNamedItem("fieldName").getNodeValue();
+			
+			assertEquals(attrs.getLength(), isArray == "false" ? 5 : 6);
+		}
+		
+		String typeAttr = attrs.getNamedItem("type").getNodeValue();
+		String isArrayAttr = attrs.getNamedItem("isArray").getNodeValue();
+
+		Node dimensionNode = attrs.getNamedItem("dimension");
+		String dimensionAttr = dimensionNode == null ? dimension : dimensionNode.getNodeValue();
+		
+		assertEquals(fieldIdAttr, fieldId);
+		assertEquals(fieldNameAttr, fieldName);
+		assertEquals(typeAttr, type);
+		assertEquals(isArrayAttr, isArray);
+		assertEquals(dimensionAttr, dimension);
+		
+		Node child = getDescriptionElement(resultNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private void checkMethodFieldProperties(Node methodNode, String name, String fieldId, String fieldName, String type, 
+			String isPrimitiveType, String isArray, String dimension, String description)
+	{
+		Node fieldNode = null;
+		
+		NodeList children = methodNode.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE && children.item(i).getNodeName() == "field")
+			{
+				Node thisNode = children.item(i);
+				NamedNodeMap attrs = thisNode.getAttributes();
+				Node valueAttr = attrs.getNamedItem("name");
+				String thisValue = valueAttr.getNodeValue();
+				if(thisValue.compareTo(name) == 0)
+				{
+					fieldNode = children.item(i);
+					break;
+				}
+			}
+		}
+		
+		// verify that the value node exists
+		assertNotNull(fieldNode);
+		
+		// verify that no unknown attr exist
+		assertTrue(onlyAttrsOfName(fieldNode, new String[] {"name", "fieldId", "fieldName", "type", 
+				"isPrimitiveType", "isArray", "dimension" }));
+
+		// verify that no unknown child nodes exist
+		assertTrue(onlyChildNodesOfName(fieldNode, new String[] {"description"}));
+	
+		NamedNodeMap attrs = fieldNode.getAttributes();
+		
+		// verify that no new stuff has snuck into the XML binding
+		// dimension attr is nullable, meaning it might just not be there if isArray = "false"
+		assertEquals(attrs.getLength(), isArray == "false" ? 6 : 7);
+		
+		String fieldIdAttr = attrs.getNamedItem("fieldId").getNodeValue();
+		String fieldNameAttr = attrs.getNamedItem("fieldName").getNodeValue();
+		String typeAttr = attrs.getNamedItem("type").getNodeValue();
+		String isArrayAttr = attrs.getNamedItem("isArray").getNodeValue();
+		String isPrimitiveTypeAttr = attrs.getNamedItem("isPrimitiveType").getNodeValue();
+		
+		Node dimensionNode = attrs.getNamedItem("dimension");
+		String dimensionAttr = dimensionNode == null ? dimension : dimensionNode.getNodeValue();
+		
+		assertEquals(fieldIdAttr, fieldId);
+		assertEquals(fieldNameAttr, fieldName);
+		assertEquals(typeAttr, type);
+		assertEquals(isArrayAttr, isArray);
+		assertEquals(dimensionAttr, dimension);
+		assertEquals( isPrimitiveType, isPrimitiveTypeAttr );
+		
+		Node child = getDescriptionElement(fieldNode);
+		
+		if(description == null)
+		{
+			assertNull(child);
+		}
+		else
+		{	
+			String descriptionValue = child.getTextContent().trim();
+			assertEquals(descriptionValue, description);
+			
+			// verify that no new children on description
+			assertEquals(getChildElementCount(child), 0);
+		}
+	}
+	
+	private Node getDescriptionElement(Node node)
+	{
+		NodeList children = node.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			short nodeType = children.item(i).getNodeType();
+			String nodeName = children.item(i).getNodeName();
+			if(nodeType == Node.ELEMENT_NODE && nodeName == "description")
+			{
+				return children.item(i);
+			}
+		}
+		return null;
+	}
+	
+	private Node getAuthorizeElement(Node node)
+	{
+		NodeList children = node.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			short nodeType = children.item(i).getNodeType();
+			String nodeName = children.item(i).getNodeName();
+			if(nodeType == Node.ELEMENT_NODE && nodeName == "authorize")
+			{
+				return children.item(i);
+			}
+		}
+		return null;
+	}
+	
+	private Node getResultElement(Node node)
+	{
+		NodeList children = node.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			short nodeType = children.item(i).getNodeType();
+			String nodeName = children.item(i).getNodeName();
+			if(nodeType == Node.ELEMENT_NODE && nodeName == "result")
+			{
+				return children.item(i);
+			}
+		}
+		return null;
+	}
+	
+	private int getChildElementCount(Node node)
+	{
+		int count = 0;
+		
+		NodeList children = node.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++)
+		{
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE)
+			{
+				count++;
+			}
+		}
+		
+		return count;
+	}
+	
+	private String getTypeName(int etchGrammarConstantsLookup)
+	{
+		switch (etchGrammarConstantsLookup)
+		{
+			case EtchGrammarConstants.VOID: return "void";
+			case EtchGrammarConstants.BOOLEAN: return "boolean";
+			case EtchGrammarConstants.BYTE: return "byte";
+			case EtchGrammarConstants.SHORT: return "short";
+			case EtchGrammarConstants.INT: return "int";
+			case EtchGrammarConstants.LONG: return "long";
+			case EtchGrammarConstants.FLOAT: return "float";
+			case EtchGrammarConstants.DOUBLE: return "double";
+			case EtchGrammarConstants.STRING: return "string";
+			default: return null;
+		}
+	}
+	
+	private boolean onlyChildNodesOfName(Node node, String[] elementNamesToCheck)
+	{
+		NodeList children = node.getChildNodes();
+		
+		boolean hasValidChildren = true;
+		
+		for(int i = 0; i < children.getLength(); i++)
+		{
+		
+			if(children.item(i).getNodeType() == Node.ELEMENT_NODE)
+			{
+				String elementName = children.item(i).getNodeName();
+				
+				boolean matches = false;
+				for (String element : elementNamesToCheck)
+				{
+					if(0 == elementName.compareTo(element) )
+					{
+						matches = true;
+						break;
+					}
+				}
+				
+				if(matches == false)
+				{
+					hasValidChildren = false;
+					break;
+				}
+			}	
+		}
+		
+		return hasValidChildren;
+	}
+	
+	private boolean onlyAttrsOfName(Node node, String[] attrNamesToCheck)
+	{
+		NamedNodeMap attrs = node.getAttributes();
+		
+		boolean hasValidAttrs = true;
+		
+		for(int i = 0; i < attrs.getLength(); i++)
+		{
+			String attrName = attrs.item(i).getNodeName();
+			
+			boolean matches = false;
+			for (String element : attrNamesToCheck)
+			{
+				if(0 == attrName.compareTo(element) )
+				{
+					matches = true;
+					break;
+				}
+			}
+			
+			if(matches == false)
+			{
+				hasValidAttrs = false;
+				break;
+			}
+			
+		}
+		
+		return hasValidAttrs;
+	}
+}
diff --git a/util/build.xml b/util/build.xml
new file mode 100644
index 0000000..9ae7f71
--- /dev/null
+++ b/util/build.xml
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ -->
+<project name="etch-util" basedir="." default="help">
+    <description>Common utilities for compiler implementations and java binding</description>
+    <property name="Etch.basedir" location="${basedir}/.." />
+    <import file="${Etch.basedir}/build-support/etch.includes.xml" />
+
+    <!-- Static properties of the sub-project -->
+    <property name="proj"                 location="${Etch.basedir}/util" />
+    <property name="target"               location="${proj}/target" />
+    <property name="src"                  location="${proj}/src" />        
+    <property name="generatedSrc"         location="${target}/generated-sources" />
+    <property name="classesDirectory"     location="${target}/classes" />
+    <property name="resourcesDirectory"   location="${target}/resources" />
+    <property name="testResultsDirectory" location="${target}/test-results" />
+
+    <!-- MACRO: init-target -->
+    <macrodef name="init-target" >
+        <sequential>
+            <delete dir="${classesDirectory}"   failonerror="false" quiet="true" />
+            <delete dir="${resourcesDirectory}" failonerror="false" quiet="true" />
+            <mkdir dir="${classesDirectory}" />
+            <mkdir dir="${classesDirectory}/main" />
+            <mkdir dir="${classesDirectory}/test" />
+            <mkdir dir="${resourcesDirectory}" />
+        </sequential>
+    </macrodef>
+
+    <!-- MACRO: compile-sources -->
+    <macrodef name="compile-sources" >
+        <sequential>
+            <mkdir dir="${classesDirectory}/main" />
+            <mkdir dir="${classesDirectory}/test" />
+            
+            <javac  debug="${Etch.javac.debug}"
+            		target="1.5"
+                    optimize="${Etch.javac.optimize}"
+                    destdir="${classesDirectory}/main" >
+                <src path="${src}/main/java" />
+                <exclude name="**/.svn/**" />
+                <classpath refid="Etch.dependencies.jar.paths" />
+            </javac>
+
+            <javac  debug="${Etch.javac.debug}"
+            		target="1.5"
+                    optimize="${Etch.javac.optimize}"
+                    destdir="${classesDirectory}/test" >
+                <src path="${src}/test/java" />
+                <exclude name="**/.svn/**" />
+                <classpath refid="Etch.dependencies.jar.paths" />
+                <classpath>
+                    <pathelement location="${classesDirectory}/main" />
+                </classpath>
+            </javac>
+
+        </sequential>
+    </macrodef>
+    
+    <!-- MACRO: bundle-jars -->
+    <macrodef name="bundle-jars" >
+        <attribute name="dist" default="${Etch.support}" />
+        <sequential>
+            <mkdir dir="@{dist}/lib" />
+            
+            <!-- CREATE jars -->
+
+            <!-- Package up etch-util jar -->
+            <jar jarfile="@{dist}/lib/${etch-util.jar}" >
+                <manifest>
+                    <attribute name="Copyright"    value="${Etch.copyrightNotice}" />
+                    <attribute name="Version"      value="${Etch.version}" />
+                    <attribute name="LongVersion"  value="${Etch.longversion}" />
+                    <attribute name="Build-Tag"    value="${Etch.buildTag}" />
+                    <attribute name="SVN-Revision" value="${Etch.runtime.revisionNumber}" />
+                </manifest>
+                <metainf dir="${Etch.basedir}" >
+                    <include name="NOTICE.txt" />
+                    <include name="LICENSE.txt" />
+                </metainf>
+                <fileset dir="${classesDirectory}/main">
+                    <include name="org/apache/etch/util/**" />
+                </fileset>
+            </jar>
+
+            <!-- placeholder -->
+            <jar jarfile="@{dist}/lib/${etch-compiler.jar}" update="true" filesetmanifest="merge">
+               <manifest>
+                  <attribute name="Version" value="${Etch.version}" />
+               </manifest>   
+            </jar>
+            <jar jarfile="@{dist}/lib/${etch-java-runtime.jar}" update="true" filesetmanifest="merge">
+               <manifest>
+                  <attribute name="Version" value="${Etch.version}" />
+               </manifest>   
+            </jar>
+
+            <!-- CREATE source archives -->
+            
+            <!-- package up etch-util src -->
+            <zip destfile="@{dist}/lib/${etch-util-src.zip}" >
+                <fileset dir="${src}/main/java" >
+                    <include name="org/apache/etch/util/**/*.java" />
+                    <exclude name="**/test/**" />
+                </fileset>
+            </zip>
+
+            <mkdir dir="${target}/empty-dir" />
+            <zip destfile="@{dist}/lib/${etch-compiler-src.zip}" update="true" whenempty="create" basedir="${target}/empty-dir" />
+            <zip destfile="@{dist}/lib/${etch-java-runtime-src.zip}" update="true" whenempty="create" basedir="${target}/empty-dir" />
+            
+
+        </sequential>
+    </macrodef>
+
+    <!-- MACRO: update-jars -->
+    <macrodef name="update-jars" >
+        <attribute name="dist" default="${Etch.dist}" />
+        <attribute name="support" default="${Etch.support}" />
+        <sequential>
+            <!-- repackage .jar -->
+            <mkdir dir="@{dist}/lib" />
+            <delete dir="${target}/tmp-compiler" quiet="true" />
+            <mkdir dir="${target}/tmp-compiler" />
+            <delete dir="${target}/tmp-runtime"  quiet="true" />
+            <mkdir dir="${target}/tmp-runtime" />
+
+            <unjar src="@{support}/lib/${etch-util.jar}"     dest="${target}/tmp-compiler" />
+            <unjar src="@{support}/lib/${etch-compiler.jar}" dest="${target}/tmp-compiler" />
+            <unjar src="@{support}/lib/${etch-util.jar}"     dest="${target}/tmp-runtime" />
+            <unjar src="@{support}/lib/${etch-java-runtime.jar}" dest="${target}/tmp-runtime" />
+
+            <jar jarfile="@{dist}/lib/${etch-compiler.jar}" update="true" filesetmanifest="merge" >
+                <fileset dir="${target}/tmp-compiler"  />
+            </jar>    
+            <jar jarfile="@{dist}/lib/${etch-java-runtime.jar}" update="true" filesetmanifest="merge" >
+                <fileset dir="${target}/tmp-runtime"  />
+            </jar>
+            
+            <!-- repackage .zip src -->
+            <mkdir dir="@{dist}/lib" />
+            <delete dir="${target}/tmp-compiler-src" quiet="true" />
+            <mkdir dir="${target}/tmp-compiler-src" />
+            <delete dir="${target}/tmp-runtime-src"  quiet="true" />
+            <mkdir dir="${target}/tmp-runtime-src" />
+            
+            <unzip src="@{support}/lib/${etch-util-src.zip}" dest="${target}/tmp-compiler-src" />
+            <unzip src="@{support}/lib/${etch-compiler-src.zip}" dest="${target}/tmp-compiler-src" />
+            <unzip src="@{support}/lib/${etch-util-src.zip}" dest="${target}/tmp-runtime-src" />
+            <unzip src="@{support}/lib/${etch-java-runtime-src.zip}" dest="${target}/tmp-runtime-src" />
+            
+            <zip destfile="@{dist}/lib/${etch-compiler-src.zip}" >
+                <fileset dir="${target}/tmp-compiler-src" />
+            </zip>
+            <zip destfile="@{dist}/lib/${etch-java-runtime-src.zip}" >
+                <fileset dir="${target}/tmp-runtime-src" />
+            </zip>
+            
+        </sequential>
+    </macrodef>
+    
+    <!-- INIT TARGET -->
+    <!-- Modify this target to define project specific properties that can only be set at runtime -->
+    <target name="do-init">
+        <delete dir="${target}" failonerror="false" quiet="true" />
+
+        <mkdir dir="${target}" />
+        <mkdir dir="${generatedSrc}" />
+        <mkdir dir="${classesDirectory}" />
+        <mkdir dir="${resourcesDirectory}" />
+        <mkdir dir="${testResultsDirectory}" />
+    </target>
+
+    <!-- CLEAN TARGET -->
+    <target name="do-clean">
+        <delete dir="${target}" />
+    </target>
+
+    <!-- BUILD TARGET -->
+    
+    <target name="generate-sources" >
+    </target>
+
+    <target name="compile-for-dist" >
+        <!-- Initialize target directories -->
+        <init-target />
+
+        <!-- Compile Source -->
+        <compile-sources />
+
+        <!-- Bundle Jars -->
+        <bundle-jars dist="${Etch.support}" />
+
+        <!-- Update Jars -->
+        <update-jars dist="${Etch.dist}" support="${Etch.support}" />
+    </target>
+    
+    <target name="compile-for-clover" if="Clover.enabled" >
+
+        <echo message="Rebuilding with clover" />
+
+        <!-- initialize-clover -->
+        <initialize-clover suffix="etchutil" >
+            <fileset dir="${src}/main/java">
+                <include name="**/*.java" />
+            </fileset>
+            <testsources dir="${src}/test/java">
+                <include name="**/*.java" />
+            </testsources>
+        </initialize-clover>
+        
+        <!-- Initialize target directories -->
+        <init-target />
+        
+        <!-- Compile Source -->
+        <compile-sources />
+        
+        <!-- Bundle Jars -->
+        <bundle-jars dist="${Etch.clover-support}" />
+
+        <!-- Update Jars -->
+        <update-jars dist="${Etch.clover-dist}" support="${Etch.clover-support}" />
+
+    </target>
+    
+    <target name="do-build" depends="generate-sources,compile-for-dist,compile-for-clover" />
+
+    <!-- TEST TARGET -->
+    <target name="do-test">
+        
+        <!-- Run Unit Tests -->
+        <junit printsummary="yes" haltonfailure="no" dir="${classesDirectory}"
+            errorProperty="build.tests.fail" failureProperty="build.tests.fail">
+            <classpath>
+                <pathelement location="${classesDirectory}/main" />
+                <pathelement location="${classesDirectory}/test" />
+                <pathelement location="${Etch.dependency.junit.jar}"/>
+                <!-- TODO: remove if clover not available -->
+                <pathelement location="${Etch.dependency.clover.jar}"/>
+            </classpath>
+            <formatter type="xml"/>
+            <batchtest fork="true" todir="${testResultsDirectory}">
+                <fileset dir="${src}/test/java">
+                    <include name="**/*.java" />
+                    <exclude name="**/PerfBasics.java" />
+                    <exclude name="**/testXmlParser.java" />
+                    <exclude name="**/testJaxp.java" />
+                </fileset>
+            </batchtest>
+        </junit>
+    </target>
+
+    <!-- POSTBUILD TARGET -->
+    <target name="do-postbuild">
+    </target>
+
+    <target name="do-publish" if="build.tests.fail">
+        <!-- Set flag file if any tests failed -->
+        <touch file="${Etch.runtime.tests.fail}"/>
+    </target>
+
+</project>
diff --git a/util/src/main/java/org/apache/etch/util/AbstractStartable.java b/util/src/main/java/org/apache/etch/util/AbstractStartable.java
new file mode 100644
index 0000000..ea5c84b
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/AbstractStartable.java
@@ -0,0 +1,89 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * Generic implementation of Startable.
+ */
+abstract public class AbstractStartable implements Startable
+{
+	final public void start() throws Exception
+	{
+		synchronized (this)
+		{
+			if (isStarted())
+				throw new IllegalStateException( "is already started" );
+
+			started = true;
+		}
+		
+		try
+		{
+			start0();
+		}
+		catch ( Exception e )
+		{
+			stop();
+			throw e;
+		}
+	}
+
+	final public void stop() throws Exception
+	{
+		synchronized (this)
+		{
+			checkIsStarted();
+			setStopped();
+		}
+		stop0();
+	}
+	
+	/**
+	 * Signals (from a subclasser) that the startable has stopped.
+	 */
+	final protected void setStopped()
+	{
+		started = false;
+	}
+	
+	final public boolean isStarted()
+	{
+		return started;
+	}
+	
+	final public void checkIsStarted()
+	{
+		if (!isStarted())
+			throw new IllegalStateException( "is not started" );
+	}
+
+	private boolean started;
+	
+	/**
+	 * @throws Exception
+	 */
+	abstract protected void start0() throws Exception;
+	
+	/**
+	 * @throws Exception
+	 */
+	abstract protected void stop0() throws Exception;
+}
diff --git a/util/src/main/java/org/apache/etch/util/AlarmListener.java b/util/src/main/java/org/apache/etch/util/AlarmListener.java
new file mode 100644
index 0000000..39d0590
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/AlarmListener.java
@@ -0,0 +1,62 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * Classes wanting alarms must implement this interface to receive the
+ * alarm.
+ * 
+ * @see AlarmManager
+ */
+public interface AlarmListener
+{
+	/**
+	 * Reports that the listener's alarm went off.
+	 * 
+	 * @param manager the manager of the alarm.
+	 * 
+	 * @param state a bit of state for the listener.
+	 * 
+	 * @param due the time the alarm was set to go off. This is in the
+	 * time coordinates as returned by Timer.getNanos().
+	 * 
+	 * @return the positive or negative snooze time in ms for this alarm,
+	 * or 0 to shutoff the alarm. If a positive number is returned, it is
+	 * added to the current due time of the alarm to calculate the new
+	 * due time for the alarm. Thus there should be very little drift
+	 * in the frequency of the alarms (although there is some because
+	 * of system clock jitter).
+	 * 
+	 * If the system is very busy, or if the listeners are trying to
+	 * do too much, alarms may not be processed quickly enough and
+	 * calculated new due times will already be in the past. This is a
+	 * pathological condition which will spiral out of control if not
+	 * detected.
+	 * 
+	 * If a negative number is returned, it is subtracted from the current
+	 * value of Timer.getNanos() to calculate the new due time for the
+	 * alarm. (In this case, subtracting the negative number is the same
+	 * as adding the absolute value...)
+	 * 
+	 * @see Timer#getNanos()
+	 */
+	public int wakeup( AlarmManager manager, Object state, long due );
+}
diff --git a/util/src/main/java/org/apache/etch/util/AlarmManager.java b/util/src/main/java/org/apache/etch/util/AlarmManager.java
new file mode 100644
index 0000000..775e6af
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/AlarmManager.java
@@ -0,0 +1,570 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeSet;
+
+/**
+ * The alarm manager is used to implement alarms.
+ * 
+ * A listener desiring a wakeup call should add itself to the manager
+ * with the specified delay in milliseconds. The listener may be removed
+ * at any time. When the alarm goes off, the listener may reset or remove
+ * the alarm.
+ * 
+ * @see #add(AlarmListener, Object, int)
+ * @see #remove(AlarmListener)
+ */
+public class AlarmManager extends AbstractStartable implements Runnable
+{
+	/**
+	 * Adds the listener to the set of those getting wakeup calls.
+	 * 
+	 * Note: uses the statically configured Alarm.
+	 * 
+	 * @param listener the target of the wakeup call.
+	 * 
+	 * @param state a bit of state for the listener.
+	 * 
+	 * @param delay the positive delay in milliseconds before the wakeup call.
+	 * 
+	 * @see #add(AlarmListener, Object, int)
+	 * @see #getAlarmManager(boolean)
+	 */
+	public static void staticAdd( AlarmListener listener, Object state, int delay )
+	{
+		getAlarmManager( true ).add( listener, state, delay );
+	}
+	
+	/**
+	 * Removes the listener from the set of those getting wakeup calls.
+	 * 
+	 * Note: uses the statically configured Alarm.
+	 * 
+	 * @param listener the target of the wakeup call.
+	 * 
+	 * @see #remove(AlarmListener)
+	 */
+	public static void staticRemove( AlarmListener listener )
+	{
+		AlarmManager am = getAlarmManager( false );
+		if (am != null)
+			am.remove( listener );
+	}
+	
+	/**
+	 * Gets the statically configured alarm manager, creating one if
+	 * specified and none exists.
+	 * @param startIt if true, we really need one and if there isn't
+	 * one then one should be started, otherwise one should not be
+	 * started.
+	 * @return the statically configured alarm manager, or a newly
+	 * created one if there is none.
+	 */
+	public static AlarmManager getAlarmManager( boolean startIt )
+	{
+		if (alarmManager == null)
+		{
+			synchronized (alarmManagerSync)
+			{
+				if (alarmManager == null)
+				{
+					if (!startIt)
+						return null;
+
+					AlarmManager am = new AlarmManager();
+					try
+					{
+						am.start();
+					}
+					catch ( RuntimeException e )
+					{
+						throw e;
+					}
+					catch ( Exception e )
+					{
+						throw new RuntimeException( "caught exception", e );
+					}
+					alarmManager = am;
+				}
+			}
+		}
+		return alarmManager;
+	}
+	
+	/**
+	 * Sets the statically configured alarm manager, returning the old one
+	 * if any. Don't forget to stop the old one.
+	 * @param newAlarmManager a new AlarmManager to be statically available.
+	 * @return the old statically available AlarmManager.
+	 */
+	public static AlarmManager setAlarmManager( AlarmManager newAlarmManager )
+	{
+		synchronized (alarmManagerSync)
+		{
+			AlarmManager oldAlarmManager = alarmManager;
+			alarmManager = newAlarmManager;
+			return oldAlarmManager;
+		}
+	}
+	
+	private static AlarmManager alarmManager;
+	
+	private final static Object alarmManagerSync = new Object();
+	
+	/**
+	 * Constructs the AlarmManager.
+	 * @param nWorkers the number of worker threads to create to process
+	 * wakeups. Must be > 0 and < 100.
+	 */
+	public AlarmManager( int nWorkers )
+	{
+		if (nWorkers <= 0 || nWorkers >= 100)
+			throw new IllegalArgumentException( "nWorkers <= 0 || nWorkers >= 100" );
+		
+		this.nWorkers = nWorkers;
+	}
+	
+	/**
+	 * Constructs the AlarmManager with the default number of
+	 * workers.
+	 * @see #DEFAULT_NWORKERS
+	 */
+	public AlarmManager()
+	{
+		this( DEFAULT_NWORKERS );
+	}
+	
+	private final int nWorkers;
+	
+	/**
+	 * The default number of worker threads (1).
+	 */
+	public final static int DEFAULT_NWORKERS = 1;
+
+	@Override
+	protected void start0() throws Exception
+	{
+		clearAlarms();
+		clearQueue();
+		
+		worker = new Thread[nWorkers];
+		for (int i = 0; i < nWorkers; i++)
+		{
+			worker[i] = new Thread( this, "AlarmManager worker thread "+i );
+			worker[i].start();
+		}
+	}
+	
+	private Thread[] worker;
+
+	@Override
+	protected void stop0() throws InterruptedException
+	{
+		clearAlarms();
+		clearQueue();
+		
+		synchronized (this)
+		{
+			notifyAll();
+		}
+		
+		for (int i = 0; i < nWorkers; i++)
+		{
+			if (worker[i] != null)
+			{
+				worker[i].join();
+				worker[i] = null;
+			}
+		}
+	}
+	
+	/**
+	 * Adds the listener to the set of those getting wakeup calls. If the
+	 * listener is already scheduled for a wakeup call, the schedule is
+	 * adjusted. There can only be one outstanding wakeup call per listener.
+	 * 
+	 * This method is thread safe.
+	 * 
+	 * @param listener the target of the wakeup call.
+	 * 
+	 * @param state a bit of state for the listener.
+	 * 
+	 * @param delay the positive delay in milliseconds before the wakeup call.
+	 * 
+	 * @throws IllegalArgumentException if the delay is less than or equal to
+	 * 0.
+	 */
+	public synchronized void add( AlarmListener listener, Object state, int delay )
+	{
+		if (listener == null)
+			throw new NullPointerException( "listener == null" );
+		
+		if (delay <= 0)
+			throw new IllegalArgumentException( "delay <= 0" );
+		
+		checkIsStarted();
+		
+		long due = Timer.getNanos() + delay * Timer.NANOS_PER_MILLI;
+		
+		Alarm alarm = getAlarm( listener );
+		if (alarm != null)
+		{
+			// schedule is being adjusted
+			dequeue( alarm );
+			alarm.setDue( due );
+			alarm.setState( state );
+			enqueue( alarm );
+		}
+		else
+		{
+			alarm = new Alarm( listener, state, due );
+			addAlarm( listener, alarm );
+			enqueue( alarm );
+		}
+		
+		notifyWorker( "add" );
+	}
+
+	private synchronized void update( Alarm alarm, int delay )
+	{
+		long due = delay > 0
+			? alarm.getDue() + delay * Timer.NANOS_PER_MILLI
+			: Timer.getNanos() - delay * Timer.NANOS_PER_MILLI;
+		
+		alarm.setDue( due );
+		enqueue( alarm );
+		notifyWorker( "update" );
+	}
+	
+	/**
+	 * Removes any scheduled wakeup call for this listener.
+	 * 
+	 * This method is thread safe.
+	 * 
+	 * @param listener the target of the wakeup call.
+	 */
+	public synchronized void remove( AlarmListener listener )
+	{
+		checkIsStarted();
+		
+		Alarm alarm = removeAlarm( listener );
+		if (alarm != null)
+		{
+			dequeue( alarm );
+			notifyWorker( "remove" );
+		}
+	}
+	
+	private synchronized void remove( Alarm alarm )
+	{
+		removeAlarm( alarm.listener );
+	}
+	
+	private void wakeup( Alarm alarm )
+	{
+		try
+		{
+			int delay = alarm.listener.wakeup( this, alarm.getState(), alarm.getDue() );
+			if (delay != 0)
+				update( alarm, delay );
+			else
+				remove( alarm );
+		}
+		catch ( Exception e )
+		{
+			remove( alarm );
+			report( e );
+		}
+	}
+	
+	private Alarm getNextDueAlarm()
+	{
+		// ok, the worker needs to get the next due alarm and
+		// then wait until its due time, then return it. if alerted
+		// by notifyWorker, it should refresh the next due alarm.
+		// one trick will be in excluding multiple workers from
+		// coming in here at the same time.
+		synchronized (getNextDueAlarmSync)
+		{
+			synchronized (this)
+			{
+				while (true)
+				{
+					if (!isStarted())
+						return null;
+					
+					Alarm alarm = getFirst();
+					
+					if (alarm == null)
+					{
+						try
+						{
+							wait( Long.MAX_VALUE );
+							continue;
+						}
+						catch ( InterruptedException e )
+						{
+							return null;
+						}
+					}
+					
+					long delayNs = alarm.getDue() - Timer.getNanos();
+					if (delayNs > 0)
+					{
+						try
+						{
+							long delay = delayNs / Timer.NANOS_PER_MILLI;
+							if (delay > 0)
+								wait( delay );
+							continue;
+						}
+						catch ( InterruptedException e )
+						{
+							return null;
+						}
+					}
+					
+					// the alarm being returned has not been removed
+					// from alarmsByListener. it is presumed that the
+					// alarm will be set again. if not, it should be
+					// removed.
+					
+					dequeue( alarm );
+					return alarm;
+				}
+			}
+		}
+	}
+
+	private final Object getNextDueAlarmSync = new Object();
+	
+	private void notifyWorker( String reason )
+	{
+		// the set of alarms has changed.
+		notify();
+	}
+	
+	public void run()
+	{
+		try
+		{
+			Alarm alarm;
+			while ((alarm = getNextDueAlarm()) != null)
+			{
+				wakeup( alarm );
+			}
+		}
+		catch ( RuntimeException e )
+		{
+			report( e );
+		}
+	}
+	
+	private void report( Exception e )
+	{
+		e.printStackTrace();
+	}
+
+	////////////////////////
+	// ALARMS BY LISTENER //
+	////////////////////////
+	
+	private Alarm getAlarm( AlarmListener listener )
+	{
+		return alarmsByListener.get( listener );
+	}
+	
+	private void addAlarm( AlarmListener listener, Alarm alarm )
+	{
+		alarmsByListener.put( listener, alarm );
+	}
+	
+	private Alarm removeAlarm( AlarmListener listener )
+	{
+		return alarmsByListener.remove( listener );
+	}
+	
+	private void clearAlarms()
+	{
+		alarmsByListener.clear();
+	}
+	
+	private final Map<AlarmListener,Alarm> alarmsByListener = new HashMap<AlarmListener,Alarm>();
+
+	////////////////////////
+	// ALARMS BY DUE TIME //
+	////////////////////////
+	
+	private Alarm getFirst()
+	{
+		if (alarms.isEmpty())
+			return null;
+		
+		return alarms.first();
+	}
+	
+	private void enqueue( Alarm alarm )
+	{
+		alarms.add( alarm );
+	}
+
+	private void dequeue( Alarm alarm )
+	{
+		alarms.remove( alarm );
+	}
+	
+	private void clearQueue()
+	{
+		alarms.clear();
+	}
+	
+	private final TreeSet<Alarm> alarms = new TreeSet<Alarm>();
+	
+	/////////////
+	// CLASSES //
+	/////////////
+
+	private final static class Alarm implements Comparable<Alarm>
+	{
+		/**
+		 * @param listener the target of the wakeup call.
+		 * @param state a bit of state for the listener.
+		 * @param due the absolute due time for the alarm.
+		 */
+		Alarm( AlarmListener listener, Object state, long due )
+		{
+			this.listener = listener;
+			this.state = state;
+			this.due = due;
+		}
+		
+		/**
+		 * @return the state for the listener.
+		 */
+		Object getState()
+		{
+			return state;
+		}
+		
+		/**
+		 * @param state a new bit of state for the listener.
+		 */
+		void setState( Object state )
+		{
+			this.state = state;
+		}
+
+		/**
+		 * @return the time the alarm is due.
+		 */
+		long getDue()
+		{
+			return due;
+		}
+
+		/**
+		 * @param due
+		 */
+		void setDue( long due )
+		{
+			this.due = due;
+		}
+
+		@Override
+		public int hashCode()
+		{
+			return (int) (due ^ due >>> 32 ^ seq ^ seq >>> 32);
+		}
+
+		@Override
+		public boolean equals( Object obj )
+		{
+			if (obj == this)
+				return true;
+			
+			if (obj == null)
+				return false;
+			
+			if (obj.getClass() != Alarm.class)
+				return false;
+			
+			Alarm other = (Alarm) obj;
+			
+			return due == other.due && seq == other.seq;
+		}
+
+		public int compareTo( Alarm other )
+		{
+			if (due < other.due)
+				return -1;
+			
+			if (due > other.due)
+				return 1;
+			
+			// due time is the same for both, now we need to
+			// compare the seq.
+			
+			if (seq < other.seq)
+				return -1;
+			
+			if (seq > other.seq)
+				return 1;
+			
+			return 0;
+		}
+		
+		/**
+		 * The listener for wakeup events.
+		 */
+		final AlarmListener listener;
+		
+		/**
+		 * Just a bit of state for the listener.
+		 */
+		private Object state;
+		
+		/**
+		 * The time the alarm is due.
+		 */
+		private long due;
+		
+		/**
+		 * A unique for all reasonable time sequence number.
+		 */
+		private final long seq = idGen.next();
+		
+		private final static IdGenerator idGen = new IdGenerator();
+	}
+
+	/**
+	 * Shuts down the default alarm manager if there is one.
+	 * @throws Exception
+	 */
+	public static void shutdown() throws Exception
+	{
+		AlarmManager am = setAlarmManager( null );
+		if (am != null)
+			am.stop();
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/ArrayIterator.java b/util/src/main/java/org/apache/etch/util/ArrayIterator.java
new file mode 100644
index 0000000..0ec4238
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/ArrayIterator.java
@@ -0,0 +1,71 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import java.lang.reflect.Array;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Iterator over a generic array.
+ */
+public class ArrayIterator implements Iterator<Object>
+{
+	/**
+	 * Constructs the ArrayIterator.
+	 * @param array
+	 */
+	public ArrayIterator( Object array )
+	{
+		if (array == null)
+			throw new NullPointerException( "array == null" );
+		
+		if (!array.getClass().isArray())
+			throw new IllegalArgumentException( "!array.getClass().isArray()" );
+		
+		this.array = array;
+		length = Array.getLength( array );
+	}
+	
+	private final Object array;
+	
+	private final int length;
+	
+	private int index = 0;
+	
+	public boolean hasNext()
+	{
+		return index < length;
+	}
+
+	public Object next()
+	{
+		if (!hasNext())
+			throw new NoSuchElementException();
+		
+		return Array.get( array, index++ );
+	}
+
+	public void remove()
+	{
+		throw new UnsupportedOperationException();
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/Assertion.java b/util/src/main/java/org/apache/etch/util/Assertion.java
new file mode 100644
index 0000000..f85c5c7
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/Assertion.java
@@ -0,0 +1,64 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * Portable assertion checking.
+ */
+public class Assertion
+{
+	/**
+	 * Checks a value for being true and if not it throws an exception
+	 * with the specified description in the message.
+	 * 
+	 * @param value a boolean value which should be true (e.g., x < 100 ).
+	 * 
+	 * @param msg a description of value (e.g., "x < 100" ).
+	 * 
+	 * @throws AssertionException when value is not true.
+	 */
+	public static void check( boolean value, String msg )
+		throws AssertionException
+	{
+		if (!value)
+			throw new AssertionException( "assertion failed: "+msg );
+	}
+
+	/**
+	 * Checks a value for being true and if not it throws an exception
+	 * with the specified description in the message.
+	 * 
+	 * @param value a boolean value which should be true (e.g., x < 100 ).
+	 * 
+	 * @param fmt a description of value (e.g., "x (%d) < 100" ).
+	 * 
+	 * @param args args for the format.
+	 * 
+	 * @throws AssertionException when value is not true.
+	 */
+	public static void check( boolean value, String fmt, Object ... args )
+		throws AssertionException
+	{
+		if (!value)
+			throw new AssertionException( "assertion failed: "+
+				String.format( fmt, args ) );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/AssertionException.java b/util/src/main/java/org/apache/etch/util/AssertionException.java
new file mode 100644
index 0000000..7cc46c4
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/AssertionException.java
@@ -0,0 +1,44 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * Exception thrown upon assertion failure.
+ * 
+ * @see Assertion#check(boolean, String, Object[])
+ */
+public class AssertionException extends RuntimeException
+{
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 3545520603445735478L;
+
+	/**
+	 * Constructs an assertion exception.
+	 * 
+	 * @param message describes the failure.
+	 */
+	public AssertionException( String message )
+	{
+		super( message );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/ByteBuffer.java b/util/src/main/java/org/apache/etch/util/ByteBuffer.java
new file mode 100644
index 0000000..c62aef6
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/ByteBuffer.java
@@ -0,0 +1,200 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import java.io.EOFException;
+import java.nio.BufferOverflowException;
+
+/**
+ * Byte buffer with operation to support getting and putting
+ * bytes.
+ */
+abstract public class ByteBuffer
+{
+	/**
+	 * @return true if the buffer is empty.
+	 */
+	public boolean isEmpty()
+	{
+		return length() == 0;
+	}
+
+	/**
+	 * @return true if the buffer is full.
+	 */
+	public boolean isFull()
+	{
+		return length() == size();
+	}
+	
+	/**
+	 * @return the amount of data the buffer can hold.
+	 */
+	abstract public int size();
+	
+	/**
+	 * @return the amount of data in the buffer.
+	 */
+	abstract public int length();
+	
+	/**
+	 * @return the next byte from the buffer.
+	 * @throws EOFException if the buffer is empty.
+	 */
+	abstract public byte get() throws EOFException;
+	
+	/**
+	 * Gets bytes from the buffer to fill buf.
+	 * @param buf
+	 * @return the length of data put into buf.
+	 */
+	public int get( byte[] buf )
+	{
+		return get( buf, 0, buf.length );
+	}
+	
+	/**
+	 * Gets bytes from the buffer to fill buf, starting at the specified
+	 * position for the specified length.
+	 * @param buf
+	 * @param off
+	 * @param len
+	 * @return the length of data put into buf.
+	 */
+	public int get( byte[] buf, int off, int len )
+	{
+		if (off < 0)
+			throw new IllegalArgumentException( "off < 0" );
+		
+		if (len < 0)
+			throw new IllegalArgumentException( "len < 0" );
+		
+		if (off+len > buf.length)
+			throw new IllegalArgumentException( "off+len > buf.length" );
+		
+		if (len == 0)
+			return 0;
+
+		int count = 0;
+		try
+		{
+			while (len > 0)
+			{
+				buf[off] = get();
+				count++;
+				off++;
+				len--;
+			}
+		}
+		catch ( EOFException e )
+		{
+			// nothing to do.
+		}
+		return count;
+	}
+	
+	/**
+	 * Puts a byte into the buffer.
+	 * @param b
+	 * @throws BufferOverflowException if the buffer is full
+	 */
+	abstract public void put( byte b ) throws BufferOverflowException;
+	
+	/**
+	 * Puts the bytes from buf into the buffer.
+	 * @param buf
+	 * @return the amount of data copied into the buffer.
+	 */
+	public int put( byte[] buf )
+	{
+		return put( buf, 0, buf.length );
+	}
+	
+	/**
+	 * Puts the bytes from buf into the buffer, starting at the specified
+	 * position for the specified length;
+	 * @param buf
+	 * @param off
+	 * @param len
+	 * @return the amount of data copied into the buffer.
+	 */
+	public int put( byte[] buf, int off, int len )
+	{
+		if (off < 0)
+			throw new IllegalArgumentException( "off < 0" );
+		
+		if (len < 0)
+			throw new IllegalArgumentException( "len < 0" );
+		
+		if (off+len > buf.length)
+			throw new IllegalArgumentException( "off+len > buf.length" );
+		
+		if (len == 0)
+			return 0;
+		
+		int count = 0;
+		try
+		{
+			while (len > 0)
+			{
+				put( buf[off] );
+				count++;
+				off++;
+				len--;
+			}
+		}
+		catch ( BufferOverflowException e )
+		{
+			// nothing to do.
+		}
+		return count;
+	}
+	
+	/**
+	 * Clears the buffer.
+	 */
+	abstract public void clear();
+	
+	/**
+	 * @return a little-endian 32-bit integer from the buffer.
+	 * @throws EOFException
+	 */
+	public int getInt() throws EOFException
+	{
+		int b0 = get() & 255;
+		int b1 = get() & 255;
+		int b2 = get() & 255;
+		int b3 = get() & 255;
+		return b0 | b1 << 8 | b2 << 16 | b3 << 24;
+	}
+	
+	/**
+	 * Puts a little-endian 32-bit integer into the buffer.
+	 * @param x
+	 */
+	public void putInt( int x )
+	{
+		put( (byte) x );
+		put( (byte) (x >>> 8) );
+		put( (byte) (x >>> 16) );
+		put( (byte) (x >>> 24) );
+	}
+}
\ No newline at end of file
diff --git a/util/src/main/java/org/apache/etch/util/CharIterator.java b/util/src/main/java/org/apache/etch/util/CharIterator.java
new file mode 100644
index 0000000..49c8ad7
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/CharIterator.java
@@ -0,0 +1,58 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * @author wert
+ */
+public class CharIterator
+{
+	/**
+	 * @param s
+	 */
+	public CharIterator( String s )
+	{
+		this.s = s;
+		n = s.length();
+	}
+	
+	private final String s;
+	
+	private final int n;
+	
+	private int i;
+
+	/**
+	 * @return true if there are more chars.
+	 */
+	public boolean hasNext()
+	{
+		return i < n;
+	}
+
+	/**
+	 * @return the next character in sequence.
+	 */
+	public char next()
+	{
+		return s.charAt( i++ );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/CircularByteBuffer.java b/util/src/main/java/org/apache/etch/util/CircularByteBuffer.java
new file mode 100644
index 0000000..71f7f3b
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/CircularByteBuffer.java
@@ -0,0 +1,96 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import java.io.EOFException;
+import java.nio.BufferOverflowException;
+
+/**
+ * Description of CircularByteBuffer.
+ */
+public class CircularByteBuffer extends ByteBuffer
+{
+	/**
+	 * Constructs the CircularByteBuffer.
+	 *
+	 * @param size
+	 */
+	public CircularByteBuffer( int size )
+	{
+		this.size = size;
+		buf = new byte[size];
+	}
+	
+	private final int size;
+	
+	private final byte[] buf;
+	
+	private int length;
+	
+	private int nextGet;
+	
+	private int nextPut;
+	
+	@Override
+	public int size()
+	{
+		return size;
+	}
+	
+	@Override
+	public int length()
+	{
+		return length;
+	}
+	
+	@Override
+	public void clear()
+	{
+		length = 0;
+		nextGet = 0;
+		nextPut = 0;
+	}
+
+	@Override
+	public byte get() throws EOFException
+	{
+		if (isEmpty())
+			throw new EOFException();
+		
+		length--;
+		byte b = buf[nextGet++];
+		if (nextGet >= size)
+			nextGet = 0;
+		return b;
+	}
+
+	@Override
+	public void put( byte b ) throws BufferOverflowException
+	{
+		if (isFull())
+			throw new BufferOverflowException();
+		
+		length++;
+		buf[nextPut++] = b;
+		if (nextPut >= size)
+			nextPut = 0;
+	}
+}
\ No newline at end of file
diff --git a/util/src/main/java/org/apache/etch/util/CircularQueue.java b/util/src/main/java/org/apache/etch/util/CircularQueue.java
new file mode 100644
index 0000000..7239aaf
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/CircularQueue.java
@@ -0,0 +1,380 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * A circular queue of a fixed size. Elements are added to one
+ * end and removed from the other, with the queue size ranging
+ * from empty to full. Operations can optionally wait until
+ * finished or return status indicating success or failure.
+ * For instance, adding to a full queue can wait until an item
+ * is removed before adding the new item or it can wait only
+ * a specified amount of time before completing successfully
+ * or giving up.
+ * @param <T> the type of items in the queue.
+ */
+public final class CircularQueue<T>
+{
+	/**
+	 * Constructs the CircularQueue.
+	 *
+	 * @param size the maximum number of items allowed in the queue.
+	 */
+	public CircularQueue( int size )
+	{
+		if (size < 1)
+			throw new IllegalArgumentException( "size < 1" );
+		
+		this.size = size;
+		items = new Object[size];
+	}
+	
+	/**
+	 * Constructs the CircularQueue with the maximum number of items
+	 * defaulted to 10.
+	 */
+	public CircularQueue()
+	{
+		this( 10 );
+	}
+
+	private final int size;
+	
+	private final Object[] items;
+	
+	/**
+	 * @return the maximum number of items that may be put in the queue.
+	 */
+	public int size()
+	{
+		return size;
+	}
+
+	/////////////////////
+	// BASIC QUEUE OPS //
+	/////////////////////
+	
+	/**
+	 * @return the current number of items in the queue.
+	 */
+	public int count()
+	{
+		return count;
+	}
+	
+	/**
+	 * @return true if the queue is empty.
+	 */
+	public boolean isEmpty()
+	{
+		return count == 0;
+	}
+	
+	/**
+	 * @return true if the queue is full.
+	 */
+	public boolean isFull()
+	{
+		return count == size;
+	}
+	
+	/**
+	 * Gets the item at the head of the queue.
+	 * @return the item at the head of the queue.
+	 */
+	private Object get0()
+	{
+		Assertion.check( count > 0, "count > 0" );
+		
+		Object obj = items[head];
+		
+		Assertion.check( obj != null, "obj != null" );
+		
+		items[head] = null;
+		
+		count--;
+		head++;
+		
+		if (head == size)
+			head = 0;
+		
+		return obj;
+	}
+	
+	/**
+	 * Puts the item at the tail of the queue.
+	 * @param obj non-null item to put.
+	 */
+	private void put0( Object obj )
+	{
+		Assertion.check( obj != null, "obj != null" );
+		Assertion.check( count < size, "count < size" );
+		Assertion.check( items[tail] == null, "items[tail] == null" );
+		
+		items[tail] = obj;
+		
+		count++;
+		tail++;
+		
+		if (tail == size)
+			tail = 0;
+	}
+	
+	private int count;
+	
+	private int head;
+	
+	private int tail;
+
+	//////////////////////
+	// PUBLIC QUEUE OPS //
+	//////////////////////
+	
+	/**
+	 * Gets the next available item from the queue, waiting
+	 * until an item is available or the queue is closed.
+	 * 
+	 * @return an item from the queue or null if the queue
+	 * is closed.
+	 * 
+	 * @throws InterruptedException if the thread is interrupted.
+	 */
+	public T get() throws InterruptedException
+	{
+		return get( 0 );
+	}
+	
+	/**
+	 * Gets the next available item from the queue, waiting
+	 * until an item is available or the queue is closed.
+	 * 
+	 * @param maxDelay the maximum time in ms to wait for
+	 * something to be put in the queue; 0 means wait forever,
+	 * less than 0 means don't wait at all.
+	 * 
+	 * @return an item from the queue or null if maxDelay
+	 * has been exceeded or the queue is closed.
+	 * 
+	 * @throws InterruptedException if the thread is interrupted.
+	 */
+	public synchronized T get( int maxDelay ) throws InterruptedException
+	{
+		if (!isEmpty())
+			return getAndNotify();
+		
+		// the queue is empty.
+		
+		if (isClosed() || maxDelay < 0)
+			return null;
+		
+		// the queue is empty, not closed, and caller has requested a delay...
+		
+		long now = Timer.getNanos();
+		long end = getEndTime( now, maxDelay );
+		Assertion.check( end > now, "end > now" );
+		
+		long d;
+		while ((d = (end - now) / Timer.NANOS_PER_MILLI) > 0)
+		{
+			// the queue is empty, not closed, and delay has not run out...
+			
+			Assertion.check( isEmpty(), "isEmpty()" );
+			Assertion.check( !isClosed(), "!isClosed()" );
+			Assertion.check( d > 0, "d > 0" );
+			
+			wait( d );
+			
+			if (!isEmpty())
+				return getAndNotify();
+			
+			if (isClosed())
+				return null;
+			
+			now = Timer.getNanos();
+		}
+		
+		return null;
+	}
+
+	/**
+	 * Puts an item in the queue, waiting until space is available
+	 * or the queue is closed.
+	 * 
+	 * @param obj a non-null item to put in the queue.
+	 * 
+	 * @return true if the item was placed in the queue
+	 * or false if the queue is closed.
+	 * 
+	 * @throws InterruptedException if the thread is interrupted.
+	 */
+	public boolean put( T obj ) throws InterruptedException
+	{
+		return put( obj, 0 );
+	}
+	
+	/**
+	 * Puts an item in the queue, waiting until space is available
+	 * or the queue is closed.
+	 * 
+	 * @param obj a non-null item to put in the queue.
+	 * 
+	 * @param maxDelay the maximum time in ms to wait for
+	 * available space the queue; 0 means wait forever,
+	 * less than 0 means don't wait at all.
+	 * 
+	 * @return true if the item was placed in the queue
+	 * or false if maxDelay has been exceeded or the queue
+	 * is closed.
+	 * 
+	 * @throws InterruptedException if the thread is interrupted.
+	 */
+	public synchronized boolean put( T obj, int maxDelay ) throws InterruptedException
+	{
+		if (obj == null)
+			throw new NullPointerException( "obj == null" );
+		
+		if (isClosed())
+			return false;
+		
+		// the queue is not closed.
+		
+		if (!isFull())
+		{
+			putAndNotify( obj );
+			return true;
+		}
+		
+		// the queue is full and not closed.
+		
+		if (maxDelay < 0)
+			return false;
+		
+		// the queue is full, not closed, and the caller has requested a delay...
+		
+		long now = Timer.getNanos();
+		long end = getEndTime( now, maxDelay );
+		Assertion.check( end > now, "end > now" );
+		
+		long d;
+		while ((d = (end - now) / Timer.NANOS_PER_MILLI) > 0)
+		{
+			// the queue is full, not closed, and delay has not run out...
+			
+			Assertion.check( isFull(), "isFull()" );
+			Assertion.check( !isClosed(), "!isClosed()" );
+			Assertion.check( d > 0, "d > 0" );
+			
+			wait( d );
+			
+			if (isClosed())
+				return false;
+			
+			// the queue is not closed.
+			
+			if (!isFull())
+			{
+				putAndNotify( obj );
+				return true;
+			}
+			
+			now = Timer.getNanos();
+		}
+		
+		return false;
+	}
+
+	/**
+	 * Closes the queue so that no more items may be put into it.
+	 * Get will return null when there are no more items to return.
+	 */
+	public synchronized void close()
+	{
+		if (!closed)
+		{
+			closed = true;
+			notifyAll();
+		}
+	}
+	
+	/**
+	 * @return true if the queue is closed.
+	 */
+	public boolean isClosed()
+	{
+		return closed;
+	}
+	
+	private boolean closed;
+	
+	//////////////////
+	// PRIVATE OPS //
+	//////////////////
+	
+	/**
+	 * Gets the item at the head of the queue. Additionally, wakes
+	 * up the next one waiting for the queue, either to get or put.
+	 * @return the item at the head of the queue.
+	 */
+	@SuppressWarnings("unchecked")
+	private T getAndNotify()
+	{
+		// the queue is now not empty.
+		
+		// putters waiting should be notified if the queue is now full.
+		boolean notify = isFull();
+		
+		Object obj = get0();
+		
+		// getters waiting should be notified if the queue is now not empty.
+		notify = notify || !isEmpty();
+		
+		if (notify)
+			notify();
+		
+		return (T) obj;
+	}
+	
+	/**
+	 * Puts the item at the tail of the queue. Additionally, wakes
+	 * up the next one waiting for the queue, either to get or put.
+	 * @param obj non-null item to put.
+	 */
+	private void putAndNotify( T obj )
+	{
+		// the queue is now not full.
+		
+		// getters waiting should be notified if the queue is now empty.
+		boolean notify = isEmpty();
+		
+		put0( obj );
+		
+		// putters waiting should be notified if the queue is now not full.
+		notify = notify || !isFull();
+		
+		if (notify)
+			notify();
+	}
+
+	private long getEndTime( long now, int maxDelay )
+	{
+		return maxDelay > 0 ? now + maxDelay * Timer.NANOS_PER_MILLI : Long.MAX_VALUE;
+	}
+}
\ No newline at end of file
diff --git a/util/src/main/java/org/apache/etch/util/EmptyIterator.java b/util/src/main/java/org/apache/etch/util/EmptyIterator.java
new file mode 100644
index 0000000..235e94a
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/EmptyIterator.java
@@ -0,0 +1,60 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * @param <E>
+ * @author wert
+ */
+public class EmptyIterator<E> implements Iterator<E>
+{
+	/* (non-Javadoc)
+	 * @see java.util.Iterator#hasNext()
+	 */
+	public boolean hasNext()
+	{
+		return false;
+	}
+
+	/* (non-Javadoc)
+	 * @see java.util.Iterator#next()
+	 */
+	public E next()
+	{
+		throw new NoSuchElementException();
+	}
+
+	/* (non-Javadoc)
+	 * @see java.util.Iterator#remove()
+	 */
+	public void remove()
+	{
+		throw new IllegalStateException();
+	}
+
+	/**
+	 * An empty iterator to use when you need it.
+	 */
+	public final static Iterator<Object> EMPTY_ITERATOR = new EmptyIterator<Object>();
+}
diff --git a/util/src/main/java/org/apache/etch/util/FlexBuffer.java b/util/src/main/java/org/apache/etch/util/FlexBuffer.java
new file mode 100644
index 0000000..238aa65
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/FlexBuffer.java
@@ -0,0 +1,755 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import java.io.EOFException;
+import java.io.IOException;
+
+/**
+ * A FlexBuffer wraps a byte array and manages the active region of
+ * it (0..length). It also supports dynamically extending the buffer
+ * as needed.
+ * 
+ * A FlexBuffer also has an index (read or write cursor). The various
+ * get and put operations always occur at the current index, with the
+ * index adjusted appropriately afterward. Get will not move index past
+ * length. If put needs to move index past length, length is also
+ * adjusted. This may cause the byte array to be re-allocated to a
+ * larger size.
+ */
+public final class FlexBuffer
+{
+	/**
+	 * Constructs a FlexBuffer with internal buffer and index and length of 0.
+	 */
+	public FlexBuffer()
+	{
+		this( new byte[INIT_BUFFER_LEN], 0, 0 );
+	}
+
+	/**
+	 * Constructs the FlexBuffer out of an existing buffer, ready to
+	 * read, with the index set to 0 and length set to buffer.length.
+	 * The buffer is adopted, not copied. If you want to copy, use
+	 * one of the put methods instead.
+	 * 
+	 * Note: this is the same as FlexBuffer( buffer, 0, buffer.length ).
+	 *
+	 * @param buffer the buffer to adopt.
+	 * 
+	 * @see #put(byte[])
+	 */
+	public FlexBuffer( byte[] buffer )
+	{
+		this( buffer, 0, buffer.length );
+	}
+	
+	/**
+	 * Constructs the FlexBuffer out of an existing buffer, ready to
+	 * read, with the index set to 0 and the specified length. The
+	 * buffer is adopted, not copied. If you want to copy, use one
+	 * of the put methods instead.
+	 * 
+	 * Note: this is the same as FlexBuffer( buffer, 0, length ).
+	 *
+	 * @param buffer the buffer to adopt.
+	 * 
+	 * @param length the length of the data in the buffer (index is
+	 * presumed to be 0).
+	 * 
+	 * @see #put(byte[], int, int)
+	 */
+	public FlexBuffer( byte[] buffer, int length )
+	{
+		this( buffer, 0, length );
+	}
+	
+	/**
+	 * Constructs the FlexBuffer out of an existing buffer, ready to
+	 * read, with the specified index and length. The buffer is adopted,
+	 * not copied. If you want to copy, use one of the put methods
+	 * instead.
+	 * 
+	 * Note: if you want to start off writing to the end of the buffer
+	 * and not reading it, specify index as the place to start writing,
+	 * and length as the amount of data that is valid after index (which
+	 * might reasonably be 0).
+	 *
+	 * @param buffer the buffer to adopt.
+	 * 
+	 * @param index the place to start reading or writing.
+	 * 
+	 * @param length the length of the valid data in the buffer,
+	 * starting at index.
+	 * 
+	 * @see #put(byte[], int, int)
+	 */
+	public FlexBuffer( byte[] buffer, int index, int length )
+	{
+		if (buffer == null)
+			throw new NullPointerException( "buffer == null" );
+		
+		if (index < 0)
+			throw new IllegalArgumentException( "index < 0" );
+		
+		if (length < 0)
+			throw new IllegalArgumentException( "length < 0" );
+		
+		if (index+length > buffer.length)
+			throw new IllegalArgumentException( "index+length > buffer.length" );
+		
+		this.buffer = buffer;
+		this.index = index;
+		this.length = index+length;
+	}
+
+	/**
+	 * @return the current byte array. Might change if any operation
+	 * needs to extend length past the end of the array.
+	 */
+	final public byte[] getBuf()
+	{
+		return buffer;
+	}
+	
+	final private void ensureLength( int len ) throws IOException
+	{
+		int n = buffer.length;
+		if (len <= n)
+			return;
+		
+		// the buffer is not big enough, we have to expand it.
+		
+		int k = n;
+		if (k < INIT_BUFFER_LEN)
+			k = INIT_BUFFER_LEN;
+		
+		while (len > k && k < MAX_BUFFER_LEN)
+			k = k << 1;
+		
+		if (len > k)
+			throw new IOException( "buffer overflow" );
+		
+		byte[] b = new byte[k];
+		System.arraycopy( buffer, 0, b, 0, n );
+		buffer = b;
+	}
+	
+	private byte[] buffer;
+	
+	private final static int INIT_BUFFER_LEN = 32;
+	
+	private final static int TRIM_BUFFER_LEN = 16*1024;
+	
+	private final static int MAX_BUFFER_LEN = 4*1024*1024;
+
+	/**
+	 * @return the current value of length. This is the last
+	 * index of valid data in the buffer.
+	 */
+	final public int length()
+	{
+		return length;
+	}
+
+	/**
+	 * @param length the new value of length. Length must be >= 0.
+	 * If length < index, index is also set to length. If length
+	 * is larger than the current buffer, the buffer is expanded.
+	 * @return this flex buffer object.
+	 * @throws IllegalArgumentException if length < 0.
+	 * @throws IOException if the buffer overflows its max length.
+	 */
+	final public FlexBuffer setLength( int length ) throws IllegalArgumentException, IOException
+	{
+		if (length < 0)
+			throw new IllegalArgumentException( "length < 0" );
+		
+		ensureLength( length );
+		
+		this.length = length;
+		
+		if (index > length)
+			index = length;
+		
+		return this;
+	}
+
+	private int length;
+	
+	/**
+	 * @return the current value of index.
+	 */
+	final public int index()
+	{
+		return index;
+	}
+	
+	/**
+	 * @param index the new value of index. Index must be >= 0.
+	 * @return this flex buffer object.
+	 * @throws IllegalArgumentException if index < 0 or if index > length.
+	 */
+	final public FlexBuffer setIndex( int index ) throws IllegalArgumentException
+	{
+		if (index < 0 || index > length)
+			throw new IllegalArgumentException( "index < 0 || index > length" );
+		
+		this.index = index;
+		
+		return this;
+	}
+	
+	private int index;
+
+	/**
+	 * @return length() - index(). Result is always >= 0. This is the amount
+	 * of data that could be read using the various forms of get. It doesn't
+	 * really mean anything in relation to put.
+	 */
+	final public int avail()
+	{
+		return length - index;
+	}
+
+	/**
+	 * Sets both index and length to 0. Trims the buffer length if it is past
+	 * the recommended limit.
+	 * 
+	 * Shorthand for setLength( 0 ).
+	 * 
+	 * @return this flex buffer object.
+	 */
+	final public FlexBuffer reset()
+	{
+		index = 0;
+		length = 0;
+		
+		if (buffer.length > TRIM_BUFFER_LEN)
+			buffer = new byte[TRIM_BUFFER_LEN];
+		
+		return this;
+	}
+
+	/**
+	 * Compacts the buffer by moving remaining data (from index to length)
+	 * to the front of the buffer. Sets index to 0, and sets length to
+	 * avail (before index was changed).
+	 * 
+	 * @return this flex buffer object.
+	 */
+	final public FlexBuffer compact()
+	{
+		if (index == 0)
+			return this;
+		
+		int n = avail();
+		if (n == 0)
+		{
+			reset();
+			return this;
+		}
+		
+		System.arraycopy( buffer, index, buffer, 0, n );
+		
+		index = 0;
+		length = n;
+		
+		return this;
+	}
+	
+	/**
+	 * @return the unsigned byte value at index, and adjusts index
+	 * by adding one.
+	 * @throws IOException if avail() < 1.
+	 */
+	final public int get() throws IOException
+	{
+		checkAvail( 1 );
+		
+		return buffer[index++] & 255;
+	}
+	
+	/**
+	 * Copies data from the byte array to buf as if by repeated
+	 * calls to get().
+	 * @param buf a buffer to receive the data. At most
+	 * min( buf.length, avail() ) bytes are transferred.
+	 * @return the amount of data transferred.
+	 * @throws IOException if avail() < 1.
+	 */
+	final public int get( byte[] buf ) throws IOException
+	{
+		return get( buf, 0, buf.length );
+	}
+	
+	/**
+	 * Copies data from the byte array to buf as if by repeated
+	 * calls to get().
+	 * @param buf a buffer to receive the data. At most
+	 * min( len, avail() ) bytes are transferred, starting
+	 * at off.
+	 * @param off the index in buf to receive the data.
+	 * Off must be >= 0 && <= buf.length.
+	 * @param len the max amount of data to transfer. Len
+	 * must be >= 0 and <= buf.length - off.
+	 * @return the amount of data transferred.
+	 * @throws IOException if avail() < 1
+	 */
+	final public int get( byte[] buf, int off, int len ) throws IOException
+	{
+		checkBuf( buf, off, len );
+		
+		if (len == 0)
+			return 0;
+		
+		checkAvail( 1 );
+		
+		int n = Math.min( len, avail() );
+		
+		System.arraycopy( buffer, index, buf, off, n );
+		index += n;
+		
+		return n;
+	}
+
+	/**
+	 * @return the next available byte.
+	 * @throws IOException if avail() < 1.
+	 */
+	final public byte getByte() throws IOException
+    {
+		checkAvail( 1 );
+		
+		return buffer[index++];
+	}
+	
+	private final static boolean littleEndian = false;
+
+	/**
+	 * @return a short composed from the next 2 bytes. Little-endian.
+	 * @throws IOException if avail() < 2.
+	 */
+	final public short getShort() throws IOException
+    {
+		checkAvail( 2 );
+
+		if (littleEndian)
+		{
+			// little-endian
+			int value = buffer[index++] & 255;
+			return (short) (value + ((buffer[index++] & 255) << 8));
+		}
+		
+		// big-endian
+		int value = buffer[index++];
+		return (short) ((value << 8) + (buffer[index++] & 255));
+    }
+	
+	/**
+	 * @return an int composed from the next 4 bytes. Little-endian.
+	 * @throws IOException if avail() < 4.
+	 */
+	final public int getInt() throws IOException
+	{
+		checkAvail( 4 );
+
+		if (littleEndian)
+		{
+			// little-endian
+			int value = buffer[index++] & 255;
+			value += (buffer[index++] & 255) << 8;
+			value += (buffer[index++] & 255) << 16;
+			return value + ((buffer[index++] & 255) << 24);
+		}
+		
+		// big-endian
+		int value = buffer[index++];
+		value = (value << 8) + (buffer[index++] & 255);
+		value = (value << 8) + (buffer[index++] & 255);
+		return (value << 8) + (buffer[index++] & 255);
+	}
+
+	/**
+	 * @return a long composed from the next 8 bytes. Little-endian.
+	 * @throws IOException if avail() < 8.
+	 */
+	final public long getLong() throws IOException
+    {
+		checkAvail( 8 );
+
+		if (littleEndian)
+		{
+			// little-endian
+			long value = buffer[index++] & 255;
+			value += (long)(buffer[index++] & 255) << 8;
+			value += (long)(buffer[index++] & 255) << 16;
+			value += (long)(buffer[index++] & 255) << 24;
+			value += (long)(buffer[index++] & 255) << 32;
+			value += (long)(buffer[index++] & 255) << 40;
+			value += (long)(buffer[index++] & 255) << 48;
+			return value + ((long)(buffer[index++] & 255) << 56);
+		}
+		
+		// big-endian
+		long value = buffer[index++];
+		value = (value << 8) + (buffer[index++] & 255);
+		value = (value << 8) + (buffer[index++] & 255);
+		value = (value << 8) + (buffer[index++] & 255);
+		value = (value << 8) + (buffer[index++] & 255);
+		value = (value << 8) + (buffer[index++] & 255);
+		value = (value << 8) + (buffer[index++] & 255);
+		return (value << 8) + (buffer[index++] & 255);
+    }
+
+	/**
+	 * @return a float from the next available bytes.
+	 * @throws IOException if avail() < 4.
+	 */
+	final public float getFloat() throws IOException
+    {
+		return Float.intBitsToFloat( getInt() );
+    }
+
+	/**
+	 * @return a double from the next available bytes.
+	 * @throws IOException if avail() < 8.
+	 */
+	final public double getDouble() throws IOException
+    {
+		return Double.longBitsToDouble( getLong() );
+    }
+
+	/**
+	 * Fills a buffer fully from the next available bytes.
+	 * @param b
+	 * @throws IOException if avail() < b.length.
+	 */
+	final public void getFully( byte[] b ) throws IOException
+    {
+	    checkAvail( b.length );
+	    int n = get( b, 0, b.length );
+	    assert n == b.length;
+    }
+	
+	/**
+	 * Puts a byte into the buffer at the current index,
+	 * then adjusts the index by one. Adjusts the length
+	 * as necessary. The buffer is expanded if needed.
+	 * @param b
+	 * @return this flex buffer object.
+	 * @throws IOException if the buffer overflows its max length.
+	 */
+	final public FlexBuffer put( int b ) throws IOException
+	{
+		ensureLength( index+1 );
+		buffer[index++] = (byte) b;
+		fixLength();
+		
+		return this;
+	}
+	
+	/**
+	 * Puts some bytes into the buffer as if by repeated
+	 * calls to put().
+	 * @param buf the source of the bytes to put. The entire
+	 * array of bytes is put.
+	 * @return this flex buffer object.
+	 * @throws IOException if the buffer overflows its max length.
+	 */
+	final public FlexBuffer put( byte[] buf ) throws IOException
+	{
+		return put( buf, 0, buf.length );
+	}
+	
+	/**
+	 * Puts some bytes into the buffer as if by repeated
+	 * calls to put().
+	 * @param buf the source of the bytes to put.
+	 * @param off the index to the first byte to put.
+	 * @param len the number of bytes to put.
+	 * @return this flex buffer object.
+	 * @throws IOException if the buffer overflows its max length.
+	 */
+	final public FlexBuffer put( byte[] buf, int off, int len ) throws IOException
+	{
+		checkBuf( buf, off, len );
+		
+		if (len == 0)
+			return this;
+		
+		ensureLength( index+len );
+		System.arraycopy( buf, off, buffer, index, len );
+		index += len;
+		fixLength();
+		
+		return this;
+	}
+
+	/**
+	 * Copies the available bytes from buf into buffer as if by
+	 * repeated execution of put( buf.get() ).
+	 * @param buf the source of the bytes to put. All available
+	 * bytes are copied.
+	 * @return this flex buffer object.
+	 * @throws IOException if the buffer overflows its max length.
+	 */
+	final public FlexBuffer put( FlexBuffer buf ) throws IOException
+	{
+		int n = buf.avail();
+		put( buf.buffer, buf.index, n );
+		buf.skip( n, false );
+		return this;
+	}
+
+	/**
+	 * Copies the specified number of bytes from buf into buffer
+	 * as if by repeated execution of put( buf.get() ).
+	 * @param buf the source of the bytes to put.
+	 * @param len the number of bytes to put. Len must be <=
+	 * buf.avail().
+	 * @return this flex buffer object.
+	 * @throws IOException if the buffer overflows its max length.
+	 */
+	final public FlexBuffer put( FlexBuffer buf, int len ) throws IOException
+	{
+		if (len > buf.avail())
+			throw new IllegalArgumentException( "len > buf.avail()" );
+		
+		put( buf.buffer, buf.index, len );
+		buf.skip( len, false );
+		return this;
+	}
+
+	/**
+	 * Puts the byte.
+	 * @param value
+	 * @throws IOException
+	 */
+	final public void putByte( byte value ) throws IOException
+    {
+		ensureLength( index+1 );
+		
+		buffer[index++] = value;
+		
+		fixLength();
+    }
+
+	/**
+	 * Puts the short as the next 2 bytes. Little-endian.
+	 * @param value
+	 * @throws IOException
+	 */
+	final public void putShort( short value ) throws IOException
+    {
+		ensureLength( index+2 );
+		
+		if (littleEndian)
+		{
+			buffer[index++] = (byte) value;
+			buffer[index++] = (byte) (value >> 8);
+		}
+		else
+		{
+			buffer[index++] = (byte) (value >>> 8);
+			buffer[index++] = (byte) value;
+		}
+		
+		fixLength();
+    }
+
+	/**
+	 * Puts the int as the next 4 bytes. Little-endian.
+	 * @param value
+	 * @throws IOException
+	 */
+	final public void putInt( int value ) throws IOException
+    {
+		ensureLength( index+4 );
+		
+		if (littleEndian)
+		{
+			buffer[index++] = (byte) value;
+			buffer[index++] = (byte) (value >> 8);
+			buffer[index++] = (byte) (value >> 16);
+			buffer[index++] = (byte) (value >> 24);
+		}
+		else
+		{
+			buffer[index++] = (byte) (value >>> 24);
+			buffer[index++] = (byte) (value >>> 16);
+			buffer[index++] = (byte) (value >>> 8);
+			buffer[index++] = (byte) value;
+		}
+		
+		fixLength();
+    }
+
+	/**
+	 * Puts the long as the next 8 bytes. Little-endian.
+	 * @param value
+	 * @throws IOException
+	 */
+	final public void putLong( long value ) throws IOException
+    {
+		ensureLength( index+8 );
+		
+		if (littleEndian)
+		{
+			buffer[index++] = (byte) value;
+			buffer[index++] = (byte) (value >> 8);
+			buffer[index++] = (byte) (value >> 16);
+			buffer[index++] = (byte) (value >> 24);
+			buffer[index++] = (byte) (value >> 32);
+			buffer[index++] = (byte) (value >> 40);
+			buffer[index++] = (byte) (value >> 48);
+			buffer[index++] = (byte) (value >> 56);
+		}
+		else
+		{
+			buffer[index++] = (byte) (value >>> 56);
+			buffer[index++] = (byte) (value >>> 48);
+			buffer[index++] = (byte) (value >>> 40);
+			buffer[index++] = (byte) (value >>> 32);
+			buffer[index++] = (byte) (value >>> 24);
+			buffer[index++] = (byte) (value >>> 16);
+			buffer[index++] = (byte) (value >>> 8);
+			buffer[index++] = (byte) value;
+		}
+		
+		fixLength();
+    }
+
+	/**
+	 * Puts the float as the next 4 bytes. Little-endian.
+	 * @param value
+	 * @throws IOException
+	 */
+	final public void putFloat( float value ) throws IOException
+    {
+		putInt( Float.floatToIntBits( value ) );
+    }
+
+	/**
+	 * Puts the double as the next 8 bytes. Little-endian.
+	 * @param value
+	 * @throws IOException
+	 */
+	final public void putDouble( double value ) throws IOException
+    {
+		putLong( Double.doubleToLongBits( value ) );
+    }
+
+	/**
+	 * Adjusts index as if by a get or put but without transferring
+	 * any data. This could be used to skip over a data item in an
+	 * input or output buffer.
+	 * 
+	 * @param len the number of bytes to skip over. Len must be
+	 * >= 0. If put is false, it is an error if len > avail().
+	 * If put is true, the buffer may be extended (and the buffer
+	 * length adjusted).
+	 * 
+	 * @param put if true it is ok to extend the length of the
+	 * buffer.
+	 * 
+	 * @return this flex buffer object.
+	 * 
+	 * @throws EOFException if put is false and len > avail().
+	 * 
+	 * @throws IOException if the max buffer size is exceeded.
+	 */
+	final public FlexBuffer skip( int len, boolean put ) throws IOException
+	{
+		if (len < 0)
+			throw new IllegalArgumentException( "len < 0" );
+		
+		if (len == 0)
+			return this;
+		
+		if (put)
+		{
+			ensureLength( index+len );
+			index += len;
+			fixLength();
+			return this;
+		}
+		
+		checkAvail( len );
+		
+		index += len;
+		
+		return this;
+	}
+
+	/**
+	 * If index has moved past length during a put, then adjust length
+	 * to track index.
+	 */
+	final private void fixLength()
+	{
+		if (index > length)
+			length = index;
+	}
+
+	/**
+	 * Checks buf, off, and len for being reasonable.
+	 * @param buf
+	 * @param off
+	 * @param len
+	 */
+	final private void checkBuf( byte[] buf, int off, int len )
+	{
+		if (buf == null)
+			throw new NullPointerException( "buf == null" );
+		
+		if (off < 0 || off > buf.length)
+			throw new IllegalArgumentException( "off < 0 || off > buf.length" );
+		
+		if (len < 0)
+			throw new IllegalArgumentException( "len < 0" );
+		
+		if (off+len > buf.length)
+			throw new IllegalArgumentException( "off+len > buf.length" );
+	}
+
+	/**
+	 * @return the currently available bytes.
+	 * @throws IOException
+	 */
+	final public byte[] getAvailBytes() throws IOException
+	{
+		byte[] buf = new byte[avail()];
+		get( buf );
+		return buf;
+	}
+	
+	/**
+	 * Checks that there are enough bytes to for a read.
+	 * @param len the length required by a read operation.
+	 * @throws EOFException if len > avail().
+	 */
+	final private void checkAvail( int len ) throws IOException
+	{
+		if (len > avail())
+			throw new EOFException( "len > avail()" );
+	}
+}
\ No newline at end of file
diff --git a/util/src/main/java/org/apache/etch/util/Hash.java b/util/src/main/java/org/apache/etch/util/Hash.java
new file mode 100644
index 0000000..d90ab36
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/Hash.java
@@ -0,0 +1,50 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * A pretty cool hash function which has few collisions.
+ */
+public class Hash
+{
+    /**
+     * Computes the hash value of the name to be used as the id when
+     * constructing an IdName.
+     * @param name the name of the type or field.
+     * @return a hash of name in the unicode character encoding which is
+     * very likely to be unique over reasonable name spaces. Collisions
+     * should be very unlikely as they will force the user to change the
+     * name.
+     */
+    public static int hash( String name )
+    {
+    	// combination of djb2 and sdbm hash algorithm:
+        int hash = 5381;
+        int n = name.length();
+        for (int i = 0; i < n; i++)
+        {
+        	char c = name.charAt( i );
+        	int h6 = hash << 6;
+        	hash = (h6 << 10) + h6 - hash + c;
+        }
+        return hash;
+    }
+}
diff --git a/util/src/main/java/org/apache/etch/util/IdGenerator.java b/util/src/main/java/org/apache/etch/util/IdGenerator.java
new file mode 100644
index 0000000..86180e0
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/IdGenerator.java
@@ -0,0 +1,76 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * Synchronously generates long id numbers.
+ */
+final public class IdGenerator
+{
+	/**
+	 * Constructs the IdGenerator with the default starting point of 1
+	 * and the default stride of 1.
+	 */
+	public IdGenerator()
+	{
+		this( 1, 1 );
+	}
+	
+	/**
+	 * Constructs the IdGenerator with the specified starting point
+	 * and the default stride of 1.
+	 *
+	 * @param nextId
+	 */
+	public IdGenerator( long nextId )
+	{
+		this( nextId, 1 );
+	}
+	
+	/**
+	 * Constructs the IdGenerator with the specified starting point
+	 * and the specified stride;
+	 * @param nextId
+	 * @param stride
+	 */
+	public IdGenerator( long nextId, int stride )
+	{
+		if (stride <= 0)
+			throw new IllegalArgumentException( "stride <= 0" );
+		
+		this.nextId = nextId;
+		this.stride = stride;
+	}
+	
+	private long nextId;
+	
+	private final int stride;
+	
+	/**
+	 * @return the next id in sequence.
+	 */
+	public synchronized long next()
+	{
+		long id = nextId;
+		nextId += stride;
+		return id;
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/IntCounter.java b/util/src/main/java/org/apache/etch/util/IntCounter.java
new file mode 100644
index 0000000..b26d5aa
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/IntCounter.java
@@ -0,0 +1,48 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * A safe integer counter.
+ */
+public class IntCounter
+{
+	/**
+	 * Adjusts the value of the counter by k.
+	 * @param k the adjustment to the counter.
+	 * @return the new value of the counter.
+	 */
+	public synchronized int adjust( int k )
+    {
+        value += k;
+        return value;
+    }
+
+	/**
+	 * @return the value of the counter.
+	 */
+	public int get()
+    {
+        return value;
+    }
+	
+	private int value;
+}
\ No newline at end of file
diff --git a/util/src/main/java/org/apache/etch/util/Log.java b/util/src/main/java/org/apache/etch/util/Log.java
new file mode 100644
index 0000000..d11025b
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/Log.java
@@ -0,0 +1,1758 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * Log implements a standardized reporting mechanism for named
+ * events which get reported to a variety of sinks in a variety
+ * of formats.
+ * 
+ * NOTE: Log.report is not a substitute for System.out.printf.
+ * 
+ * Example:
+ * 
+ * Log.report( "SystemUp", "time", new Date() );
+ * 
+ * The event is "SystemUp", and there is one additional parameter
+ * named "time" which has a value of the current date/time.
+ * 
+ * Under the hood, the event is used to select a Template,
+ * which then controls how the event is handled. The template
+ * knows the importance of the event, perhaps how the event
+ * is formatted, etc. It is done this way to minimize how much
+ * work is done until it is time to actually do something with
+ * the log entry. For example, if the log entry is not important
+ * enough, it will be ignored. Any work done to format it will be
+ * wasted effort. Furthermore, a preformmated log entry cannot be
+ * localized.
+ */
+public class Log
+{
+	private Log()
+	{
+		// cannot create an instance of this class.
+	}
+
+	/////////////////////////
+	// DEFAULT DATE FORMAT //
+	/////////////////////////
+	
+	/**
+	 * The default date format used by entry formatters.
+	 */
+	public static DateFormat defaultDateFormat
+		= new SimpleDateFormat( "HH:mm:ss.SSS" );
+	
+	///////////////
+	// TEMPLATES //
+	///////////////
+
+	/**
+	 * Registers the template, making it globally available. It isn't necessary
+	 * to register a template to use it directly, but Log.report only works
+	 * with registered templates.
+	 * 
+	 * @param template the template to register.
+	 * 
+	 * @return the template that was registered.
+	 * 
+	 * @throws IllegalArgumentException if the template name has already
+	 * been registered.
+	 */
+	public static Template register( Template template )
+	{
+		synchronized (templates)
+		{
+			if (hasTemplate( template.getName() ))
+				throw new IllegalArgumentException(
+					"template '"+template.getName()+"' already registered" );
+			addTemplate( template );
+		}
+		
+		synchronized (template)
+		{
+			sync( template );
+		}
+		
+		return template;
+	}
+
+	/**
+	 * Creates a template for an event and registers it all in one step.
+	 * 
+	 * @param name the name of the event.
+	 * @param category the category of the event.
+	 * @param enable flag which allows reporting of the event.
+	 * @param fields the list of fields of the event.
+	 * 
+	 * @return the template that was created and registered.
+	 * 
+	 * @throws IllegalArgumentException if the template name has already
+	 * been registered.
+	 */
+	public static Template register( String name, Category category,
+			boolean enable, String ... fields )
+		{
+			return register( new Template( name, category, enable, Template.UNLIMITED_ENTRIES, fields ) );
+		}
+		
+	/**
+	 * Register and set log entry limit
+	 * @param name
+	 * @param category
+	 * @param enable
+	 * @param limit
+	 * @param fields
+	 * @return the template that was created and registered.
+	 */
+	public static Template register( String name, Category category,
+		boolean enable, int limit, String ... fields )
+	{
+		return register( new Template( name, category, enable, limit, fields ) );
+	}
+	
+	/**
+	 * @param name the name of the event.
+	 * @return true if the named template exists.
+	 */
+	public static boolean hasTemplate( String name )
+	{
+		return templates.containsKey( name );
+	}
+
+	private static void addTemplate( Template template )
+	{
+		templates.put( template.getName(), template );
+	}
+	
+	private static Template getTemplate0( String name )
+	{
+		return templates.get( name );
+	}
+	
+	/**
+	 * @param name the name of the event.
+	 * 
+	 * @param register flag determines if a newly created template
+	 * will be registered or not. The template should not be registered
+	 * if the "name" of the event is really an already formatted string
+	 * which should not be remembered. this might happen if legacy logging
+	 * or tracing code is being converted (e.g., by changing calls to
+	 * System.out.println() into Log.report().
+	 * 
+	 * @param defCat the default category if the template does not
+	 * exist.
+	 * 
+	 * @param defEnable the default enable if the template does not
+	 * exist.
+	 * 
+	 * @return the template with the specified name if registed, or
+	 * a new template with specified name and default category and
+	 * enable. The new template may or may not be registered depending
+	 * up the value of the register parameter.
+	 * 
+	 * @see #getTemplate(String)
+	 */
+	public static Template getTemplate( String name, boolean register,
+		Category defCat, boolean defEnable )
+	{
+		Template template = getTemplate0( name );
+		if (template == null)
+		{
+			if (!register)
+				return new Template( name, defCat, defEnable, Template.UNLIMITED_ENTRIES );
+
+			synchronized (templates)
+			{
+				template = getTemplate0( name );
+				if (template == null)
+					template = register( name, defCat, defEnable );
+			}
+		}
+		return template;
+	}
+	
+	/**
+	 * @param name the name of the event.
+	 * 
+	 * @return the template with the specified name if registered, or
+	 * a new template with specified name and default category and
+	 * default enable. The new template may or may not be registered
+	 * depending upon the value of the allowAutoRegister global.
+	 * 
+	 * @see #getTemplate(String, boolean, Category, boolean)
+	 * @see #getAllowAutoRegister()
+	 * @see #getDefaultCategory()
+	 * @see #getDefaultEnable()
+	 * @see #getDefaultLimit()
+	 */
+	public static Template getTemplate( String name )
+	{
+		return getTemplate( name, getAllowAutoRegister(),
+			getDefaultCategory(), getDefaultEnable() );
+	}
+	
+	/**
+	 * @return the default enable flag for unknown events.
+	 */
+	public static boolean getDefaultEnable()
+	{
+		return defaultEnable;
+	}
+	
+	/**
+	 * @return the default limit for unknown events.
+	 */
+	public static int getDefaultLimit()
+	{
+		return defaultLimit;
+	}
+	
+	/**
+	 * @return the default category for unknown events.
+	 */
+	public static Category getDefaultCategory()
+	{
+		return defaultCategory;
+	}
+
+	/**
+	 * @return the value of the auto register flag, which controls
+	 * whether Log.report(name, ...) and Log.getTemplate(name) will
+	 * register a newly created template.
+	 */
+	public static boolean getAllowAutoRegister()
+	{
+		return allowAutoRegister;
+	}
+	
+	/**
+	 * Sets the value of the auto register flag.
+	 * 
+	 * @param value the new value of the auto register flag.
+	 * 
+	 * @see #getTemplate(String)
+	 */
+	public static void setAllowAutoRegister( boolean value )
+	{
+		allowAutoRegister = value;
+	}
+	
+	private static boolean allowAutoRegister = true;
+	
+	private static Category defaultCategory = Category.Debug;
+	
+	private static boolean defaultEnable = true;
+	
+	private static int defaultLimit = Template.UNLIMITED_ENTRIES;
+	
+	private final static Map<String, Template> templates =
+		Collections.synchronizedMap( new HashMap<String, Template>() );
+
+	///////////
+	// SINKS //
+	///////////
+
+	/**
+	 * Adds the specified sink to the set of sinks which
+	 * desire notification of events.
+	 * @param sink
+	 */
+	public static void addSink( Sink sink )
+	{
+		if (sink == null)
+		{
+			// HACK: this is special hack that adds a default
+			// log sink which prints to standard out. But we
+			// only want one, so while a nullSink is active,
+			// don't add another.
+
+			if (nullSink != null)
+				return;
+			
+			nullSink = sink = new Sink()
+			{
+				public synchronized void start()
+				{
+					checkIsStarted();
+					started = true;
+					sync( this );
+				}
+
+				public boolean isStarted()
+				{
+					return started;
+				}
+
+				public boolean hasInterest( Template template )
+				{
+					return started;
+				}
+				
+				public synchronized void report( Entry entry )
+				{
+					System.out.println( entry );
+				}
+
+				public synchronized void stop()
+				{
+					started = false;
+					sync( this );
+				}
+				
+				private boolean started = true;
+
+				public String getName()
+				{
+					return null;
+				}
+
+				public void setAcceptCat( String tokenList )
+				{
+					// ignore.
+				}
+
+				public void setDenyCat( String tokenList )
+				{
+					// ignore.
+				}
+
+				public void setAcceptName( String tokenList )
+				{
+					// ignore.
+				}
+
+				public void setDenyName( String tokenList )
+				{
+					// ignore.
+				}
+
+				public void checkIsStarted()
+				{
+					if (started)
+						throw new IllegalStateException( "already started" );
+				}
+			};
+		}
+		
+		synchronized (sink)
+		{
+			if (sinks.add( sink ))
+				sync( sink );
+			
+			String name = sink.getName();
+			if (name != null)
+				sinksByName.put( name, sink );
+		}
+	}
+	
+	private static Sink nullSink;
+	
+	/**
+	 * Removes the specified sink from the set of sinks which
+	 * desire notification of events.
+	 * @param sink
+	 */
+	public static void removeSink( Sink sink )
+	{
+		synchronized (sink)
+		{
+			if (sinks.remove( sink ))
+				sync( sink );
+			
+			String name = sink.getName();
+			if (name != null)
+				sinksByName.remove( name );
+			
+			if (sink == nullSink)
+				nullSink = null;
+		}
+	}
+	
+	/**
+	 * @param name
+	 * @return the named sink or null.
+	 */
+	public static Sink findSink( String name )
+	{
+		return sinksByName.get( name );
+	}
+
+	/**
+	 * @param sink
+	 */
+	public static void sync( Sink sink )
+	{
+		// sink is synchronized.
+		
+		// the interests of this sink must be compared to all the
+		// templates. the list of templates must be frozen so that
+		// we are sure all templates are fairly considered. if a
+		// template is added or removed, a similar process is
+		// performed but freezing the sink list.
+		
+		boolean installed = sinks.contains( sink );
+		synchronized (templates)
+		{
+			for (Template template : templates.values())
+			{
+				if (installed && sink.hasInterest( template ))
+					template.addSink( sink );
+				else
+					template.removeSink( sink );
+			}
+		}
+	}
+	
+	/**
+	 * @param template
+	 */
+	public static void sync( Template template )
+	{
+		// template is synchronized at this point. templates
+		// are essentially immutable except for the enable
+		// flag.
+
+		if (!template.getEnable())
+		{
+			template.clearSinks();
+			return;
+		}
+		
+		synchronized (sinks)
+		{
+			for (Sink sink : sinks)
+			{
+				if (sink.hasInterest( template ))
+					template.addSink( sink );
+				else
+					template.removeSink( sink );
+			}
+		}
+	}
+	
+	private final static Set<Sink> sinks =
+		Collections.synchronizedSet( new HashSet<Sink>() );
+	
+	private final static Map<String, Sink> sinksByName =
+		Collections.synchronizedMap( new HashMap<String, Sink>() );
+	
+	/**
+	 * @return a list of the sinks.
+	 */
+	public static Sink[] getSinks()
+	{
+		synchronized (sinks)
+		{
+			return sinks.toArray( new Sink[sinks.size()] );
+		}
+	}
+	
+	///////////////////
+	// REPORT EVENTS //
+	///////////////////
+	
+	/**
+	 * Reports the named event with the specified parameters.
+	 * @param name the name of the event.
+	 * @param fieldValues a sequence of field/value pairs which are
+	 * parameters of the event.
+	 * @return the entry that was reported.
+	 */
+	public static Entry report( String name, Object ... fieldValues )
+	{
+		return newEntry( name, fieldValues ).report();
+	}
+	
+	/**
+	 * Creates a new entry for the named event with the specified
+	 * parameters.
+	 * @param name the name of the event.
+	 * @param fieldValues a sequence of field/value pairs which are
+	 * parameters of the event.
+	 * @return the entry that was created.
+	 */
+	public static Entry newEntry( String name, Object ... fieldValues )
+	{
+		return getTemplate( name ).newEntry( fieldValues );
+	}
+	
+	/**
+	 * Log entry id generator.
+	 */
+	final static IdGenerator entryIdGen = new IdGenerator( Timer.getNanos() );
+
+	/**
+	 * Standard way of attaching an exception to a log entry.
+	 */
+	public static final String EXCP = "excp";
+
+	//////////////////
+	// stack traces //
+	//////////////////
+	
+	/**
+	 * @param t
+	 * @return the string rep of the stack trace of the specified throwable.
+	 */
+	public static String getStackTrace( Throwable t )
+	{
+		StringWriter sw = new StringWriter();
+		PrintWriter pw = new PrintWriter( sw );
+		t.printStackTrace( pw );
+		return sw.toString().trim();
+	}
+
+	/////////////
+	// Classes //
+	/////////////
+	
+	/**
+	 * Categories of events. Category may be reported when the event is
+	 * logged, and sinks may use category to select events to be logged.
+	 */
+	public enum Category
+	{
+		/**
+		 * Very detailed info about a process.
+		 */
+		Verbose,
+		/**
+		 * General info about a process.
+		 */
+		Info,
+		/**
+		 * A warning about something that may not be right in a process.
+		 */
+		Warning,
+		/**
+		 * A report about an error in a process.
+		 */
+		Error,
+		/**
+		 * A debugging report about a process.
+		 */
+		Debug,
+		/**
+		 * An audit report from a process.
+		 */
+		Audit,
+		/**
+		 * A statistic report.
+		 */
+		Stat
+	}
+	
+	/**
+	 * A template for an event.
+	 */
+	final public static class Template
+	{
+		/**
+		 * Constructs the Template.
+		 *
+		 * @param name the name of the event.
+		 * @param category the category of the event.
+		 * @param enable flag which allows reporting of the event.
+		 * @param limit the limit on how many such messages per period
+		 * to allow.
+		 * @param fields the list of fields of the event.
+		 */
+		public Template( String name, Category category,
+			boolean enable, int limit, String ... fields )
+		{
+			this.name = name;
+			this.category = category;
+			this.limit = limit;
+			setEnable( enable );
+			addFields( fields );
+		}
+		
+		/**
+		 * Flag indicating unlimited entry rate.
+		 */
+		public static final int UNLIMITED_ENTRIES = -1;
+
+		private final String name;
+		
+		private final Category category;
+		
+		private int limit = UNLIMITED_ENTRIES;
+		
+		private int dropCount = 0;
+		
+		private int minuteCount = 0;
+		
+		private long lastNanos;
+								
+
+		/**
+		 * @return the name of this template.
+		 */
+		public String getName()
+		{
+			return name;
+		}
+		
+		/**
+		 * @return the category of this template.
+		 */
+		public Category getCategory()
+		{
+			return category;
+		}
+		
+		/**
+		 * @return entries per minutes
+		 */
+		public int getLimit()
+		{
+			return limit;
+		}
+		
+		/**
+		 * set log entries per minute
+		 * @param limit
+		 */
+		public void setLimit( int limit )
+		{
+			this.limit = limit;
+		}
+
+		/**
+		 * @return dropped entries count
+		 */
+		public int getDropCount()
+		{
+			return dropCount;
+		}
+		
+		/**
+		 * set drop count to 0
+		 */
+		public void resetDropCount()
+		{
+			dropCount = 0;
+		}
+				
+		////////////////
+		// ENABLEMENT //
+		////////////////
+		
+		/**
+		 * @return the enable flag of this template. If true, the
+		 * event will be reported to sinks that are interested. If
+		 * false, the event will not be reported no matter what.
+		 */
+		public boolean getEnable()
+		{
+			return enable;
+		}
+		
+		/**
+		 * Sets the enable flag of this template.
+		 * 
+		 * @param enable the enable flag of this template. If true, the
+		 * event will be reported to sinks that are interested. If
+		 * false, the event will not be reported no matter what.
+		 */
+		public synchronized void setEnable( boolean enable )
+		{
+			if (enable != this.enable)
+			{
+				this.enable = enable;
+				sync( this );
+			}
+			
+			if (isLimitedLogging())
+			{
+				lastNanos = Timer.getNanos();
+				dropCount = 0;
+				minuteCount = 0;
+			}
+		}
+		
+		private boolean enable = true;
+
+		////////////
+		// FIELDS //
+		////////////
+		
+		/**
+		 * @param field the field name.
+		 * @return true if this field is defined.
+		 */
+		public boolean hasField( String field )
+		{
+			return _fields.contains( field );
+		}
+		
+		/**
+		 * Adds the specified field to the template if it hasn't already
+		 * been added.
+		 * @param field the field name.
+		 * @return this template.
+		 */
+		public Template addField( String field )
+		{
+			synchronized (_fields)
+			{
+				if (!hasField( field ))
+				{
+					int id = _fields.size();
+					_fields.add( field );
+					fieldIds.put( field, id );
+				}
+			}
+			return this;
+		}
+		
+		/**
+		 * @param field the field name.
+		 * @param create flag which specifies that the field should be
+		 * created if it doesn't already exist.
+		 * @return the id of the specified field.
+		 */
+		public int getFieldId( String field, boolean create )
+		{
+			Integer id = fieldIds.get( field );
+			if (id == null)
+			{
+				if (!create)
+					return -1;
+				addField( field );
+				id = fieldIds.get( field );
+			}
+			return id;
+		}
+		
+		/**
+		 * @return the count of fields in the template.
+		 */
+		public int countFields()
+		{
+			return _fields.size();
+		}
+		
+		/**
+		 * @param fields a list of fields to add.
+		 * @return the template.
+		 */
+		public Template addFields( String ... fields )
+		{
+			for (String field: fields)
+				addField( field );
+			
+			return this;
+		}
+
+		/**
+		 * @return a list of the fields of the template.
+		 */
+		public String[] getFields()
+		{
+			synchronized (_fields)
+			{
+				return _fields.toArray( new String[_fields.size()] );
+			}
+		}
+		
+		private List<String> _fields =
+			Collections.synchronizedList( new ArrayList<String>() );
+		
+		private Map<String, Integer> fieldIds =
+			Collections.synchronizedMap( new HashMap<String, Integer>() );
+
+		///////////
+		// SINKS //
+		///////////
+		
+		/**
+		 * @return true if the event is enabled and there are any
+		 * sinks interested in the event.
+		 */
+		boolean isEnabled()
+		{
+			return enable && hasSinks();
+		}
+		
+		/**
+		 * @return true if there are any log sinks interested in this
+		 * template.
+		 */
+		private boolean hasSinks()
+		{
+			return !tsinks.isEmpty();
+		}
+
+		/**
+		 * Adds sink to the set of those notified when this
+		 * template generates an event.
+		 * @param sink
+		 */
+		void addSink( Sink sink )
+		{
+			synchronized (tsinks)
+			{
+				tsinks.add( sink );
+				sinksArray = null;
+			}
+		}
+
+		/**
+		 * Removes sink from the set of those notified when this
+		 * template generates an event.
+		 * @param sink
+		 */
+		void removeSink( Sink sink )
+		{
+			synchronized (tsinks)
+			{
+				tsinks.remove( sink );
+				sinksArray = null;
+			}
+		}
+
+		/**
+		 * Removes all the sinks.
+		 */
+		void clearSinks()
+		{
+			synchronized (tsinks)
+			{
+				tsinks.clear();
+				sinksArray = null;
+			}
+		}
+
+		/**
+		 * @return the list of sinks interested in this event.
+		 */
+		public Sink[] getSinks()
+		{
+			synchronized (tsinks)
+			{
+				if (sinksArray == null)
+					sinksArray = tsinks.toArray( new Sink[tsinks.size()] );
+				return sinksArray;
+			}
+		}
+		
+		private Set<Sink> tsinks = new HashSet<Sink>();
+		
+		private Sink[] sinksArray;
+
+		/////////////
+		// ENTRIES //
+		/////////////
+		
+		/**
+		 * Constructs a new entry for this event with the specified
+		 * parameter values. If the event is enabled and some sink
+		 * wants it, then a functional entry object is returned which
+		 * can be used to report the event. If the event is disabled
+		 * or no sink wants it, a dummy entry object is returned which
+		 * doesn't report anything.
+		 * 
+		 * @param fieldValues a sequence of field/value pairs which are
+		 * parameters of the event.
+		 * 
+		 * @return constructed entry object which is used to report
+		 * the event.
+		 * 
+		 * @see NormalEntry
+		 * @see DummyEntry
+		 */
+		public Entry newEntry( Object ... fieldValues )
+		{
+			synchronized (countSync)
+			{
+				count++;
+				
+				int k = fieldValues.length;
+				fieldValuesCount += k;
+				if (k == 0)
+					zeroFieldValuesCount++;
+			}
+			
+			if (isEnabled())
+			{
+				if (isLimitedLogging())
+				{
+					if (isLoggingTooFast())
+					{
+						dropCount++;
+						synchronized(countSync)
+						{
+							dummyCount++;
+						}
+						return new DummyEntry();
+					}
+					minuteCount++;
+				}
+				return new NormalEntry( this, fieldValues );
+			}
+			
+			synchronized (countSync)
+			{
+				dummyCount++;
+			}
+			
+			return new DummyEntry();
+		}
+
+		private boolean isLoggingTooFast()
+		{
+			if (!isLimitedLogging())
+				return false;	// logging is not limited.
+			
+			if (Timer.getSecondsSince(lastNanos) > 60)
+			{
+				// over a minute now, reset counters.
+				minuteCount = 0;
+				//dropCount = 0;
+				// reset time stamp.
+				lastNanos = Timer.getNanos();
+				
+				return false;
+			}
+			if (minuteCount < getLimit())
+			{
+				// still within limit.
+				return false;
+			}
+			
+			return true;
+		}
+
+		private boolean isLimitedLogging()
+		{
+			return limit != UNLIMITED_ENTRIES;
+		}
+	}
+	
+	/**
+	 * Count of log entries created.
+	 */
+	static int count;
+	
+	/**
+	 * Count of dummy log entries created.
+	 */
+	static int dummyCount;
+		
+	/**
+	 * Count of field value pairs reported.
+	 */
+	static int fieldValuesCount;
+	
+	/**
+	 * Description of zeroFieldValuesCount.
+	 */
+	static int zeroFieldValuesCount;
+	
+	/**
+	 * Synchronize access to counters.
+	 */
+	final static Object countSync = new Object();
+
+	private static final String LOG_STATS = "LogStats";
+
+	private static final String COUNT = "count";
+
+	private static final String DUMMY_COUNT = "dummyCount";
+	
+	private static final String FIELD_VALUES_COUNT = "fieldValuesCount";
+
+	private static final String ZERO_FIELD_VALUES_COUNT = "zeroFieldValuesCount";
+	
+	/**
+	 * Reports log stats.
+	 */
+	public static void reportLogStats()
+	{
+		synchronized (countSync)
+		{
+			Log.report( LOG_STATS,
+				COUNT, count,
+				DUMMY_COUNT, dummyCount,
+				FIELD_VALUES_COUNT, fieldValuesCount,
+				ZERO_FIELD_VALUES_COUNT, zeroFieldValuesCount);
+		}
+	}
+	
+	static
+	{
+		Log.register( LOG_STATS, Category.Stat, true,
+			COUNT, DUMMY_COUNT, FIELD_VALUES_COUNT, ZERO_FIELD_VALUES_COUNT );
+	}
+	
+	/**
+	 * Interface for log entries.
+	 */
+	public interface Entry
+	{
+		/**
+		 * @return the template for this entry.
+		 */
+		public Template getTemplate();
+		
+		/**
+		 * @return the timestamp for this entry. This is the
+		 * value returned by System.currentTimeMillis() when
+		 * the entry was created.
+		 */
+		public long getTimestamp();
+		
+		/**
+		 * @param field the field name.
+		 * @return true if the field is defined and has a value.
+		 */
+		public boolean hasField( String field );
+		
+		/**
+		 * @param field the field name.
+		 * @return the field's value (possibly null).
+		 */
+		public Object getField( String field );
+		
+		/**
+		 * Sets the value of the field.
+		 * @param field the field name.
+		 * @param value the field value, may be null.
+		 * @return this entry.
+		 */
+		public Entry setField( String field, Object value );
+		
+		/**
+		 * @return reports this entry to interested log sinks. An
+		 * entry id is assigned if the entry is actually going to
+		 * be reported to a sink.
+		 */
+		public Entry report();
+		
+		/**
+		 * Calls the FieldValueFormatter.format() method for each field
+		 * defined in the template (even those with null values).
+		 * 
+		 * @param formatter
+		 * @throws IOException
+		 */
+		public void formatFieldValues( FieldValueFormatter formatter )
+			throws IOException;
+		
+		/**
+		 * Converts entry to string value using standard date format.
+		 * @return string value of entry
+		 */
+		public String toString();
+		
+		/**
+		 * Converts entry to string value using standard date format.
+		 * @param brief
+		 * @return string value of entry
+		 */
+		public String toString( boolean brief );
+
+		/**
+		 * Converts entry to string using specified date format.
+		 * @param df
+		 * @return string value of entry
+		 */
+		public String toString( DateFormat df );
+
+		/**
+		 * Converts entry to string using specified date format.
+		 * @param brief
+		 * @param df
+		 * @return string value of entry
+		 */
+		public String toString( boolean brief, DateFormat df );
+		
+		/**
+		 * @param wtr
+		 * @throws IOException
+		 */
+		public void write( Writer wtr ) throws IOException;
+		
+		/**
+		 * @param wtr
+		 * @param brief
+		 * @throws IOException
+		 */
+		public void write( Writer wtr, boolean brief ) throws IOException;
+		
+		/**
+		 * @param wtr
+		 * @param df
+		 * @throws IOException
+		 */
+		public void write( Writer wtr, DateFormat df ) throws IOException;
+		
+		/**
+		 * @param wtr
+		 * @param brief
+		 * @param df
+		 * @throws IOException
+		 */
+		public void write( Writer wtr, boolean brief, DateFormat df ) throws IOException;
+		
+		/**
+		 * @return the id assigned to the entry when it was logged.
+		 * If the entry was not logged, returns 0.
+		 */
+		public long getEntryId();
+	}
+	
+	/**
+	 * Basic implementation of entry which includes support
+	 * for template and timestamp.
+	 */
+	abstract public static class AbstractEntry implements Entry
+	{
+		/**
+		 * Constructs the AbstractEntry with the specified template
+		 * and timestamp.
+		 *
+		 * @param template the template which created this entry.
+		 * @param timestamp the current value of System.currentTimeMillis();
+		 */
+		public AbstractEntry( Template template, long timestamp )
+		{
+			this.template = template;
+			this.timestamp = timestamp;
+		}
+		
+		private final Template template;
+		
+		private final long timestamp;
+
+		final public Template getTemplate()
+		{
+			return template;
+		}
+
+		final public long getTimestamp()
+		{
+			return timestamp;
+		}
+
+		@Override
+		final public String toString()
+		{
+			return toString( false, defaultDateFormat );
+		}
+
+		final public String toString( boolean brief )
+		{
+			return toString( brief, defaultDateFormat );
+		}
+
+		final public String toString( DateFormat df )
+		{
+			return toString( false, df );
+		}
+
+		final public String toString( boolean brief, DateFormat df )
+		{
+			try
+			{
+				StringWriter sw = new StringWriter();
+				write( sw, brief, df );
+				return sw.toString();
+			}
+			catch ( IOException e )
+			{
+				return "format failed, caught exception "+e;
+			}
+		}
+
+		final public void write( Writer wtr ) throws IOException
+		{
+			write( wtr, false, defaultDateFormat );
+		}
+
+		final public void write( Writer wtr, boolean brief ) throws IOException
+		{
+			write( wtr, brief, defaultDateFormat );
+		}
+
+		final public void write( final Writer wtr, DateFormat df ) throws IOException
+		{
+			write( wtr, false, df );
+		}
+	}
+	
+	/**
+	 * Dummy implementation of entry which doesn't do jack.
+	 * Returned by Template.newEntry when the event is disabled
+	 * or there is no interest in it.
+	 */
+	final public static class DummyEntry extends AbstractEntry
+	{
+		/**
+		 * Constructs the DummyEntry.
+		 */
+		public DummyEntry()
+		{
+			super( null, 0 );
+		}
+		
+		public boolean hasField( String field )
+		{
+			// ignore.
+			return false;
+		}
+		
+		public Object getField( String field )
+		{
+			// ignore.
+			return null;
+		}
+
+		public Entry setField( String field, Object value )
+		{
+			// ignore.
+			return this;
+		}
+
+		public Entry report()
+		{
+			// ignore.
+			return this;
+		}
+		
+		public long getEntryId()
+		{
+			// ignore.
+			return 0;
+		}
+
+		public void formatFieldValues( FieldValueFormatter formatter )
+		{
+			// ignore.
+		}
+
+		public void write( Writer wtr, boolean brief, DateFormat df ) throws IOException
+		{
+			wtr.write( "DummyEntry(" );
+			wtr.write( getTemplate().getName() );
+			wtr.write( ")" );
+		}
+	}
+	
+	/**
+	 * A normal implementation of entry which saves field values
+	 * and reports to sinks. Returned by Template.newEntry when
+	 * the event is enabled and there is interest in it.
+	 */
+	final public static class NormalEntry extends AbstractEntry
+	{
+		/**
+		 * Constructs the PlainEntry.
+		 *
+		 * @param template the template which created this entry.
+		 * @param fieldValues a sequence of field/value pairs which are
+		 * parameters of the event.
+		 */
+		public NormalEntry( Template template, Object ... fieldValues )
+		{
+			super( template, System.currentTimeMillis() );
+			fields = new Object[template.countFields()];
+			setFields( fieldValues );
+		}
+
+		////////////
+		// FIELDS //
+		////////////
+		
+		public boolean hasField( String field )
+		{
+			return hasField( getTemplate().getFieldId( field, false ) );
+		}
+		
+		public Object getField( String field )
+		{
+			return getField( getTemplate().getFieldId( field, false ) );
+		}
+
+		public Entry setField( String field, Object value )
+		{
+			return setField( getTemplate().getFieldId( field, true ), value );
+		}
+		
+		/**
+		 * @param fieldValues a sequence of field/value pairs which are
+		 * parameters of the event.
+		 * @return the entry.
+		 */
+		public Entry setFields( Object ... fieldValues )
+		{
+			if (fieldValues.length == 0)
+				return this;
+			
+			if (fieldValues.length % 2 != 0)
+				throw new IllegalArgumentException(
+					"fieldValues must be sequence of field/value pairs" );
+			
+			Iterator<Object> i = new ArrayIterator<Object>( fieldValues );
+			while (i.hasNext())
+			{
+				Object fieldObj = i.next();
+				Object valueObj = i.next();
+				
+				if (!(fieldObj instanceof String))
+					throw new IllegalArgumentException(
+						"field not a string: "+fieldObj );
+				
+				setField( (String) fieldObj, valueObj );
+			}
+			
+			return this;
+		}
+
+		////////////////
+		// FIELD IMPL //
+		////////////////
+		
+		private boolean hasField( int fid )
+		{
+			return getField( fid ) != null;
+		}
+		
+		private Object getField( int fid )
+		{
+			return fid >= 0 && fid < fields.length ? fields[fid] : null;
+		}
+		
+		private Entry setField( int fid, Object value )
+		{
+			if (fid >= fields.length)
+			{
+				Object[] newFields = new Object[getTemplate().countFields()];
+				System.arraycopy( fields, 0, newFields, 0, fields.length );
+				fields = newFields;
+			}
+			
+			fields[fid] = value;
+			
+			return this;
+		}
+		
+		private Object[] fields;
+
+		////////////
+		// REPORT //
+		////////////
+
+		public Entry report()
+		{
+			if (entryId != 0)
+				throw new IllegalStateException( "this entry already reported" );
+			
+			entryId = entryIdGen.next();
+			
+			for (Sink sink : getTemplate().getSinks())
+				sink.report( this );
+			
+			return this;
+		}
+
+		public void formatFieldValues( FieldValueFormatter formatter )
+			throws IOException
+		{
+			int i = 0;
+			for (String field : getTemplate().getFields())
+				formatter.format( field, getField( i++ ) );
+		}
+		
+		public long getEntryId()
+		{
+			return entryId;
+		}
+		
+		private long entryId;
+
+		////////////////
+		// FORMATTING //
+		////////////////
+		
+		public void write( final Writer wtr, boolean brief, DateFormat df ) throws IOException
+		{
+			if (!brief)
+			{
+				String ds;
+				synchronized (df)
+				{
+					ds = df.format( getTimestamp() );
+				}
+				wtr.write( ds );
+				wtr.write( " : " );
+				wtr.write( Long.toString( getEntryId() ) );
+				wtr.write( " : " );
+				wtr.write( getTemplate().getCategory().toString() );
+				wtr.write( " : " );
+				
+				// print out drop count
+				if ( getTemplate().getLimit() > Template.UNLIMITED_ENTRIES &&  getTemplate().getDropCount() > 0 )
+				{
+					wtr.write( "(" );
+					wtr.write( Integer.toString( getTemplate().getDropCount() ) );
+					wtr.write( ")" );
+					wtr.write( " : " );
+					
+					getTemplate().resetDropCount();
+				}
+			}
+						
+			wtr.write( getTemplate().getName() );
+			
+			formatFieldValues(
+				new FieldValueFormatter()
+				{
+					private boolean first = true;
+					public void format( String field, Object value )
+						throws IOException
+					{
+						if (value == null)
+							return;
+						
+						if (first)
+						{
+							wtr.write( " : " );
+							first = false;
+						}
+						else
+						{
+							wtr.write( "; " );
+						}
+						
+						wtr.write( field );
+						wtr.write( '=' );
+						if (value instanceof Throwable)
+							wtr.write( getStackTrace( (Throwable) value ) );
+						else
+							wtr.write( value.toString() );
+					}
+				} );
+			wtr.write( ';' );
+		}
+	}
+	
+	/**
+	 * Array iterator may be used to create an iterator over
+	 * an arbitrary array of a specified type.
+	 * @param <T> the type of the elements of the array.
+	 */
+	final public static class ArrayIterator<T> implements Iterator<T>
+	{
+		/**
+		 * Constructs the ArrayIterator.
+		 *
+		 * @param values the array of values to iterate over.
+		 */
+		public ArrayIterator( T[] values )
+		{
+			this.values = values;
+		}
+		
+		private T[] values;
+		
+		private int index;
+
+		public boolean hasNext()
+		{
+			return index < values.length;
+		}
+
+		public T next()
+		{
+			if (index >= values.length)
+				throw new NoSuchElementException();
+			
+			return values[index++];
+		}
+
+		public void remove()
+		{
+			throw new UnsupportedOperationException();
+		}
+	}
+	
+	/**
+	 * Interface for those interested in events.
+	 */
+	public interface Sink extends Startable
+	{
+		/**
+		 * Reports the specified event to the sink.
+		 * @param entry
+		 */
+		public void report( Entry entry );
+		
+		/**
+		 * @return the name of this sink (if it has one).
+		 */
+		public String getName();
+
+		/**
+		 * @param template
+		 * @return true if the sink has any interest in the template.
+		 */
+		public boolean hasInterest( Template template );
+		
+		/**
+		 * @param tokenList
+		 */
+		public void setAcceptCat( String tokenList );
+		
+		/**
+		 * @param tokenList
+		 */
+		public void setDenyCat( String tokenList );
+		
+		/**
+		 * @param tokenList
+		 */
+		public void setAcceptName( String tokenList );
+		
+		/**
+		 * @param tokenList
+		 */
+		public void setDenyName( String tokenList );
+	}
+	
+	/**
+	 * Interface for reporting field/value pairs in response to a
+	 * call to Entry.formatFieldValues().
+	 * 
+	 * @see Entry#formatFieldValues(FieldValueFormatter)
+	 */
+	public interface FieldValueFormatter
+	{
+		/**
+		 * @param field the field name.
+		 * @param value the field value, may be null.
+		 * @throws IOException
+		 */
+		public void format( String field, Object value ) throws IOException;
+	}
+	
+	/**
+	 * A combination interface of Sink and FieldValueFormatter.
+	 */
+	public interface SinkFieldValueFormatter extends Sink, FieldValueFormatter
+	{
+		// nothing else to add.
+	}
+
+	/**
+	 * Removes and stops all the sinks.
+	 */
+	public static void shutdown()
+	{
+		for (Sink sink : Log.getSinks())
+		{
+			Log.removeSink( sink );
+			try
+			{
+				sink.stop();
+			}
+			catch ( Exception e )
+			{
+				e.printStackTrace();
+			}
+		}
+	}
+
+	/**
+	 * @param name
+	 * @param fieldValues
+	 * @return an exception report using the log entry mechanism
+	 */
+	public static LogEntryException newException( String name, Object ... fieldValues )
+	{
+		return new LogEntryException( name, fieldValues );
+	}
+	
+	/**
+	 *
+	 */
+	public static class LogEntryException extends Exception implements Entry
+	{
+		/**
+		 * @param name
+		 * @param fieldValues
+		 */
+		public LogEntryException( String name, Object ... fieldValues )
+		{
+			Template t = Log.getTemplate( name, getAllowAutoRegister(), Category.Error, true );
+			entry = new NormalEntry( t, fieldValues );
+		}
+		
+		/**
+		 * @return the entry as reported.
+		 */
+		public LogEntryException report()
+		{
+			if (okToLog && entry.getTemplate().isEnabled())
+			{
+				okToLog = false;
+				entry.report();
+			}
+			return this;
+		}
+
+		/**
+		 * @param okToLog
+		 * @return this log entry exception.
+		 */
+		public LogEntryException setOkToLog( boolean okToLog )
+		{
+			this.okToLog = okToLog;
+			return this;
+		}
+		
+		private boolean okToLog = true;
+
+		@Override
+		public String getMessage()
+		{
+			return getMessage( false );
+		}
+		
+		/**
+		 * @param brief
+		 * @return a text form of the message.
+		 * @see #toString(boolean)
+		 */
+		public String getMessage( boolean brief )
+		{
+			return toString( brief );
+		}
+		
+		private final Entry entry;
+		
+		private static final long serialVersionUID = 1L;
+
+		///////////////////
+		// ENTRY METHODS //
+		///////////////////
+
+		public Template getTemplate()
+		{
+			return entry.getTemplate();
+		}
+
+		public long getTimestamp()
+		{
+			return entry.getTimestamp();
+		}
+
+		public boolean hasField( String field )
+		{
+			return entry.hasField( field );
+		}
+
+		public Object getField( String field )
+		{
+			return entry.getField( field );
+		}
+
+		public LogEntryException setField( String field, Object value )
+		{
+			entry.setField( field, value );
+			return this;
+		}
+
+		public void formatFieldValues( FieldValueFormatter formatter )
+			throws IOException
+		{
+			entry.formatFieldValues( formatter );
+		}
+
+		@Override
+		public String toString()
+		{
+			return toString( false );
+		}
+		
+		/**
+		 * @param brief
+		 * @return a text form of the message.
+		 */
+		public String toString( boolean brief )
+		{
+			return entry.toString( brief );
+		}
+		
+		public String toString( DateFormat df )
+		{
+			return entry.toString( df );
+		}
+		
+		public String toString( boolean brief, DateFormat df )
+		{
+			return entry.toString( brief, df );
+		}
+
+		public void write( Writer wtr ) throws IOException
+		{
+			entry.write( wtr );
+		}
+
+		public void write( Writer wtr, boolean brief ) throws IOException
+		{
+			entry.write( wtr, brief );
+		}
+
+		public void write( Writer wtr, DateFormat df ) throws IOException
+		{
+			entry.write( wtr, df );
+		}
+
+		public void write( Writer wtr, boolean brief, DateFormat df ) throws IOException
+		{
+			entry.write( wtr, brief, df );
+		}
+
+		public long getEntryId()
+		{
+			return entry.getEntryId();
+		}
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/Monitor.java b/util/src/main/java/org/apache/etch/util/Monitor.java
new file mode 100644
index 0000000..b29f694
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/Monitor.java
@@ -0,0 +1,338 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+
+/**
+ * A class which we can use to monitor conditions.
+ * 
+ * @param <T> The type of object that may be stored in the monitor.
+ */
+public class Monitor<T>
+{
+	/**
+	 * Constructs the Monitor.
+	 * 
+	 * @param description a description of this monitor.
+	 * 
+	 * @param initialValue the initial value of this monitor.
+	 */
+	public Monitor( String description, T initialValue )
+	{
+		this.description = description;
+		this.value = initialValue;
+	}
+	
+	/**
+	 * Constructs the Monitor with null initial value.
+	 * 
+	 * @param description a description of this monitor.
+	 */
+	public Monitor( String description )
+	{
+		this( description, null );
+	}
+	
+	/**
+	 * @return the description of this monitor.
+	 */
+	public String getDescription()
+	{
+		return description;
+	}
+	
+	private final String description;
+	
+	private T value;
+
+	@Override
+	public String toString()
+	{
+		return "Monitor "+description+": "+value;
+	}
+	
+	/**
+	 * @return the current value of the monitor.
+	 */
+	public T get()
+	{
+		return value;
+	}
+	
+	/**
+	 * Sets the current value.
+	 * 
+	 * @param newValue the value to be set.
+	 * 
+	 * @return the old value.
+	 */
+	public synchronized T set( T newValue )
+	{
+		T oldValue = value;
+		value = newValue;
+		notifyAll();
+		return oldValue;
+	}
+
+	/**
+	 * Waits until value equals the desired value and
+	 * then sets the value. Will wait forever.
+	 * 
+	 * @param desiredValue the value we want.
+	 * 
+	 * @param newValue the value to be set.
+	 * 
+	 * @return the old value
+	 * 
+	 * @throws InterruptedException if waiting was interrupted.
+	 * 
+	 * @throws TimeoutException if we waited too long.
+	 */
+	public T waitUntilEqAndSet( T desiredValue, T newValue )
+		throws InterruptedException, TimeoutException
+	{
+		return waitUntilEqAndSet( desiredValue, 0, newValue );
+	}
+
+	/**
+	 * Waits until value equals the desired value and
+	 * then sets the value.
+	 * 
+	 * @param desiredValue the value we want.
+	 * 
+	 * @param maxDelay the max amount of time in ms to wait.
+	 * If 0 is specified, we will wait forever.
+	 * 
+	 * @param newValue the value to be set.
+	 * 
+	 * @return the old value
+	 * 
+	 * @throws InterruptedException if waiting was interrupted.
+	 * 
+	 * @throws TimeoutException if we waited too long.
+	 */
+	public synchronized T waitUntilEqAndSet( T desiredValue, int maxDelay,
+		T newValue ) throws InterruptedException, TimeoutException
+	{
+		waitUntilEq( desiredValue, maxDelay );
+		return set( newValue );
+	}
+
+	/**
+	 * Waits until value equals the desired value. Will wait forever.
+	 * 
+	 * @param desiredValue the value we want.
+	 * 
+	 * @throws InterruptedException if waiting was interrupted.
+	 * 
+	 * @throws TimeoutException if we waited too long.
+	 */
+	public void waitUntilEq( T desiredValue )
+		throws InterruptedException, TimeoutException
+	{
+		waitUntilEq( desiredValue, 0 );
+	}
+
+	/**
+	 * Waits until value equals the desired value.
+	 * 
+	 * @param desiredValue the value we want.
+	 * 
+	 * @param maxDelay the max amount of time in ms to wait.
+	 * If 0 is specified, we will wait forever.
+	 * 
+	 * @throws InterruptedException if waiting was interrupted.
+	 * 
+	 * @throws TimeoutException if we waited too long.
+	 */
+	public synchronized void waitUntilEq( T desiredValue, int maxDelay )
+		throws InterruptedException, TimeoutException
+	{
+		checkDelay( maxDelay );
+		
+		long now = Timer.getNanos();
+		long end = endTime( now, maxDelay );
+		
+		long d;
+		while (!eq( value, desiredValue ) && (d = remTime( end, now )) > 0)
+		{
+			wait( d );
+			now = Timer.getNanos();
+		}
+		
+		if (!eq( value, desiredValue ))
+			throw new TimeoutException( "timeout" );
+	}
+
+	/**
+	 * Waits until value does not equal the undesired value and then
+	 * sets the value. Will wait forever.
+	 * 
+	 * @param undesiredValue the value we do not want.
+	 * 
+	 * @param newValue the value to be set.
+	 * 
+	 * @return the old value
+	 * 
+	 * @throws InterruptedException if waiting was interrupted.
+	 * 
+	 * @throws TimeoutException if we waited too long.
+	 */
+	public T waitUntilNotEqAndSet( T undesiredValue, T newValue )
+		throws InterruptedException, TimeoutException
+	{
+		return waitUntilNotEqAndSet( undesiredValue, 0, newValue );
+	}
+
+	/**
+	 * Waits until value does not equal the undesired value and then
+	 * sets the value.
+	 * 
+	 * @param undesiredValue the value we do not want.
+	 * 
+	 * @param maxDelay the max amount of time in ms to wait.
+	 * If 0 is specified, we will wait forever.
+	 * 
+	 * @param newValue the value to be set.
+	 * 
+	 * @return the old value
+	 * 
+	 * @throws InterruptedException if waiting was interrupted.
+	 * 
+	 * @throws TimeoutException if we waited too long.
+	 */
+	public synchronized T waitUntilNotEqAndSet( T undesiredValue, int maxDelay,
+		T newValue ) throws InterruptedException, TimeoutException
+	{
+		waitUntilNotEq( undesiredValue, maxDelay );
+		return set( newValue );
+	}
+	
+	/**
+	 * Waits until value does not equal the undesired value. Will
+	 * wait forever.
+	 * 
+	 * @param undesiredValue the value we do not want.
+	 * 
+	 * @return the current value.
+	 * 
+	 * @throws InterruptedException if waiting was interrupted.
+	 * 
+	 * @throws TimeoutException if we waited too long.
+	 */
+	public T waitUntilNotEq( T undesiredValue )
+		throws InterruptedException, TimeoutException
+	{
+		return waitUntilNotEq( undesiredValue, 0 );
+	}
+	
+	/**
+	 * Waits until value does not equal the undesired value.
+	 * 
+	 * @param undesiredValue the value we do not want.
+	 * 
+	 * @param maxDelay the max amount of time in ms to wait.
+	 * If 0 is specified, we will wait forever.
+	 * 
+	 * @return the current value.
+	 * 
+	 * @throws InterruptedException if waiting was interrupted.
+	 * 
+	 * @throws TimeoutException if we waited too long.
+	 */
+	public synchronized T waitUntilNotEq( T undesiredValue, int maxDelay )
+		throws InterruptedException, TimeoutException
+	{
+		checkDelay( maxDelay );
+		
+		long now = Timer.getNanos();
+		long end = endTime( now, maxDelay );
+		
+		long d;
+		while (eq( value, undesiredValue ) && (d = remTime( end, now )) > 0)
+		{
+			wait( d );
+			now = Timer.getNanos();
+		}
+		
+		if (eq( value, undesiredValue ))
+			throw new TimeoutException( "timeout" );
+		
+		return value;
+	}
+
+	/////////////////////
+	// PRIVATE METHODS //
+	/////////////////////
+	
+	private void checkDelay( int maxDelay )
+	{
+		if (maxDelay < 0)
+			throw new IllegalArgumentException( "maxDelay < 0" );
+	}
+
+	/**
+	 * Calculates the ending time for waiting.
+	 * 
+	 * @param now current nanotime.
+	 * 
+	 * @param maxDelay the max amount of time in ms to wait.
+	 * If 0 is specified, we will wait forever.
+	 * 
+	 * @return the nanotime for ending.
+	 */
+	private long endTime( long now, int maxDelay )
+	{
+		return maxDelay > 0 ? now + maxDelay * Timer.NANOS_PER_MILLI : Long.MAX_VALUE;
+	}
+	
+	/**
+	 * Calculates the number of milliseconds from now to end.
+	 * 
+	 * @param end nanotime for ending.
+	 * 
+	 * @param now current nanotime
+	 * 
+	 * @return the number of milliseconds from now to end.
+	 */
+	private long remTime( long end, long now )
+	{
+		return (end - now) / Timer.NANOS_PER_MILLI;
+	}
+
+	/**
+	 * Compares the specified values.
+     * 
+	 * @param v1 a value to compare, which may be null.
+	 * 
+	 * @param v2 another value to compare, which may be null.
+	 * 
+	 * @return true if the values are equal, false otherwise. If both
+	 * values are null, they are considered equal.
+	 */
+	private boolean eq( T v1, T v2 )
+	{
+		if (v1 != null && v2 != null)
+			return v1.equals( v2 );
+		
+		return v1 == v2;
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/PerfTest.java b/util/src/main/java/org/apache/etch/util/PerfTest.java
new file mode 100644
index 0000000..5b52d96
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/PerfTest.java
@@ -0,0 +1,176 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Framework for running performance tests.
+ */
+abstract public class PerfTest
+{
+	/**
+	 * Constructs the PerfTest.
+	 * @param descr the description of the test.
+	 * @param runtime the number of seconds to run each test cycle.
+	 * @param count the number of test cycles to run.
+	 * @param nThreads the number of threads to use for the test.
+	 */
+	public PerfTest( String descr, int runtime, int count, int nThreads )
+	{
+		if (runtime < 1)
+			throw new IllegalArgumentException( "runtime < 1" );
+		
+		if (count < 1)
+			throw new IllegalArgumentException( "count < 1" );
+		
+		if (nThreads < 1)
+			throw new IllegalArgumentException( "nThreads < 1" );
+		
+		this.descr = descr;
+		this.runtime = runtime;
+		this.count = count;
+		this.nThreads = nThreads;
+	}
+	
+	/**
+	 * Constructs the PerfTest.
+	 * @param descr the description of the test.
+	 * @param runtime the number of seconds to run each test cycle.
+	 * @param count the number of test cycles to run.
+	 */
+	public PerfTest( String descr, int runtime, int count )
+	{
+		this( descr, runtime, count, 1 );
+	}
+	
+	private final String descr;
+	
+	private final int runtime;
+	
+	private final int count;
+	
+	private final int nThreads;
+	
+	/**
+	 * Runs the perf test.
+	 * @throws Exception
+	 */
+	final public void run() throws Exception
+    {
+		long oldn = 0;
+		long n = 1;
+		double t = 0;
+		while (t < 1)
+		{
+			if (t > 0.1)
+				System.out.printf( "%s: %d took %f, trying %d to get >= 1 second\n", descr, oldn, t, n );
+			oldn = n;
+			t = runOne( n );
+			n *= 2;
+		}
+		n = oldn;
+		
+		int k = 2;
+		n = (long) (k * n / t);
+		System.out.printf( "%s: %d took %f, trying %d for %d seconds\n", descr, oldn, t, n, k );
+		oldn = n;
+		t = runOne( n );
+		
+		k = 4;
+		n = (long) (k * n / t);
+		System.out.printf( "%s: %d took %f, trying %d for %d seconds\n", descr, oldn, t, n, k );
+		oldn = n;
+		t = runOne( n );
+		
+		n = (long) (runtime * n / t);
+		System.out.printf( "%s: %d took %f, using %d for %d seconds\n",
+			descr, oldn, t, n, runtime );
+		
+		List<Double> list = new ArrayList<Double>( count );
+		double sum = 0;
+		for (int i = 1; i <= count; i++)
+		{
+			t = runOne( n );
+			double r = n/t;
+			list.add( r );
+			sum += r;
+			System.out.printf( "%s %d/%d\t%d\t%d\t%f\t%f\t%f\n",
+				descr, i, count, nThreads, n, t, r, r*nThreads );
+		}
+		Collections.sort( list );
+		System.out.printf( "%s min\t%f\n", descr, list.get( 0 )*nThreads );
+		System.out.printf( "%s median\t%f\n", descr, list.get( count/2 )*nThreads );
+		System.out.printf( "%s avg\t%f\n", descr, sum*nThreads/count );
+		System.out.printf( "%s max\t%f\n", descr, list.get( count-1 )*nThreads );
+    }
+	
+	final private double runOne( long n ) throws Exception
+	{
+	    long t0 = System.nanoTime();
+	    
+	    if (nThreads == 1)
+	    	run( n );
+	    else
+	    	runThreads( n );
+	    
+	    long t1 = System.nanoTime();
+	    return (t1 - t0) / 1000000000.0;
+	}
+	
+	private void runThreads( final long n ) throws InterruptedException
+	{
+		Thread[] threads = new Thread[nThreads];
+		
+		for (int i = 0; i < nThreads; i++)
+		{
+			threads[i] = new Thread( new Runnable()
+			{
+				public void run()
+				{
+					try
+					{
+						PerfTest.this.run( n );
+					}
+					catch ( Exception e )
+					{
+						e.printStackTrace();
+					}
+				}
+			} );
+		}
+		
+		for (int i = 0; i < nThreads; i++)
+			threads[i].start();
+		
+		for (int i = 0; i < nThreads; i++)
+			threads[i].join();
+	}
+
+	/**
+	 * Runs the test with the specific number of times.
+	 * @param n
+	 * @throws Exception
+	 */
+	abstract public void run( long n ) throws Exception;
+}
\ No newline at end of file
diff --git a/util/src/main/java/org/apache/etch/util/PlainByteBuffer.java b/util/src/main/java/org/apache/etch/util/PlainByteBuffer.java
new file mode 100644
index 0000000..91b028c
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/PlainByteBuffer.java
@@ -0,0 +1,146 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import java.io.EOFException;
+import java.nio.BufferOverflowException;
+
+
+/**
+ * Description of PlainByteBuffer.
+ */
+public class PlainByteBuffer extends ByteBuffer
+{
+	/**
+	 * Constructs the PlainByteBuffer.
+	 *
+	 * @param size
+	 */
+	public PlainByteBuffer( int size )
+	{
+		this.size = size;
+		buffer = new byte[size];
+	}
+	
+	private final int size;
+	
+	private final byte[] buffer;
+	
+	private int nextGet;
+	
+	private int nextPut;
+	
+	@Override
+	public int size()
+	{
+		return size;
+	}
+	
+	/**
+	 * @return the byte array backing this buffer.
+	 */
+	public byte[] getBuf()
+	{
+		return buffer;
+	}
+	
+	@Override
+	public int length()
+	{
+		return nextPut-nextGet;
+	}
+	
+	@Override
+	public void clear()
+	{
+		nextGet = 0;
+		nextPut = 0;
+	}
+
+	@Override
+	public byte get() throws EOFException
+	{
+		if (nextGet >= nextPut)
+			throw new EOFException();
+		
+		return buffer[nextGet++];
+	}
+	
+	@Override
+	public int get( byte[] buf, int off, int len )
+	{
+		if (off < 0)
+			throw new IllegalArgumentException( "off < 0" );
+		
+		if (len < 0)
+			throw new IllegalArgumentException( "len < 0" );
+		
+		if (off+len > buf.length)
+			throw new IllegalArgumentException( "off+len > buf.length" );
+		
+		if (len == 0)
+			return 0;
+		
+		int count = Math.min( len, nextPut-nextGet );
+		
+		if (count > 0)
+		{
+			System.arraycopy( buffer, nextGet, buf, off, count );
+			nextGet += count;
+		}
+		
+		return count;
+	}
+
+	@Override
+	public void put( byte b ) throws BufferOverflowException
+	{
+		if (nextPut >= size)
+			throw new BufferOverflowException();
+		buffer[nextPut++] = b;
+	}
+	
+	@Override
+	public int put( byte[] buf, int off, int len )
+	{
+		if (off < 0)
+			throw new IllegalArgumentException( "off < 0" );
+		
+		if (len < 0)
+			throw new IllegalArgumentException( "len < 0" );
+		
+		if (off+len > buf.length)
+			throw new IllegalArgumentException( "off+len > buf.length" );
+		
+		if (len == 0)
+			return 0;
+		
+		int count = Math.min( len, size-nextPut );
+		
+		if (count > 0)
+		{
+			System.arraycopy( buf, off, buffer, nextPut, count );
+			nextPut += count;
+		}
+		
+		return count;
+	}
+}
\ No newline at end of file
diff --git a/util/src/main/java/org/apache/etch/util/Resources.java b/util/src/main/java/org/apache/etch/util/Resources.java
new file mode 100644
index 0000000..e63e4f7
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/Resources.java
@@ -0,0 +1,109 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A HashMap of string to object.
+ */
+public class Resources
+{
+	/**
+	 * Constructs the Resources.
+	 */
+	public Resources()
+	{
+		this( null );
+	}
+	
+	/**
+	 * Constructs the Resources with a reference to related Resources.
+	 * @param related
+	 */
+	public Resources( Resources related )
+	{
+		this.related = related;
+	}
+	
+	private final Resources related;
+	
+	private final Map<String, Object> res = new HashMap<String, Object>();
+	
+	/**
+	 * @return the related Resources.
+	 */
+	public Resources getRelated()
+	{
+		return related;
+	}
+
+	/**
+	 * Returns true if this Resources or any related Resources has the key.
+	 * @param key the string name of a resource.
+	 * @return true if this Resources or any related Resources has the key.
+	 */
+	public boolean containsKey( String key )
+	{
+		return res.containsKey( key ) ||
+			related != null && related.containsKey( key );
+	}
+	
+	/**
+	 * Returns the named resource from this Resources if present, otherwise
+	 * searches for key in the related Resources.
+	 * @param key the string name of a resource.
+	 * @return the value of the resource.
+	 */
+	public Object get( String key )
+	{
+		Object o = res.get( key );
+		
+		if (o != null)
+			return o;
+		
+		return related != null ? related.get( key ) : null;
+	}
+	
+	/**
+	 * Puts the named resource into this Resources. No related Resources are
+	 * affected.
+	 * @param key the string name of a resource.
+	 * @param value the value of the resource.
+	 * @return the old value of the key in this Resources only.
+	 */
+	public Object put( String key, Object value )
+	{
+		return res.put( key, value );
+	}
+	
+	/**
+	 * Removes the named resource from this Resources only. No related Resources
+	 * are affected.
+	 * @param key the string name of a resource.
+	 * @return the old value of the key in this Resources only.
+	 */
+	public Object remove( String key )
+	{
+		return res.remove( key );
+	}
+}
\ No newline at end of file
diff --git a/util/src/main/java/org/apache/etch/util/Runner.java b/util/src/main/java/org/apache/etch/util/Runner.java
new file mode 100644
index 0000000..9123ceb
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/Runner.java
@@ -0,0 +1,132 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+
+/**
+ * Implementation of startable which creates a thread and runs.
+ */
+abstract public class Runner
+	extends AbstractStartable implements Runnable
+{
+	/**
+	 * Constructs the Runner.
+	 */
+	public Runner()
+	{
+		// nothing to do.
+	}
+	
+	/**
+	 * @param handler the handler to notify of started and stopped events.
+	 */
+	public void setHandler( RunnerHandler handler )
+	{
+		this.handler = handler;
+	}
+	
+	/**
+	 * The handler is used to report started and stopped events.
+	 */
+	private RunnerHandler handler;
+	
+	@Override
+	protected void start0() throws Exception
+	{
+		thread = new Thread( this );
+		thread.start();
+	}
+
+	@Override
+	protected void stop0() throws Exception
+	{
+		Thread t = thread;
+		if (t != null)
+		{
+			thread = null;
+			//t.join();
+		}
+	}
+	
+	private Thread thread;
+	
+	final public void run()
+	{
+		fireStarted();
+		
+		try
+		{
+			boolean first = true;
+			while (isStarted())
+			{
+				if (!run0( first ))
+					break;
+				first = false;
+			}
+		}
+		catch ( Exception e )
+		{
+			fireException( "run", e );
+		}
+		finally
+		{
+			setStopped();
+			fireStopped();
+			//Log.report( "thread dead" );
+		}
+	}
+	
+	private void fireStarted()
+	{
+		handler.started();
+	}
+
+	/**
+	 * Reports an exception caught by the thread managing the runnable.
+	 * @param what
+	 * @param e
+	 */
+	protected void fireException( String what, Exception e )
+	{
+		try
+		{
+			handler.exception( what, e );
+		}
+		catch ( Exception x )
+		{
+			e.printStackTrace();
+			if (x != e)
+				x.printStackTrace();
+		}
+	}
+
+	private void fireStopped()
+	{
+		handler.stopped();
+	}
+
+	/**
+	 * @param first true the first time we are called
+	 * @return true if we should keep running.
+	 * @throws Exception
+	 */
+	abstract protected boolean run0( boolean first ) throws Exception;
+}
diff --git a/util/src/main/java/org/apache/etch/util/RunnerHandler.java b/util/src/main/java/org/apache/etch/util/RunnerHandler.java
new file mode 100644
index 0000000..4d237b5
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/RunnerHandler.java
@@ -0,0 +1,45 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * RunnerHandler receives notification of runner events.
+ */
+public interface RunnerHandler
+{
+	/**
+	 * Reports that the thread controlling the runner has started.
+	 */
+	void started();
+
+	/**
+	 * Reports that the thread controlling the runner has stopped.
+	 */
+	void stopped();
+
+	/**
+	 * Reports that the thread controlling the runner has caught an
+	 * exception.
+	 * @param what a short description of the origin
+	 * @param e an exception that was caught
+	 */
+	void exception( String what, Exception e );
+}
diff --git a/util/src/main/java/org/apache/etch/util/SingleIterator.java b/util/src/main/java/org/apache/etch/util/SingleIterator.java
new file mode 100644
index 0000000..08a980f
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/SingleIterator.java
@@ -0,0 +1,72 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * An iterator over a single object.
+ * @param <E>
+ */
+final public class SingleIterator<E> implements Iterator<E>
+{
+	/**
+	 * Constructs a SingleIterator.
+	 *
+	 * @param obj the object to be iterated.
+	 */
+	public SingleIterator( E obj )
+	{
+		this.obj = obj;
+	}
+	
+	private E obj;
+	
+	/* (non-Javadoc)
+	 * @see java.util.Iterator#hasNext()
+	 */
+	public boolean hasNext()
+	{
+		return obj != null;
+	}
+
+	/* (non-Javadoc)
+	 * @see java.util.Iterator#next()
+	 */
+	public E next()
+	{
+		if (obj == null)
+			throw new NoSuchElementException();
+		
+		E o = obj;
+		obj = null;
+		return o;
+	}
+
+	/* (non-Javadoc)
+	 * @see java.util.Iterator#remove()
+	 */
+	public void remove()
+	{
+		throw new UnsupportedOperationException();
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/Startable.java b/util/src/main/java/org/apache/etch/util/Startable.java
new file mode 100644
index 0000000..f2897b9
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/Startable.java
@@ -0,0 +1,48 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * Description of Startable
+ */
+public interface Startable
+{
+	/**
+	 * @throws Exception
+	 */
+	public void start() throws Exception;
+	
+	/**
+	 * @throws Exception
+	 */
+	public void stop() throws Exception;
+	
+	/**
+	 * @return true if started.
+	 */
+	public boolean isStarted();
+
+	/**
+	 * Checks that the startable is started.
+	 * @throws IllegalStateException if not started.
+	 */
+	public void checkIsStarted();
+}
diff --git a/util/src/main/java/org/apache/etch/util/StringUtil.java b/util/src/main/java/org/apache/etch/util/StringUtil.java
new file mode 100644
index 0000000..667688a
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/StringUtil.java
@@ -0,0 +1,212 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * Miscellaneous string utility functions.
+ */
+public class StringUtil
+{
+	/**
+	 * Makes a random string using the default characters, which
+	 * are B-Z (minus E,I,O,U), b-z (minus e,i,o,u), and 2-9. Thus
+	 * we have no vowel like characters in the result so that strings
+	 * like 'fool', 'idiot', and 'doofus' will not ever appear.
+	 * 
+	 * Because there are 50 choices for each character in the resulting
+	 * string, each character contributes 5.64 bits of randomness. so, if
+	 * you want at least 64 bits of randomness, you'll need at least 12
+	 * characters.
+	 * 
+	 * @param n the length of the string.
+	 * 
+	 * @return a random string of the specified length.
+	 */
+	public static String rndString( int n )
+	{
+		return rndString( n, DEFAULT_CHARS );
+	}
+	
+	/**
+	 * Makes a random string using the specified characters.
+	 * @param n the length of the string.
+	 * @param chars the characters used to construct the random string.
+	 * @return a random string of the specified length.
+	 */
+	public static String rndString( int n, char[] chars )
+	{
+		if (n < 1)
+			throw new IllegalArgumentException( "n < 1" );
+		
+		int k = chars.length;
+		if (k < 2)
+			throw new IllegalArgumentException( "chars.length < 2" );
+		
+		StringBuffer sb = new StringBuffer( n );
+		while (n-- > 0)
+			sb.append( chars[(int) (Math.random() * k)] );
+		
+		return sb.toString();
+	}
+	
+	private final static char[] DEFAULT_CHARS = (
+		"BCDFGHJKLMNPQRSTVWXYZ" +
+		"bcdfghjklmnpqrstvwxyz" +
+		"23456789"
+		).toCharArray();
+
+	/**
+	 * @param s
+	 * @param c
+	 * @return an array x of two elements containing s split in two by the
+	 * leftmost c. x[0] is the chars before c, x[1] is the chars after c.
+	 * If c is not in s, returns null.
+	 */
+	public static String[] leftSplit( String s, char c )
+	{
+		if (s == null)
+			throw new NullPointerException( "s == null" );
+		
+		int i = s.indexOf( c );
+		if (i < 0)
+			return null;
+		
+		return new String[] { s.substring( 0, i ), s.substring( i+1 ) };
+	}
+	
+	/**
+	 * @param s
+	 * @param c
+	 * @return an array x of two elements containing s split in two by the
+	 * rightmost c. x[0] is the chars before c, x[1] is the chars after c.
+	 * If c is not in s, returns null.
+	 */
+	public static String[] rightSplit( String s, char c )
+	{
+		if (s == null)
+			throw new NullPointerException( "s == null" );
+		
+		int i = s.lastIndexOf( c );
+		if (i < 0)
+			return null;
+		
+		return new String[] { s.substring( 0, i ), s.substring( i+1 ) };
+	}
+
+	/**
+	 * @param a
+	 * @param b
+	 * @return true if a equals b, false otherwise. takes into account nulls.
+	 */
+	public static boolean equals( String a, String b )
+	{
+		if (a == b)
+			return true;
+		
+		if (a == null || b == null)
+			return false;
+		
+		return a.equals( b );
+	}
+
+	/**
+	 * @param a
+	 * @return matches behavior of equals, above.
+	 */
+	public static int hashCode( String a )
+	{
+		if (a == null)
+			return 0;
+		return a.hashCode();
+	}
+
+	/**
+	 * @param a
+	 * @param b
+	 * @return true if a equals b, false otherwise. takes into account nulls.
+	 */
+	public static boolean equalsIgnoreCase( String a, String b )
+	{
+		if (a == b)
+			return true;
+		
+		if (a == null || b == null)
+			return false;
+		
+		return a.equalsIgnoreCase( b );
+	}
+
+	/**
+	 * @param a
+	 * @return matches behavior of equalsIgnoreCase, above.
+	 */
+	public static int hashCodeIgnoreCase( String a )
+	{
+		if (a == null)
+			return 0;
+		return a.toLowerCase().hashCode();
+	}
+	
+	/**
+	 * Translates a hex char into an int.
+	 * @param c a hex char (0-9, A-F, a-f).
+	 * @return an int (0-15).
+	 */
+	public static int fromHex( char c )
+	{
+		if (c >= '0' && c <= '9')
+			return c - '0';
+		if (c >= 'A' && c <= 'F')
+			return c - 'a' + 10;
+		if (c >= 'a' && c <= 'f')
+			return c - 'a' + 10;
+		throw new IllegalArgumentException( "bad hex char "+c );
+	}
+	
+	/**
+	 * Translates an int into a hex char.
+	 * @param i an int (0-15)
+	 * @return a hex char (0-9, a-f).
+	 */
+	public static char toHex( int i )
+	{
+		if (i >= 0 && i <= 9)
+			return (char) ('0' + i);
+		if (i >= 10 && i <= 15)
+			return (char) ('a' + i - 10);
+		throw new IllegalArgumentException( "bad hex digit selector "+i );
+	}
+	
+	/**
+	 * @param digest
+	 * @return string version of digest.
+	 */
+	public static String fingerprint( byte[] digest )
+	{
+		StringBuffer sb = new StringBuffer( digest.length * 2 );
+		for (byte b: digest)
+		{
+			sb.append( toHex( b >>> 4 & 15 ) );
+			sb.append( toHex( b & 15 ) );
+		}
+		return sb.toString();
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/TimeoutException.java b/util/src/main/java/org/apache/etch/util/TimeoutException.java
new file mode 100644
index 0000000..7057d78
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/TimeoutException.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * RuntimeException for Timeout condition.
+ */
+public class TimeoutException extends RuntimeException
+{
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * Constructs the TimeoutException.
+	 * @param message
+	 */
+	public TimeoutException( String message )
+	{
+		super( message );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/Timer.java b/util/src/main/java/org/apache/etch/util/Timer.java
new file mode 100644
index 0000000..23c6363
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/Timer.java
@@ -0,0 +1,239 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * Timer enables making high precision interval tests. In the usual
+ * scenario, some code is going to be bracketed by calls to
+ * initialize a timer and later get the elapsed time since the init.
+ * 
+ * Trying to use the system clock (System.currentTimeMillis) is
+ * problematic because periodic system time adjustments (by ntp,
+ * windows time, etc.) will invalidate any interval testing based
+ * on the system clock. Also, the system clock resolution is not
+ * all that good (15 ms typically on a windows box).
+ * 
+ * Timer tmr = new Timer().init();
+ * foo();
+ * long ns = tmr.elapsedNanos();
+ * System.out.println( "foo() took "+ns+" nanos" );
+ * 
+ * Timer keeps state, initialized by init(), and used by elapsedBlah()
+ * and thus is thread safe as long as calls to init() are serialized.
+ * 
+ * For lower cost timing needs, Timer supports a set of static interfaces.
+ * 
+ * long t0 = Timer.getStartTime();
+ * foo();
+ * long ns = Timer.getNanosSince( t0 );
+ * System.out.println( "foo() took "+ns+" nanos" );
+ * 
+ * Note: reading the high precision clock (which all these methods
+ * ultimately do) takes about 1,487 nanoseconds on Windows XP Pro
+ * running on a Dell Precision 370 workstation using jdk 1.5.0_04.
+ * By comparison, a method call takes about 1.97 nanoseconds. Also,
+ * on the above platform, the resolution of the timer is 1,396 ns.
+ * Could be that the resolution is smaller, but we'll never know it
+ * because just getting the value from the OS is the dominant factor.
+ * 
+ * @see #getNanos()
+ * @see #getNanosSince(long)
+ */
+public class Timer
+{
+	/**
+	 * Constructs the Timer. The timer is not started.
+	 * @see #init()
+	 */
+	public Timer()
+	{
+		// nothing to do.
+	}
+	
+	/**
+	 * Initializes the startTime of this timer.
+	 * @return returns this timer.
+	 */
+	public Timer init()
+	{
+		startTime = getNanos();
+		return this;
+	}
+	
+	/**
+	 * @return the elapsed time in nanos since the last init.
+	 */
+	public long elapsedNanos()
+	{
+		if (startTime == Long.MIN_VALUE)
+			throw new UnsupportedOperationException( "Timer not started" );
+		return getNanosSince( startTime );
+	}
+	
+	/**
+	 * @return the elapsed time in micros since the last init.
+	 */
+	public long elapsedMicros()
+	{
+		return elapsedNanos() / NANOS_PER_MICRO;
+	}
+	
+	/**
+	 * @return the elapsed time in millis since the last init.
+	 */
+	public long elapsedMillis()
+	{
+		return elapsedNanos() / NANOS_PER_MILLI;
+	}
+	
+	/**
+	 * @return the elapsed time in seconds since the last init.
+	 */
+	public double elapsedSeconds()
+	{
+		return elapsedNanos() / NANOS_PER_SECOND;
+	}
+	
+	private long startTime = Long.MIN_VALUE;
+	
+	/**
+	 * Number of nanoseconds per microsecond.
+	 */
+	public final static long NANOS_PER_MICRO = 1000;
+	
+	/**
+	 * Number of nanoseconds per milliseconds.
+	 */
+	public final static long NANOS_PER_MILLI = 1000000;
+	
+	/**
+	 * Number of nanoseconds per second.
+	 */
+	public final static double NANOS_PER_SECOND = 1000000000.0;
+
+	//////////////////////
+	// STATIC INTERFACE //
+	//////////////////////
+	
+	/**
+	 * @return the starting point of a timing test in nanos.
+	 */
+	public static long getNanos()
+	{
+		return System.nanoTime();
+	}
+	
+	/**
+	 * Don't use this method for newly built timing. This is only
+	 * for easy backwards compatible (for delta time purposes) replacement
+	 * of System.currentTimeMillis().
+	 * 
+	 * @return the starting point of a timing test in millis.
+	 * 
+	 * @see System#currentTimeMillis()
+	 */
+	public static long currentTimeMillis()
+	{
+		return getNanos() / NANOS_PER_MILLI;
+	}
+	
+	/**
+	 * @param startTime a value returned by getStartTime.
+	 * 
+	 * @return the number of nanos which have passed since startTime.
+	 * 
+	 * @see #getNanos()
+	 */
+	public static long getNanosSince( long startTime )
+	{
+		return System.nanoTime() - startTime;
+	}
+	
+	/**
+	 * @param startTime a value returned by getStartTime.
+	 * 
+	 * @return the number of micros which have passed since startTime.
+	 * 
+	 * @see #getNanos()
+	 */
+	public static long getMicrosSince( long startTime )
+	{
+		return getNanosSince( startTime ) / NANOS_PER_MICRO;
+	}
+	
+	/**
+	 * @param startTime a value returned by getStartTime.
+	 * 
+	 * @return the number of millis which have passed since startTime.
+	 * 
+	 * @see #getNanos()
+	 */
+	public static long getMillisSince( long startTime )
+	{
+		return getNanosSince( startTime ) / NANOS_PER_MILLI;
+	}
+
+	/**
+	 * @param startTime a value returned by getStartTime.
+	 * 
+	 * @return the number of seconds which have passed since startTime.
+	 * 
+	 * @see #getNanos()
+	 */
+	public static double getSecondsSince( long startTime )
+	{
+		return getNanosSince( startTime ) / NANOS_PER_SECOND;
+	}
+	
+	/**
+	 * @return returns the minimum value of many invocations of
+	 * getNanosSince( getStartTime() ).
+	 */
+	public static long getResolution()
+	{
+		long r = Long.MAX_VALUE;
+		for (int i = 0; i < 100000; i++)
+		{
+			r = Math.min( r, getNanosSince( getNanos() ) );
+		}
+		return r;
+	}
+	
+	/**
+	 * @param s the number of seconds
+	 * @return a nice text description of the amount of time
+	 */
+	public static String howLong( int s )
+	{
+		if (s < 60)
+			return Integer.toString( s ) + "s";
+		
+		int m = s / 60;
+		if (m < 60)
+			return Integer.toString( m ) + "m "+s%60+"s";
+		
+		int h = m / 60;
+		if (h < 24)
+			return Integer.toString( h ) + "h "+m%60+"m";
+		
+		return Integer.toString( h / 24 ) + "d "+h%24+"h";
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/Todo.java b/util/src/main/java/org/apache/etch/util/Todo.java
new file mode 100644
index 0000000..20c725c
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/Todo.java
@@ -0,0 +1,43 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * A Todo is used to perform a lightweight action.
+ * 
+ * @see TodoManager
+ */
+public interface Todo
+{
+	/**
+	 * Performs the action.
+	 * @param mgr the todo manager where this todo was queued.
+	 * @throws Exception if there is a problem.
+	 */
+	public void doit( TodoManager mgr ) throws Exception;
+
+	/**
+	 * Reports an exception that occurred while running the todo.
+	 * @param mgr the todo manager where this todo was queued.
+	 * @param e the exception that the todo threw.
+	 */
+	public void exception( TodoManager mgr, Exception e );
+}
diff --git a/util/src/main/java/org/apache/etch/util/TodoManager.java b/util/src/main/java/org/apache/etch/util/TodoManager.java
new file mode 100644
index 0000000..6465429
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/TodoManager.java
@@ -0,0 +1,342 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+/**
+ * A standalone verion of a processor for todo items.
+ */
+public class TodoManager extends AbstractStartable implements Runnable
+{
+	/**
+	 * Constructs the TodoManager.
+	 * @param maxEntries the maximum number of entries in the queue before
+	 * the caller of addEntry is delayed.
+	 * @param entryDelay milliseconds to delay a caller who tries to
+	 * add a entry over the limit.
+	 * @param minWorkers the minimum number of workers to keep waiting.
+	 * @param maxWorkers the maxumum number of workers to allow.
+	 * @param workerLinger milliseconds a worker will wait for a Todo
+	 * before considering quitting.
+	 * @param threshold the per worker threshold for queue length. If
+	 * queue length exceeds this amount, a new worker is added if allowed.
+	 */
+	public TodoManager( int maxEntries, int entryDelay, int minWorkers,
+		int maxWorkers, int workerLinger, int threshold )
+	{
+		if (maxEntries < 1)
+			throw new IllegalArgumentException( "maxEntries < 1" );
+		
+		if (entryDelay < 1)
+			throw new IllegalArgumentException( "entryDelay < 1" );
+		
+		if (minWorkers < 0)
+			throw new IllegalArgumentException( "minWorkers < 0" );
+		
+		if (maxWorkers < 1)
+			throw new IllegalArgumentException( "maxWorkers < 1" );
+		
+		if (maxWorkers < minWorkers)
+			throw new IllegalArgumentException( "maxWorkers < minWorkers" );
+		
+		if (workerLinger < 1)
+			throw new IllegalArgumentException( "workerLinger < 1" );
+		
+		if (threshold < 0)
+			throw new IllegalArgumentException( "threshold < 0" );
+		
+		this.maxEntries = maxEntries;
+		this.entryDelay = entryDelay;
+		this.minWorkers = minWorkers;
+		this.maxWorkers = maxWorkers;
+		this.workerLinger = workerLinger;
+		this.threshold = threshold;
+	}
+	
+	private final int maxEntries;
+	
+	private final int entryDelay;
+	
+	private final int minWorkers;
+	
+	private final int maxWorkers;
+	
+	private final int workerLinger;
+	
+	private final int threshold;
+
+	@Override
+    protected void start0() throws Exception
+    {
+	    // nothing to do.
+    }
+
+	@Override
+    protected void stop0() throws Exception
+    {
+	    // nothing to do.
+		notifyAll();
+    }
+	
+	/**
+	 * @param todo
+	 * @throws InterruptedException
+	 */
+	public synchronized void add( Todo todo ) throws InterruptedException
+	{
+		checkIsStarted();
+		
+		int n = addEntry( todo );
+		notify();
+		
+		considerStartingAWorker( n );
+		
+		if (n > maxEntries)
+			Thread.sleep( entryDelay );
+	}
+
+	public void run()
+	{
+		boolean needsAdjust = true;
+		try
+		{
+			Todo todo;
+			while ((todo = getNextTodo()) != null)
+			{
+				try
+				{
+					todo.doit( this );
+				}
+				catch ( Exception e )
+				{
+					todo.exception( this, e );
+				}
+			}
+			needsAdjust = false;
+		}
+		finally
+		{
+			if (needsAdjust)
+				workers.adjust( -1 );
+		}
+	}
+
+	/////////////
+	// WORKERS //
+	/////////////
+	
+	/**
+	 * @return the number of workers.
+	 */
+	public int numWorkers()
+	{
+		return workers.get();
+	}
+
+	private synchronized void considerStartingAWorker( int qlen )
+    {
+	    int n = numWorkers();
+	    
+	    if (n >= maxWorkers)
+	    	return;
+	    
+	    // start a new worker if there are none or if the queue
+	    // length per worker has exceeded the threshold.
+	    
+	    if (n == 0 || (qlen + n - 1) / n > threshold)
+	    	startAWorker();
+	    
+    }
+	
+	private void startAWorker()
+	{
+		workers.adjust( 1 );
+		new Thread( this ).start();
+	}
+	
+	private final IntCounter workers = new IntCounter();
+
+	///////////
+	// QUEUE //
+	///////////
+	
+	/**
+	 * Adds the todo to the tail of the queue.
+	 * @param todo the todo to add.
+	 * @return the current queue length.
+	 */
+	private synchronized int addEntry( Todo todo )
+    {
+		Entry e = new Entry();
+		
+		e.todo = todo;
+		
+		if (tail != null)
+			tail.next = e;
+		else
+			head = e;
+		
+		tail = e;
+	    
+		return entries.adjust( 1 );
+    }
+	
+	/**
+	 * @return a todo from the head of the queue, or null if the
+	 * queue is empty.
+	 */
+	private synchronized Todo removeEntry()
+    {
+	    if (head == null)
+	    	return null;
+	    
+	    Entry e = head;
+	    head = e.next;
+	    
+	    if (head == null)
+	    	tail = null;
+	    
+	    entries.adjust( -1 );
+	    
+	    return e.todo;
+    }
+	
+	/**
+	 * @return the number of todos.
+	 */
+	public int numEntries()
+	{
+		return entries.get();
+	}
+	
+	private Entry head;
+	
+	private Entry tail;
+	
+	private final IntCounter entries = new IntCounter();
+	
+	/** An entry in the todo queue */
+	public static class Entry
+	{
+		/** the todo to be performed. */
+		public Todo todo;
+		/** the next todo in the queue. */
+		public Entry next;
+	}
+
+	//////////
+	// BLAH //
+	//////////
+	
+	private synchronized Todo getNextTodo()
+	{
+		Todo todo = null;
+		boolean lingered = false;
+		while (isStarted() && (todo = removeEntry()) == null)
+		{
+			try
+			{
+				if (lingered && workers.get() > minWorkers)
+				{
+					workers.adjust( -1 );
+					return null;
+				}
+				
+				wait( workerLinger );
+				
+				// we lingered. we might have been woken because
+				// we're stopping, or a todo might have been
+				// queued.
+				
+				lingered = true;
+			}
+			catch ( InterruptedException e )
+			{
+				workers.adjust( -1 );
+				return null;
+			}
+		}
+		return todo;
+	}
+
+	//////////////////
+	// STATIC STUFF //
+	//////////////////
+	
+	/**
+	 * @param todo
+	 */
+	public static void addTodo( Todo todo )
+	{
+		try
+		{
+			getTodoManager().add( todo );
+		}
+		catch ( Exception e )
+		{
+			todo.exception( null, e );
+		}
+	}
+
+	/**
+	 * @return the configured todo manager. if there isn't one, it makes
+	 * one with one worker thread.
+	 * @throws Exception if there is a problem creating the todo manager.
+	 */
+	public static TodoManager getTodoManager() throws Exception
+	{
+		if (todoManager == null)
+		{
+			synchronized (TodoManager.class)
+			{
+				if (todoManager == null)
+				{
+					todoManager = new TodoManager( 50, 10, 0, 5, 5000, 0 );
+					todoManager.start();
+				}
+			}
+		}
+		return todoManager;
+	}
+	
+	/**
+	 * @param newTodoManager
+	 * @return the old todo manager.
+	 */
+	public static synchronized TodoManager setTodoManager( TodoManager newTodoManager )
+	{
+		TodoManager oldTodoManager = todoManager;
+		todoManager = newTodoManager;
+		return oldTodoManager;
+	}
+	
+	/**
+	 * Shuts down the currently configured static todo manager if any.
+	 * @throws Exception
+	 */
+	public static void shutdown() throws Exception
+	{
+		TodoManager oldTodoManager = setTodoManager( null );
+		if (oldTodoManager != null)
+			oldTodoManager.stop();
+	}
+	
+	private static TodoManager todoManager;
+}
diff --git a/util/src/main/java/org/apache/etch/util/URL.java b/util/src/main/java/org/apache/etch/util/URL.java
new file mode 100644
index 0000000..d200d12
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/URL.java
@@ -0,0 +1,1317 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Models a url of the form scheme://user:password@host:port/uri;parms?terms#fragment
+ */
+public class URL
+{
+	/**
+	 * Constructs a url from a string.
+	 * @param urlStr
+	 */
+	public URL( String urlStr )
+	{
+		if (urlStr != null && urlStr.length() > 0)
+			parse( urlStr );
+	}
+	
+	/**
+	 * Constructs a url from another url.
+	 * @param other
+	 */
+	public URL( URL other )
+	{
+		scheme = other.scheme;
+		user = other.user;
+		password = other.password;
+		host = other.host;
+		port = other.port;
+		uri = other.uri;
+		params = copyList( other.params );
+		terms = copyTerms( other.terms );
+		fragment = other.fragment;
+	}
+
+	/**
+	 * Constructs an empty url.
+	 */
+	public URL()
+	{
+		// nothing to do.
+	}
+	
+	private void parse( String s )
+	{
+		// s is scheme:[//[user[:password]@]host[:port]/]uri[;params][?terms][#fragment]
+		
+		String[] x = StringUtil.leftSplit( s, ':' );
+		if (x == null)
+			throw new IllegalArgumentException( "missing scheme" );
+		
+		setScheme( unescape( x[0] ) );
+		s = x[1];
+		
+		// s is [//[user[:password]@]host[:port]/]uri[;params][?terms][#fragment]
+		
+		x = StringUtil.leftSplit( s, '#' );
+		if (x != null)
+		{
+			setFragment( unescape( x[1] ) );
+			s = x[0];
+		}
+		
+		// s is [//[user[:password]@]host[:port]/]uri[;params][?terms]
+		
+		x = StringUtil.leftSplit( s, '?' );
+		if (x != null)
+		{
+			parseTerms( x[1] );
+			s = x[0];
+		}
+		
+		// s is [//[user[:password]@]host[:port]/]uri[;params]
+		
+		x = StringUtil.leftSplit( s, ';' );
+		if (x != null)
+		{
+			parseParams( x[1] );
+			s = x[0];
+		}
+		
+		// s is [//[user[:password]@]host[:port]/]uri
+		
+		if (s.startsWith( "//" ))
+		{
+			s = s.substring( 2 );
+			// s is [user[:password]@]host[:port]/uri
+			x = StringUtil.leftSplit( s, '/' );
+			if (x != null)
+			{
+				// s is [user[:password]@]host[:port]/uri
+				parseHost( x[0] );
+				s = x[1];
+			}
+			else
+			{
+				// s is [user[:password]@]host[:port]
+				parseHost( s );
+				s = "";
+			}
+		}
+		setUri( unescape( s ) );
+	}
+
+	private void parseHost( String s )
+	{
+		// s is [user[:password]@]host[:port]
+		String[] x = StringUtil.leftSplit( s, '@' );
+		if (x != null)
+		{
+			parseUserPassword( x[0] );
+			parseHostPort( x[1] );
+		}
+		else
+		{
+			parseHostPort( s );
+		}
+	}
+
+	private void parseUserPassword( String s )
+	{
+		// s is user[:password]
+		String[] x = StringUtil.leftSplit( s, ':' );
+		if (x != null)
+		{
+			setUser( unescape( x[0] ) );
+			setPassword( unescape( x[1] ) );
+		}
+		else
+		{
+			setUser( unescape( s ) );
+		}
+	}
+
+	private void parseHostPort( String s )
+	{
+		// s is host[:port]
+		String[] x = StringUtil.leftSplit( s, ':' );
+		if (x != null)
+		{
+			setHost( unescape( x[0] ) );
+			String p = unescape( x[1] );
+			checkNotInteger( "port", p );
+			setPort( Integer.parseInt( p ) );
+		}
+		else
+		{
+			setHost( unescape( s ) );
+		}
+	}
+
+	private void parseParams( String s )
+	{
+		// s is param[;param]*
+		
+		if (s.length() == 0)
+			return;
+		
+		ensureParams();
+		
+		String[] x;
+		while ((x = StringUtil.leftSplit( s, ';' )) != null)
+		{
+			addParam( unescape( x[0] ) );
+			s = x[1];
+		}
+		
+		addParam( unescape( s ) );
+	}
+
+	private void parseTerms( String s )
+	{
+		// s is term[&term]*
+		
+		if (s.length() == 0)
+			return;
+		
+		String[] x;
+		while ((x = StringUtil.leftSplit( s, '&' )) != null)
+		{
+			parseTerm( x[0] );
+			s = x[1];
+		}
+		
+		parseTerm( s );
+	}
+
+	private void parseTerm( String s )
+	{
+		// s is name[=value]
+		
+		if (s.length() == 0)
+			return;
+		
+		ensureTerms();
+		
+		String[] x = StringUtil.leftSplit( s, '=' );
+		if (x != null)
+			addTerm( unescape( x[0] ), unescape( x[1] ) );
+		else
+			addTerm( unescape( s ), "" );
+	}
+
+	private String scheme;
+	
+	private String user;
+	
+	private String password;
+	
+	private String host;
+	
+	private Integer port;
+	
+	private String uri;
+	
+	private List<String> params;
+	
+	private Map<String, Object> terms;
+	
+	private String fragment;
+
+	////////////
+	// SCHEME //
+	////////////
+	
+	/**
+	 * @return the scheme.
+	 */
+	public String getScheme()
+	{
+		return scheme;
+	}
+	
+	/**
+	 * Sets the scheme.
+	 * 
+	 * @param scheme the scheme to set which may be null but not blank.
+	 */
+	public void setScheme( String scheme )
+	{
+		checkNotBlank( "scheme", scheme );
+		this.scheme = scheme;
+	}
+	
+	/**
+	 * Tests the scheme for a match. The schemes are case-insensitive.
+	 * 
+	 * @param testScheme a scheme to test against.
+	 * 
+	 * @return true if the schemes match, false otherwise.
+	 */
+	public boolean isScheme( String testScheme )
+	{
+		return testScheme.equalsIgnoreCase( scheme );
+	}
+
+	//////////
+	// USER //
+	//////////
+	
+	/**
+	 * @return the user.
+	 */
+	public String getUser()
+	{
+		return user;
+	}
+	
+	/**
+	 * Sets the user.
+	 * 
+	 * @param user the user to set which may be null but not blank.
+	 */
+	public void setUser( String user )
+	{
+		checkNotBlank( "user", user );
+		this.user = user;
+	}
+
+	//////////////
+	// PASSWORD //
+	//////////////
+	
+	/**
+	 * @return the password.
+	 */
+	public String getPassword()
+	{
+		return password;
+	}
+	
+	/**
+	 * Sets the password.
+	 * 
+	 * @param password the password to set which may be null but not blank.
+	 */
+	public void setPassword( String password )
+	{
+		//checkNotBlank( "password", password );
+		this.password = password;
+	}
+
+	//////////
+	// HOST //
+	//////////
+
+	/**
+	 * @return the host.
+	 */
+	public String getHost()
+	{
+		return host;
+	}
+
+	/**
+	 * Sets the host.
+	 * 
+	 * @param host the host to set which may be null but not blank.
+	 */
+	public void setHost( String host )
+	{
+		checkNotBlank( "host", host );
+		this.host = host;
+	}
+
+	//////////
+	// PORT //
+	//////////
+
+	/**
+	 * @return true if a port has been specified, false otherwise.
+	 */
+	public boolean hasPort()
+	{
+		return port != null;
+	}
+	
+	/**
+	 * @return the port. Null if no port has been specified.
+	 */
+	public Integer getPort()
+	{
+		return port;
+	}
+
+	/**
+	 * Sets the port.
+	 * 
+	 * @param port the port to set which may be between 0 and 65535.
+	 */
+	public void setPort( Integer port )
+	{
+		if (port != null && (port < 0 || port > 65535))
+			throw new IllegalArgumentException( "port < 0 || port > 65535" );
+		
+		this.port = port;
+	}
+
+	/////////
+	// URI //
+	/////////
+	
+	/**
+	 * @return the uri.
+	 */
+	public String getUri()
+	{
+		return uri;
+	}
+
+	/**
+	 * Sets the uri.
+	 * 
+	 * @param uri the uri to set which may be null or blank.
+	 */
+	public void setUri( String uri )
+	{
+		this.uri = uri;
+	}
+
+	////////////
+	// PARAMS //
+	////////////
+	
+	/**
+	 * @return true if there is at least one param.
+	 */
+	public boolean hasParams()
+	{
+		return params != null && params.size() > 0;
+	}
+
+	/**
+	 * Fetchs the first param found which starts with the given prefix. The
+	 * search order is not specified, and the params are not maintained in any
+	 * specific order.
+	 * 
+	 * @param prefix the prefix of the param to fetch (e.g., "transport=").
+	 * 
+	 * @return the first param which starts with the specified prefix.
+	 */
+	public String getParam( String prefix )
+	{
+		checkNotNull( prefix, "prefix == null" );
+		
+		if (params == null)
+			return null;
+		
+		for (String p: params)
+			if (p.startsWith( prefix ))
+				return p;
+		
+		return null;
+	}
+	
+	/**
+	 * @return an iterator over all the params. The params are strings, generally
+	 * of the form "transport=tcp". But they can be anything you like, really.
+	 * The iterator might be empty.
+	 */
+	public String[] getParams()
+	{
+		if (params == null)
+			return new String[] {};
+		
+		return params.toArray( new String[] {} );
+	}
+	
+	/**
+	 * Adds a param to the list of params for this url. Only the unique
+	 * params are maintained. Duplicate param values are suppressed.
+	 * 
+	 * @param param a param (e.g., "transport=tcp" or "01831864574898475").
+	 */
+	public void addParam( String param )
+	{
+		checkNotNull( param, "param == null" );
+		ensureParams();
+		params.add( param );
+	}
+	
+	/**
+	 * Removes the first param found which starts with the given prefix. The
+	 * search order is not specified, and the params are not maintained in any
+	 * specific order.
+	 * 
+	 * @param prefix the prefix of the param to remove (e.g., "transport=").
+	 * 
+	 * @return the param removed.
+	 */
+	public String removeParam( String prefix )
+	{
+		checkNotNull( prefix, "prefix == null" );
+		
+		if (params == null)
+			return null;
+		
+		for (String p: getParams())
+		{
+			if (p.startsWith( prefix ))
+			{
+				params.remove( p );
+				return p;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Removes all the params.
+	 */
+	public void clearParams()
+	{
+		if (params != null)
+			params.clear();
+	}
+	
+	private void ensureParams()
+	{
+		if (params == null)
+			params = new ArrayList<String>();
+	}
+
+	/////////////////
+	// QUERY TERMS //
+	/////////////////
+	
+	/**
+	 * @return true if there is at least one query term. Query terms
+	 * are of the form name=value.
+	 */
+	public boolean hasTerms()
+	{
+		return terms != null && !terms.isEmpty();
+	}
+	
+	/**
+	 * @param name
+	 * 
+	 * @return true if there is at least one query term with the specified
+	 * name.
+	 */
+	public boolean hasTerm( String name )
+	{
+		checkName( name );
+		
+		if (terms == null)
+			return false;
+		
+		return terms.containsKey( name );
+	}
+	
+	/**
+	 * @param name
+	 * @param value
+	 * @return true if there is a query term with the specified value.
+	 */
+	@SuppressWarnings("unchecked")
+	public boolean hasTerm( String name, String value )
+	{
+		checkName( name );
+		
+		if (terms == null)
+			return false;
+		
+		if (value == null)
+			return hasTerm( name );
+		
+		Object obj = terms.get( name );
+		if (obj == null)
+			return false;
+		
+		if (obj instanceof List)
+			return ((List<String>) obj).contains( value );
+		
+		return obj.equals( value );
+	}
+
+	/**
+	 * @param name
+	 * @param value
+	 * @return true if there is a query term with the specified value.
+	 */
+	public boolean hasTerm( String name, Integer value )
+	{
+		return hasTerm( name, toString( value ) );
+	}
+
+	/**
+	 * @param name
+	 * @param value
+	 * @return true if there is a query term with the specified value.
+	 */
+	public boolean hasTerm( String name, Double value )
+	{
+		return hasTerm( name, toString( value ) );
+	}
+
+	/**
+	 * @param name
+	 * @param value
+	 * @return true if there is a query term with the specified value.
+	 */
+	public boolean hasTerm( String name, Boolean value )
+	{
+		return hasTerm( name, toString( value ) );
+	}
+	
+	/**
+	 * @param name
+	 * @return true if the query term specified by name has multiple values.
+	 */
+	@SuppressWarnings("unchecked")
+	public boolean hasMultipleValues( String name )
+	{
+		checkName( name );
+		
+		if (terms == null)
+			return false;
+		
+		Object obj = terms.get( name );
+		if (obj == null)
+			return false;
+		
+		if (obj instanceof List)
+			return ((List<String>) obj).size() > 1;
+		
+		return false;
+	}
+	
+	/**
+	 * Gets the value of the specified query term.
+	 * 
+	 * @param name
+	 * 
+	 * @return the value of the specified term, or null if not found.
+	 * 
+	 * @throws UnsupportedOperationException if the query term has multiple values.
+	 * Use getTerms(name) instead.
+	 * 
+	 * @see #getTerms(String)
+	 * @see #getIntegerTerm(String)
+	 * @see #getDoubleTerm(String)
+	 */
+	@SuppressWarnings("unchecked")
+	public String getTerm( String name )
+	{
+		checkName( name );
+		
+		if (terms == null)
+			return null;
+		
+		Object obj = terms.get( name );
+		if (obj == null)
+			return null;
+		
+		if (obj instanceof List)
+		{
+			Iterator<String> i = ((List<String>) obj).iterator();
+			
+			if (!i.hasNext())
+				return null;
+			
+			String v = i.next();
+			
+			if (i.hasNext())
+				throw new UnsupportedOperationException( String.format(
+					"term '%s' has multiple values", name ) );
+			
+			return v;
+		}
+		
+		return (String) obj;
+	}
+
+	/**
+	 * @param name
+	 * @param defaultValue
+	 * @return the value of the specified term, or defaultValue if not found.
+	 */
+	public String getTerm( String name, String defaultValue )
+	{
+		String value = getTerm( name );
+		if (value == null)
+			return defaultValue;
+		return value;
+	}
+	
+	/**
+	 * Gets the Integer value of the specified query term.
+	 * @param name
+	 * @return the Integer value, or null if not found.
+	 * @see #getTerm(String)
+	 */
+	public Integer getIntegerTerm( String name )
+	{
+		String s = getTerm( name );
+		if (s == null)
+			return null;
+		return Integer.valueOf( s );
+	}
+
+	/**
+	 * Gets the integer value of the specified query term.
+	 * @param name
+	 * @param defaultValue the value to return if the term is not found.
+	 * @return the integer value, or defaultValue if not found.
+	 * @see #getTerm(String)
+	 */
+	public int getIntegerTerm( String name, int defaultValue )
+	{
+		Integer value = getIntegerTerm( name );
+		if (value == null)
+			return defaultValue;
+		return value;
+	}
+	
+	/**
+	 * Gets the Double value of the specified query term.
+	 * @param name
+	 * @return the Double value, or null if not found.
+	 * @see #getTerm(String)
+	 */
+	public Double getDoubleTerm( String name )
+	{
+		String s = getTerm( name );
+		if (s == null)
+			return null;
+		return Double.valueOf( s );
+	}
+
+	/**
+	 * Gets the double value of the specified query term.
+	 * @param name
+	 * @param defaultValue the value to return if the term is not found.
+	 * @return the double value, or defaultValue if not found.
+	 * @see #getTerm(String)
+	 */
+	public double getDoubleTerm( String name, double defaultValue )
+	{
+		Double value = getDoubleTerm( name );
+		if (value == null)
+			return defaultValue;
+		return value;
+	}
+
+	/**
+	 * Gets the boolean value of the specified query term.
+	 * @param name
+	 * @return the boolean value, or null if not found.
+	 * @see #getTerm(String)
+	 */
+	public Boolean getBooleanTerm( String name )
+	{
+		String s = getTerm( name );
+		if (s == null)
+			return null;
+		return Boolean.valueOf( s );
+	}
+
+	/**
+	 * Gets the boolean value of the specified query term.
+	 * @param name
+	 * @param defaultValue the value to return if the term is not found.
+	 * @return the boolean value, or defaultValue if not found.
+	 * @see #getTerm(String)
+	 */
+	public boolean getBooleanTerm( String name, boolean defaultValue )
+	{
+		Boolean value = getBooleanTerm( name );
+		if (value == null)
+			return defaultValue;
+		return value;
+	}
+	
+	/**
+	 * Gets the values of the specified query term.
+	 * @param name
+	 * @return an iterator over the string values of the query term. May be empty.
+	 */
+	@SuppressWarnings("unchecked")
+	public String[] getTerms( String name )
+	{
+		checkName( name );
+		
+		if (terms == null)
+			return new String[] {};
+		
+		Object obj = terms.get( name );
+		if (obj == null)
+			return new String[] {};
+		
+		if (obj instanceof List)
+			return ((List<String>) obj).toArray( new String[] {} );
+		
+		return new String[] { (String) obj };
+	}
+	
+	/**
+	 * Gets the names of the query terms.
+	 * @return an iterator over the string names.
+	 */
+	public String[] getTermNames()
+	{
+		if (terms == null)
+			return new String[] {};
+		
+		return terms.keySet().toArray( new String[] {} );
+	}
+	
+	/**
+	 * Adds the specified query term to the list of query terms. Duplicate
+	 * name/value pairs are suppressed.
+	 * @param name
+	 * @param value
+	 */
+	@SuppressWarnings("unchecked")
+	public void addTerm( String name, String value )
+	{
+		checkName( name );
+		
+		if (value == null)
+			return;
+		
+		ensureTerms();
+		
+		Object obj = terms.get( name );
+		if (obj == null)
+		{
+			terms.put( name, value );
+			return;
+		}
+		
+		if (obj instanceof List)
+		{
+			List<String> values = (List<String>) obj;
+			if (!values.contains( value ))
+				values.add( value );
+			return;
+		}
+		
+		// obj is not a list but we need one, so replace obj in terms with a
+		// list, then add value to the list.
+		
+		List<String> values = new ArrayList<String>();
+		terms.put( name, values );
+		values.add( (String) obj );
+
+		values.add( value );
+	}
+
+	/**
+	 * Adds the specified query term to the list of query terms. Duplicate
+	 * name/value pairs are suppressed.
+	 * @param name
+	 * @param value
+	 */
+	public void addTerm( String name, Integer value )
+	{
+		addTerm( name, toString( value ) );
+	}
+
+	/**
+	 * Adds the specified query term to the list of query terms. Duplicate
+	 * name/value pairs are suppressed.
+	 * @param name
+	 * @param value
+	 */
+	public void addTerm( String name, Double value )
+	{
+		addTerm( name, toString( value ) );
+	}
+
+	/**
+	 * Adds the specified query term to the list of query terms. Duplicate
+	 * name/value pairs are suppressed.
+	 * @param name
+	 * @param value
+	 */
+	public void addTerm( String name, Boolean value )
+	{
+		addTerm( name, toString( value ) );
+	}
+	
+	/**
+	 * Removes all the values associated with the specified query term.
+	 * @param name
+	 * @return true if something was removed, false otherwise.
+	 */
+	public boolean removeTerm( String name )
+	{
+		checkName( name );
+		
+		if (terms == null)
+			return false;
+		
+		return terms.remove( name ) != null;
+	}
+	
+	/**
+	 * Removes the specified name/value pair from the list of query terms.
+	 * @param name
+	 * @param value
+	 * @return true if the name/value pair was found and removed.
+	 */
+	@SuppressWarnings("unchecked")
+	public boolean removeTerm( String name, String value )
+	{
+		checkName( name );
+		
+		if (terms == null)
+			return false;
+		
+		if (value == null)
+			return removeTerm( name );
+		
+		Object obj = terms.get( name );
+		if (obj == null)
+			return false;
+		
+		if (obj instanceof List)
+		{
+			List<String> values = (List<String>) obj;
+			boolean ok = values.remove( value );
+			if (values.isEmpty())
+				terms.remove( name );
+			return ok;
+		}
+		
+		if (obj.equals( value ))
+		{
+			terms.remove( name );
+			return true;
+		}
+		
+		return false;
+	}
+
+	/**
+	 * Removes the specified name/value pair from the list of query terms.
+	 * @param name
+	 * @param value
+	 * @return true if the name/value pair was found and removed.
+	 */
+	public boolean removeTerm( String name, Integer value )
+	{
+		return removeTerm( name, toString( value ) );
+	}
+
+	/**
+	 * Removes the specified name/value pair from the list of query terms.
+	 * @param name
+	 * @param value
+	 * @return true if the name/value pair was found and removed.
+	 */
+	public boolean removeTerm( String name, Double value )
+	{
+		return removeTerm( name, toString( value ) );
+	}
+
+	/**
+	 * Removes the specified name/value pair from the list of query terms.
+	 * @param name
+	 * @param value
+	 * @return true if the name/value pair was found and removed.
+	 */
+	public boolean removeTerm( String name, Boolean value )
+	{
+		return removeTerm( name, toString( value ) );
+	}
+	
+	/**
+	 * Removes all the query terms.
+	 */
+	public void clearTerms()
+	{
+		if (terms != null)
+			terms.clear();
+	}
+	
+	private void ensureTerms()
+	{
+		if (terms == null)
+			terms = new HashMap<String, Object>();
+	}
+
+	//////////////
+	// FRAGMENT //
+	//////////////
+
+	/**
+	 * @return the fragment.
+	 */
+	public String getFragment()
+	{
+		return fragment;
+	}
+
+	/**
+	 * Sets the fragment.
+	 * 
+	 * @param fragment the fragment to set which may be null but not blank.
+	 */
+	public void setFragment( String fragment )
+	{
+		checkNotBlank( "fragment", fragment );
+		this.fragment = fragment;
+	}
+
+	//////////
+	// UTIL //
+	//////////
+
+	@Override
+	public String toString()
+	{
+		StringBuffer sb = new StringBuffer();
+		
+		escape( sb, scheme );
+		sb.append( ':' );
+		
+		if (host != null)
+		{
+			sb.append( "//" );
+			if (user != null)
+			{
+				escape( sb, user );
+				if (password != null)
+				{
+					sb.append( ':' );
+					escape( sb, password );
+				}
+				sb.append( '@' );
+			}
+			escape( sb, host );
+			if (port != null)
+			{
+				sb.append( ':' );
+				sb.append( port );
+			}
+			sb.append( '/' );
+		}
+		
+		if (uri != null)
+			escape( sb, uri );
+		
+		if (hasParams())
+			paramsToString( sb );
+		
+		if (hasTerms())
+			termsToString( sb );
+		
+		if (fragment != null)
+		{
+			sb.append( '#' );
+			escape( sb, fragment );
+		}
+		
+		return sb.toString();
+	}
+
+	@Override
+	public int hashCode()
+	{
+		int code = 23547853;
+		code ^= hc( scheme );
+		code ^= hc( user );
+		code ^= hc( password );
+		code ^= hc( host );
+		code ^= hc( port );
+		code ^= hc( uri );
+		code ^= hc( params );
+		code ^= hc( terms );
+		code ^= hc( fragment );
+		return code;
+	}
+	
+	private int hc( Map<String, Object> m )
+	{
+		return m != null ? m.hashCode() : 793;
+	}
+
+	private int hc( List<String> s )
+	{
+		return s != null ? s.hashCode() : 161;
+	}
+
+	private int hc( Integer i )
+	{
+		return i != null ? i.hashCode() : 59;
+	}
+
+	private int hc( String s )
+	{
+		return s != null ? s.hashCode() : 91;
+	}
+
+	@Override
+	public boolean equals( Object obj )
+	{
+		if (obj == this)
+			return true;
+		
+		if (obj == null)
+			return false;
+		
+		if (obj.getClass() != URL.class)
+			return false;
+		
+		URL other = (URL) obj;
+		
+		if (!StringUtil.equalsIgnoreCase( scheme, other.scheme ))
+			return false;
+		
+		if (!StringUtil.equals( user, other.user ))
+			return false;
+		
+		if (!StringUtil.equals( password, other.password ))
+			return false;
+		
+		if (!StringUtil.equals( host, other.host ))
+			return false;
+		
+		if (!eq( port, other.port ))
+			return false;
+		
+		if (!StringUtil.equals( uri, other.uri ))
+			return false;
+		
+		if (!eq( params, other.params ))
+			return false;
+		
+		if (!eq( terms, other.terms ))
+			return false;
+		
+		if (!StringUtil.equals( fragment, other.fragment ))
+			return false;
+		
+		return true;
+	}
+	
+	private boolean eq( Object a, Object b )
+	{
+		return a == b || a != null && b != null && a.equals( b );
+	}
+
+	private void paramsToString( StringBuffer sb )
+	{
+		for (String p: getParams())
+		{
+			sb.append( ';' );
+			escape( sb, p );
+		}
+	}
+
+	private void termsToString( StringBuffer sb )
+	{
+		char sep = '?';
+		for (String n: getTermNames())
+		{
+			for (String v: getTerms( n ))
+			{
+				sb.append( sep );
+				escape( sb, n );
+				sb.append( '=' );
+				escape( sb, v );
+				sep = '&';
+			}
+		}
+	}
+
+	/**
+	 * Dumps the url contents for easy viewing.
+	 */
+	public void dump()
+	{
+		System.out.println( "---------------" );
+		System.out.println( "scheme = "+scheme );
+		System.out.println( "user = "+user );
+		System.out.println( "password = "+password );
+		System.out.println( "host = "+host );
+		System.out.println( "port = "+port );
+		System.out.println( "uri = "+uri );
+		System.out.println( "params = "+params );
+		System.out.println( "terms = "+terms );
+		System.out.println( "fragment = "+fragment );
+	}
+
+	private static void escape( StringBuffer sb, String s )
+	{
+		if (s == null)
+		{
+			sb.append( "null" );
+			return;
+		}
+		
+		CharIterator i = new CharIterator( s );
+		while (i.hasNext())
+		{
+			char c = i.next();
+			if (isEscaped( c ))
+			{
+				sb.append( '%' );
+				sb.append( StringUtil.toHex( c >>> 4 & 15 ) );
+				sb.append( StringUtil.toHex( c & 15 ) );
+			}
+			else if (c == ' ')
+			{
+				sb.append( '+' );
+			}
+			else
+			{
+				sb.append( c );
+			}
+		}
+	}
+
+	private static boolean isEscaped( char c )
+	{
+		if (c >= '0' && c <= '9') return false;
+		if (c >= 'A' && c <= 'Z') return false;
+		if (c >= 'a' && c <= 'z') return false;
+		if (c == ' ') return false;
+		if (c == ',') return false;
+		if (c == '.') return false;
+		if (c == '/') return false;
+		if (c == '!') return false;
+		if (c == '$') return false;
+		if (c == '^') return false;
+		if (c == '*') return false;
+		if (c == '(') return false;
+		if (c == ')') return false;
+		if (c == '_') return false;
+		if (c == '-') return false;
+		if (c == '{') return false;
+		if (c == '}') return false;
+		if (c == '[') return false;
+		if (c == ']') return false;
+		if (c == '|') return false;
+		if (c == '\\') return false;
+		return true;
+	}
+
+	private static String unescape( String s )
+	{
+		StringBuffer sb = new StringBuffer();
+		CharIterator i = new CharIterator( s );
+		while (i.hasNext())
+		{
+			char c = i.next();
+			if (c == '%')
+			{
+				char c1 = i.next();
+				char c2 = i.next();
+				sb.append( (char) (StringUtil.fromHex( c1 ) << 4 | StringUtil.fromHex( c2 )) );
+			}
+			else if (c == '+')
+			{
+				sb.append( ' ' );
+			}
+			else
+			{
+				sb.append( c );
+			}
+		}
+		return sb.toString();
+	}
+	
+	private static void checkName( String name )
+	{
+		if (name == null || name.length() == 0)
+			throw new IllegalArgumentException( "name null or empty" );
+	}
+
+	private static String toString( Object value )
+	{
+		return value != null ? value.toString() : null;
+	}
+	
+	private static void checkNotNull( Object v, String msg )
+	{
+		if (v == null)
+			throw new NullPointerException( msg );
+	}
+
+	private static void checkNotBlank( String name, String value )
+	{
+		if (value != null && value.length() == 0)
+			throw new IllegalArgumentException( name+" is blank" );
+	}
+
+	private static void checkNotInteger( String name, String value )
+	{
+		checkNotBlank( name, value );
+		try
+		{
+			Integer.parseInt( value );
+		}
+		catch ( NumberFormatException e )
+		{
+			throw new IllegalArgumentException( name+" is not integer" );
+		}
+	}
+
+	private static List<String> copyList( List<String> params )
+	{
+		// just goes one level deep.
+		
+		if (params == null)
+			return null;
+		
+		return new ArrayList<String>( params );
+	}
+	
+	@SuppressWarnings("unchecked")
+	private static Map<String, Object> copyTerms( Map<String, Object> terms )
+	{
+		if (terms == null)
+			return null;
+		
+		Map<String, Object> nterms = new HashMap<String, Object>();
+		for (Map.Entry<String, Object> me: terms.entrySet())
+		{
+			String name = me.getKey();
+			Object value = me.getValue();
+			if (value instanceof List)
+				value = copyList( (List<String>) value );
+			nterms.put( name, value );
+		}
+		return nterms;
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/AndConstraint.java b/util/src/main/java/org/apache/etch/util/cmd/AndConstraint.java
new file mode 100644
index 0000000..f600601
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/AndConstraint.java
@@ -0,0 +1,54 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * Description of AndConstraint.
+ */
+public class AndConstraint implements Constraint
+{
+	/**
+	 * Constructs the AndConstraint.
+	 * @param a
+	 * @param b
+	 */
+	public AndConstraint( Constraint a, Constraint b )
+	{
+		this.a = a;
+		this.b = b;
+	}
+	
+	private final Constraint a;
+	
+	private final Constraint b;
+	
+	public void checkValue( Object value ) throws Exception
+	{
+		a.checkValue( value );
+		b.checkValue( value );
+	}
+	
+	@Override
+	public String toString()
+	{
+		return "("+a+") AND ("+b+")";
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/BooleanConverter.java b/util/src/main/java/org/apache/etch/util/cmd/BooleanConverter.java
new file mode 100644
index 0000000..c0f7412
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/BooleanConverter.java
@@ -0,0 +1,65 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Handle translation of various types of boolean values.
+ */
+public class BooleanConverter
+{
+	/**
+	 * @param value
+	 * @return result of translation of boolean value.
+	 */
+	public static Boolean valueOf( String value )
+	{
+		Boolean v = values.get( value.toLowerCase() );
+		if (v == null)
+			throw new IllegalArgumentException( "bad boolean value: "+value );
+		return v;
+	}
+	
+	/**
+	 * Defines static key pairs to use for true/false item conversions.
+	 * @param trueKey
+	 * @param falseKey
+	 */
+	public static void define( String trueKey, String falseKey )
+	{
+		if (trueKey != null)
+			values.put( trueKey.toLowerCase(), Boolean.TRUE );
+		
+		if (falseKey != null)
+			values.put( falseKey.toLowerCase(), Boolean.FALSE );
+	}
+	
+	private final static Map<String,Boolean> values = new HashMap<String,Boolean>();
+	static
+	{
+		define( "true", "false" );
+		define( "yes", "no" );
+		define( "1", "0" );
+		define( "enable", "disable" );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/BooleanOption.java b/util/src/main/java/org/apache/etch/util/cmd/BooleanOption.java
new file mode 100644
index 0000000..53e38f5
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/BooleanOption.java
@@ -0,0 +1,54 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * An option whose value is a boolean.
+ */
+public class BooleanOption extends Option
+{
+	/**
+	 * @param cp
+	 * @param tokens
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param flags
+	 * @param defaultValue
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public BooleanOption( CommandParser cp, String tokens, String name, String method,
+		String description, int flags, Boolean defaultValue, Constraint constraint )
+		throws Exception
+	{
+		super( cp, tokens, name, method, PARAMS, description, flags, defaultValue, constraint );
+	}
+	
+	private final static Class<?>[] PARAMS =
+		{ CommandParser.class, Option.class, String.class, Boolean.class };
+
+	@Override
+	protected Object convertValue( String value )
+	{
+		return BooleanConverter.valueOf( value );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/BooleanParameter.java b/util/src/main/java/org/apache/etch/util/cmd/BooleanParameter.java
new file mode 100644
index 0000000..3f7f48f
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/BooleanParameter.java
@@ -0,0 +1,51 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * A parameter whose value is a boolean.
+ */
+public class BooleanParameter extends Parameter
+{
+	/**
+	 * @param cp
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param isRequired
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public BooleanParameter( CommandParser cp, String name, String method,
+		String description, boolean isRequired, Constraint constraint ) throws Exception
+	{
+		super( cp, name, method, PARAMS, description, isRequired, constraint );
+	}
+	
+	private final static Class<?>[] PARAMS =
+		{ CommandParser.class, Parameter.class, Boolean.class };
+
+	@Override
+	public Object convertValue( String value )
+	{
+		return BooleanConverter.valueOf( value );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/CommandParser.java b/util/src/main/java/org/apache/etch/util/cmd/CommandParser.java
new file mode 100644
index 0000000..f1a2ee1
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/CommandParser.java
@@ -0,0 +1,1105 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.apache.etch.util.CharIterator;
+import org.apache.etch.util.StringUtil;
+import org.apache.etch.util.URL;
+
+
+/**
+ * CommandParser implements standard parsing of command lines.
+ * Command line options and parameters are described and then
+ * handling of printing usage and help messages is automatic,
+ * as is distribution of default option values when none is
+ * specified before the first parameter. Data type conversions
+ * and value constraint checking is also supported.
+ */
+public class CommandParser
+{
+	/**
+	 * Constructs a CommandParser for the specified program.
+	 * @param program
+	 */
+	public CommandParser( Program program )
+	{
+		this.program = program;
+	}
+	
+	/**
+	 * Description of prog
+	 */
+	protected final Program program;
+	
+	/**
+	 * Defines an option. Checks option flags and default value.
+	 * @param option
+	 */
+	public void define( Option option )
+	{
+		// hidden options are just that, hidden, they aren't required. hidden means
+		// help doesn't show them. they can still be specified.
+//		if (option.isHidden() && option.getDefaultValues() == null)
+//			throw new IllegalArgumentException( "hidden option '"+option+"' has no default value" );
+
+		// adding hidden to an option just means it isn't shown in the help. it
+		// you shouldn't have to otherwise edit it. rude it is, however, to hide
+		// a required option with no default value.
+//		if (option.isHidden() && option.isSingleton())
+//			throw new IllegalArgumentException( "hidden option '"+option+"' redundantly marked singleton" );
+		
+		if (option.isRequired() && option.getDefaultValues() != null)
+			throw new IllegalArgumentException( "option '"+option+"' with default value redundantly marked required" );
+		
+		// we still want to process hidden options, just not show them.
+		if (true /* !option.isHidden() */)
+		{
+			Iterator<String> i = option.getTokens();
+			while (i.hasNext())
+			{
+				String token = i.next();
+				
+				if (token.startsWith( "--" ))
+				{
+					// long option (e.g., --name)
+
+					String name = token.substring( 2 );
+
+					// rule out empty name
+					if (name.length() == 0)
+						throw new IllegalArgumentException( "long option token '"+token+"' has no chars after the dashes" );
+					
+					// rule out three or more dashes
+					if (name.startsWith( "-" ))
+						throw new IllegalArgumentException( "long option token '"+token+"' starts with three or more dashes" );
+					
+					checkValidChars( name, "long option", token, longTokenChars );
+					defineOption( options, name, option );
+					continue;
+				}
+				
+				if (!token.startsWith( "-" ))
+					throw new IllegalArgumentException( "option token '"+token+"' does not start with dash" );
+				
+				// short option (e.g., -c)
+				
+				String c = token.substring( 1 );
+
+				// rule out any but single char
+				if (c.length() != 1)
+					throw new IllegalArgumentException( "short option token '"+token+"' must have only one char after the dash" );
+
+				checkValidChars( c, "short option", token, shortTokenChars );
+				defineOption( shortOptions, c, option );
+			}
+		}
+		
+		optionList.add( option );
+	}
+	
+	private void checkValidChars( String name, String descr, String token, Pattern pattern )
+	{
+		if (!pattern.matcher( name ).matches())
+			throw new IllegalArgumentException( descr+" token '"+token+"' has bad chars" );
+	}
+	
+	private final Pattern longTokenChars = Pattern.compile( "^[a-z0-9]+(-[a-z0-9]+)*$" );
+	
+	private final Pattern shortTokenChars = Pattern.compile( "^[a-zA-Z0-9]$" );
+	
+	private void defineOption( Map<String, Option> map, String token, Option option )
+	{
+		Option other = map.put( token, option );
+		if (other != null)
+			throw new IllegalArgumentException(
+				"options '"+option+"' and '"+other+"' have overlapping token sets" );
+	}
+
+	/**
+	 * @param parameter
+	 * @param isCatchAll
+	 */
+	public void define( Parameter parameter, boolean isCatchAll )
+	{
+		if (parameter.isRequired() && !lastIsRequired)
+			throw new IllegalArgumentException(
+				"required parameter '"+parameter+"' cannot follow optional one" );
+		
+		lastIsRequired  = parameter.isRequired();
+		
+		if (isCatchAll)
+		{
+			defineCatchAll( parameter );
+			return;
+		}
+		
+		if (catchAllParameter != null)
+			throw new UnsupportedOperationException(
+				"cannot define parameter '"+parameter+"': catch all parameter already defined" );
+		
+		parameters.add( parameter );
+	}
+	
+	/**
+	 * @param parameter
+	 */
+	private void defineCatchAll( Parameter parameter )
+	{
+		if (parameter != null && catchAllParameter != null)
+			throw new UnsupportedOperationException(
+				"cannot define catch all parameter '"+parameter+"': catch all parameter already defined" );
+		
+		catchAllParameter = parameter;
+	}
+	
+	/**
+	 * @param args
+	 * @return true if parsing was sucessful, false otherwise.
+	 * @throws Exception
+	 */
+	public boolean parse( String[] args ) throws Exception
+	{
+		Iterator<Parameter> parametersIterator = getParameters();
+		
+		argsIterator = new StringArrayIterator( args );
+		while (argsIterator.hasNext())
+		{
+			String token = argsIterator.next();
+			
+			if (token.startsWith( "-" ))
+			{
+				// might be a long option (e.g., --name), a short option
+				// (e.g., -c) or a parameter (-).
+				if (token.startsWith( "--" ))
+				{
+					// handle long option (e.g., --name)
+					
+					String[] x = StringUtil.leftSplit( token, '=' );
+					String tok = null;
+					String val = null;
+					if (x != null)
+					{
+						tok = x[0];
+						val = x[1];
+					}
+					else
+					{
+						tok = token;
+						val = null;
+					}
+					
+					Option option = findOption( tok.substring( 2 ) );
+					if (option == null)
+					{
+						report( "unexpected command line option", token, argsIterator );
+						return false;
+					}
+					
+					Object[] values = null;
+					
+					if (option.wantsValue())
+					{
+						values = option.getAndConvertValue( tok, val, argsIterator );
+						if (values == null)
+							return false;
+						
+						if (!option.checkValue( tok, values ))
+							return false;
+					}
+					else
+					{
+						if (val != null)
+							report( "unexpected option value", tok, argsIterator );
+					}
+					
+					if (!option.deliverValue( tok, values, false ))
+						return false;
+					
+					continue;
+				}
+				else if (token.length() > 1)
+				{
+					// handle short option (e.g., -c)
+					
+					CharIterator i = new CharIterator( token.substring( 1 ) );
+					while (i.hasNext())
+					{
+						String tok = String.valueOf( i.next() );
+						
+						Option option = findShortOption( tok );
+						if (option == null)
+						{
+							report( String.format(
+								"unexpected command line option (-%s)", tok ),
+								token, argsIterator );
+							return false;
+						}
+						
+						Object[] values = null;
+						
+						if (option.wantsValue())
+						{
+							String val = rest( i );
+							
+							values = option.getAndConvertValue( tok, val, argsIterator );
+							
+							if (values == null)
+								return false;
+							
+							if (!option.checkValue( tok, values ))
+								return false;
+						}
+						
+						if (!option.deliverValue( tok, values, false ))
+							return false;
+					}
+					continue;
+				}
+				// token is -, which is a parameter, so just fall through...
+			}
+			
+			// ok, we're delivering a non-option value.
+			if (!finalizeOptions( " before the first parameter" ))
+				return false;
+			
+			if (parametersIterator.hasNext() || catchAllParameter != null)
+			{
+				Parameter parameter = parametersIterator.hasNext() ?
+					(Parameter) parametersIterator.next() : catchAllParameter;
+				
+				Object value = parameter.convertValue( token );
+				if (value == null)
+					return false;
+				
+				if (!parameter.checkValue( value ))
+					return false;
+				
+				if (!parameter.deliverValue( value ))
+					return false;
+				
+				if (parameter == catchAllParameter)
+					hasDeliveredToCatchAll = true;
+				
+				continue;
+			}
+			
+			report( "unexpected command line token", token, argsIterator );
+			return false;
+		}
+		
+		// ok, we're about to call run, finalize options
+		
+		if (!finalizeOptions( " on the command line" ))
+			return false;
+		
+		// check for unspecified but required parameters.
+		
+		if (parametersIterator.hasNext())
+		{
+			Parameter parameter = parametersIterator.next();
+			if (parameter.isRequired())
+			{
+				report( "required parameter '"+parameter+"' has not been specified", null, null );
+				return false;
+			}
+		}
+		
+		if (catchAllParameter != null && catchAllParameter.isRequired() && !hasDeliveredToCatchAll)
+		{
+			report( "required parameter '"+catchAllParameter+"' has not been specified", null, null );
+			return false;
+		}
+		
+		return true;
+	}
+	
+	private String rest( CharIterator i )
+	{
+		if (!i.hasNext())
+			return null;
+		
+		StringBuffer sb = new StringBuffer();
+		while (i.hasNext())
+			sb.append( i.next() );
+		return sb.toString();
+	}
+
+	/**
+	 * @return true if there is another token.
+	 */
+	public boolean hasNextToken()
+	{
+		return argsIterator.hasNext();
+	}
+	
+	/**
+	 * @return the next token.
+	 * @throws java.util.NoSuchElementException if there isn't one.
+	 */
+	public String nextToken()
+	{
+		return argsIterator.next();
+	}
+	
+	private Iterator<String> argsIterator;
+	
+	private boolean hasDeliveredToCatchAll = false;
+
+//	/**
+//	 * Delivers an option value from another source.
+//	 * @param token
+//	 * @param strValue
+//	 * @return true if the value was delivered to the option, false otherwise.
+//	 * @throws Exception
+//	 */
+//	public boolean deliverValue( String token, String strValue )
+//		throws Exception
+//	{
+//		Option option = findOption( token );
+//		if (option == null)
+//			throw new Exception( "no such option '"+token+"'" );
+//
+//		if (!option.wantsValue())
+//			throw new Exception( "option '"+token+"' does not accept a value" );
+//
+//		Object value = option.convertValue( strValue );
+//		if (value == null)
+//			return false;
+//
+//		if (!option.checkValue( token, value ))
+//			return false;
+//
+//		return option.deliverValue( token, value, false );
+//	}
+	
+	/**
+	 * Finalizes the options before some important event (described by when).
+	 * 
+	 * @param when
+	 * 
+	 * @return true if the options are ok, false if there is a problem, such
+	 * as a required option without a value, etc.
+	 * 
+	 * @throws Exception
+	 */
+	public boolean finalizeOptions( String when ) throws Exception
+	{
+		if (hasFinalizedOptions)
+			return true;
+		
+		hasFinalizedOptions = true;
+		
+		Iterator<Option> i = getOptionList();
+		while (i.hasNext())
+		{
+			Option option = i.next();
+//			System.out.println( "checking option "+option );
+			if (!isAlreadySpecified( option, false ))
+			{
+				if (option.getDefaultValues() != null)
+				{
+					if (!option.deliverValue( option.getPrimaryToken(),
+							option.getDefaultValues(), true ))
+						return false;
+				}
+				else if (option.isRequired())
+				{
+					// ok, it isn't already specified, it doesn't have a default
+					// value, and it is required. we blow beets.
+					report( "option '"+option+"' must be specified"+when, null, null );
+					return false;
+				}
+			}
+		}
+		
+		return true;
+	}
+	
+	private boolean hasFinalizedOptions = false;
+
+	/**
+	 * @param token
+	 * @return the option matching token or null.
+	 */
+	private Option findOption( String token )
+	{
+		Option o = getOption( token );
+//		System.out.printf( "findOption( %s ) found %s\n", token, o );
+		return o;
+	}
+
+	/**
+	 * @param token
+	 * @return the option matching token or null.
+	 */
+	private Option findShortOption( String token )
+	{
+		Option o = getShortOption( token );
+//		System.out.printf( "findShortOption( %s ) found %s\n", token, o );
+		return o;
+	}
+	
+	/**
+	 * @param msg
+	 * @param token
+	 * @param i
+	 */
+	public void report( String msg, String token, Iterator<String> i )
+	{
+		System.err.print( program );
+		System.err.print( ": " );
+		System.err.print( msg );
+		
+		if (token != null)
+		{
+			System.err.print( ": " );
+			System.err.print( token );
+			while (i != null && i.hasNext())
+			{
+				System.err.print( ' ' );
+				System.err.print( i.next() );
+			}
+		}
+		
+		System.err.println();
+		System.err.flush();
+	}
+	
+	private final Map<String,Option> options = new HashMap<String, Option>();
+	
+	private final Map<String,Option> shortOptions = new HashMap<String, Option>();
+	
+	private final List<Option> optionList = new ArrayList<Option>();
+	
+	private final List<Parameter> parameters = new ArrayList<Parameter>();
+	
+	private Parameter catchAllParameter;
+
+	/**
+	 * @param justUsage true if the
+	 */
+	public void showHelp( boolean justUsage )
+	{
+		System.err.print( "usage: " );
+		
+		System.err.print( program );
+		
+		boolean hasOptions = false;
+		
+		{
+			Iterator<Option> i = getOptionList();
+			while (i.hasNext())
+			{
+				Option option = i.next();
+				if (option.isHidden())
+					continue;
+				
+				// only show [options] if there are any visible options...
+				System.err.print( " [options]" );
+				hasOptions = true;
+				break;
+			}
+		}
+		
+		int brackets = 0;
+		
+		{
+			Iterator<Parameter> i = getParameters();
+			while (i.hasNext())
+			{
+				Parameter parameter = i.next();
+				if (!parameter.isRequired())
+				{
+					brackets++;
+					System.err.print( " [" );
+				}
+				parameter.showShortDescription();
+			}
+		}
+		
+		if (catchAllParameter != null)
+		{
+			if (!catchAllParameter.isRequired())
+			{
+				brackets++;
+				System.err.print( " [" );
+			}
+			catchAllParameter.showShortDescription();
+			System.err.print( " ..." );
+		}
+		
+		while (brackets-- > 0)
+			System.err.print( " ]" );
+		
+		System.err.println();
+		
+		if (!justUsage)
+		{
+			{
+				if (hasOptions)
+				{
+					System.err.println();
+					System.err.println( "OPTIONS:" );
+				}
+				
+				Iterator<Option> i = getOptionList();
+				while (i.hasNext())
+				{
+					Option option = i.next();
+					if (option.isHidden())
+						continue;
+					System.err.println();
+					option.showLongDescription();
+				}
+			}
+			
+			{
+				Iterator<Parameter> i = getParameters();
+				
+				if (i.hasNext() || catchAllParameter != null)
+				{
+					System.err.println();
+					System.err.println( "PARAMETERS:" );
+				}
+				
+				while (i.hasNext())
+				{
+					Parameter parameter = i.next();
+					System.err.println();
+					parameter.showLongDescription();
+				}
+			}
+			
+			if (catchAllParameter != null)
+			{
+				System.err.println();
+				catchAllParameter.showLongDescription();
+			}
+		}
+	}
+
+	/**
+	 * Checks whether the option has already been specified or
+	 * not, and marks it as having been specified.
+	 * @param option
+	 * @param update
+	 * @return true if the option has already been specified (other than by default).
+	 */
+	public boolean isAlreadySpecified( Option option, boolean update )
+	{
+		if (specifiedOptions.contains( option ))
+			return true;
+		
+		if (update)
+			specifiedOptions.add( option );
+		
+		return false;
+	}
+	
+	private Set<Option> specifiedOptions = new HashSet<Option>();
+
+	private boolean lastIsRequired = true;
+
+	/**
+	 * @return an iterator over parameters.
+	 */
+	private Iterator<Parameter> getParameters()
+	{
+		return parameters.iterator();
+	}
+
+	/**
+	 * @param token
+	 * @return the option for the specified token, or null.
+	 */
+	public Option getOption( String token )
+	{
+		return options.get( token );
+	}
+
+	/**
+	 * @param token
+	 * @return the option for the specified token, or null.
+	 */
+	public Option getShortOption( String token )
+	{
+		return shortOptions.get( token );
+	}
+	
+	private Iterator<Option> getOptionList()
+	{
+		return optionList.iterator();
+	}
+
+	////////////////////////////////
+	// DEFINE PARAMETER SHORTCUTS //
+	////////////////////////////////
+	
+	/**
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param isRequired
+	 * @param isCatchAll
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public void defineBooleanParameter( String name, String method, String description,
+		boolean isRequired, boolean isCatchAll, Constraint constraint ) throws Exception
+	{
+		define( new BooleanParameter( this, name, method, description,
+			isRequired, constraint ), isCatchAll );
+	}
+	
+	/**
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param isRequired
+	 * @param isCatchAll
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public void defineDoubleParameter( String name, String method, String description,
+		boolean isRequired, boolean isCatchAll, Constraint constraint ) throws Exception
+	{
+		define( new DoubleParameter( this, name, method, description,
+			isRequired, constraint ), isCatchAll );
+	}
+	
+	/**
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param isRequired
+	 * @param isCatchAll
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public void defineFileParameter( String name, String method, String description,
+		boolean isRequired, boolean isCatchAll, Constraint constraint ) throws Exception
+	{
+		define( new FileParameter( this, name, method, description,
+			isRequired, constraint ), isCatchAll );
+	}
+	
+	/**
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param isRequired
+	 * @param isCatchAll
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public void defineIntegerParameter( String name, String method, String description,
+		boolean isRequired, boolean isCatchAll, Constraint constraint ) throws Exception
+	{
+		define( new IntegerParameter( this, name, method, description,
+			isRequired, constraint ), isCatchAll );
+	}
+	
+	/**
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param isRequired
+	 * @param isCatchAll
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public void defineStringParameter( String name, String method, String description,
+		boolean isRequired, boolean isCatchAll, Constraint constraint ) throws Exception
+	{
+		define( new StringParameter( this, name, method, description,
+			isRequired, constraint ), isCatchAll );
+	}
+	
+	/**
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param isRequired
+	 * @param isCatchAll
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public void defineUrlParameter( String name, String method, String description,
+		boolean isRequired, boolean isCatchAll, Constraint constraint ) throws Exception
+	{
+		define( new UrlParameter( this, name, method, description,
+			isRequired, constraint ), isCatchAll );
+	}
+
+	/////////////////////////////
+	// DEFINE OPTION SHORTCUTS //
+	/////////////////////////////
+
+	/**
+	 * Defines a boolean option. The value of the boolean option may be
+	 * specified as true, false, yes, no, 1, 0, enable, or disable (e.g., -x0
+	 * would specify the boolean option -x as false).
+	 * 
+	 * @param tokens a sequence of short and long tokens which are used to
+	 * specify the option (e.g., "-x|--extend"). The tokens are separated from
+	 * each other by vertical bar, comma, semi-colon, or any sort of whitespace.
+	 * The tokens come in short (-x) and long (--extend) varieties. Short tokens
+	 * may only have a single alphanumeric character after the dash. Case is
+	 * significant. Long tokens must match this pattern: [a-z0-9]+(-[a-z0-9]+)*.
+	 * That is, one or more alphanumeric characters broken up by single internal
+	 * dashes. No upper case. Note that -x and --x are not the same.
+	 * 
+	 * @param name the name of the value of the option.
+	 * 
+	 * @param method the name of a method of the target class to call with the
+	 * option when it is specified or defaulted. The method must have the
+	 * signature boolean method(CommandParser cp, Option option, String token,
+	 * Boolean value) or void method(CommandParser cp, Option option, String
+	 * token, Boolean value).
+	 * 
+	 * @param description a description of the option which is formatted into a
+	 * help message for the command.
+	 * 
+	 * @param flags some flag values which may be or'ed together.
+	 * 
+	 * @param defaultValue a default value for the option.
+	 * 
+	 * @param constraint a constraint expression for values of the option.
+	 * 
+	 * @throws Exception if there are problems with the tokens, the method, or
+	 * the flags.
+	 * 
+	 * @see Option#HIDDEN
+	 * @see Option#NONE
+	 * @see Option#REQUIRED
+	 * @see Option#SINGLETON
+	 */
+	public void defineBooleanOption( String tokens, String name, String method,
+		String description, int flags, Boolean defaultValue, Constraint constraint )
+		throws Exception
+	{
+		define( new BooleanOption( this, tokens, name, method, description, flags,
+			defaultValue, constraint ) );
+	}
+
+	/**
+	 * Defines a double option. The value of the double option may be specified
+	 * as any valid floating point number (e.g., -x0.1 would specify the double
+	 * option -x as 0.1).
+	 * 
+	 * @param tokens a sequence of short and long tokens which are used to
+	 * specify the option (e.g., "-x|--extend"). The tokens are separated from
+	 * each other by vertical bar, comma, semi-colon, or any sort of whitespace.
+	 * The tokens come in short (-x) and long (--extend) varieties. Short tokens
+	 * may only have a single alphanumeric character after the dash. Case is
+	 * significant. Long tokens must match this pattern: [a-z0-9]+(-[a-z0-9]+)*.
+	 * That is, one or more alphanumeric characters broken up by single internal
+	 * dashes. No upper case. Note that -x and --x are not the same.
+	 * 
+	 * @param name the name of the value of the option.
+	 * 
+	 * @param method the name of a method of the target class to call with the
+	 * option when it is specified or defaulted. The method must have the
+	 * signature boolean method(CommandParser cp, Option option, String token,
+	 * Double value) or void method(CommandParser cp, Option option, String
+	 * token, Double value).
+	 * 
+	 * @param description a description of the option which is formatted into a
+	 * help message for the command.
+	 * 
+	 * @param flags some flag values which may be or'ed together.
+	 * 
+	 * @param defaultValue a default value for the option.
+	 * 
+	 * @param constraint a constraint expression for values of the option.
+	 * 
+	 * @throws Exception if there are problems with the tokens, the method, or
+	 * the flags.
+	 * 
+	 * @see Option#HIDDEN
+	 * @see Option#NONE
+	 * @see Option#REQUIRED
+	 * @see Option#SINGLETON
+	 */
+	public void defineDoubleOption( String tokens, String name, String method,
+		String description, int flags, Double defaultValue, Constraint constraint )
+		throws Exception
+	{
+		define( new DoubleOption( this, tokens, name, method, description, flags,
+			defaultValue, constraint ) );
+	}
+
+	/**
+	 * Defines a file option. The value of the file option may be specified
+	 * as any valid file or directory name (e.g., -xfoo.txt would specify the
+	 * file option -x as foo.txt).
+	 * 
+	 * @param tokens a sequence of short and long tokens which are used to
+	 * specify the option (e.g., "-x|--extend"). The tokens are separated from
+	 * each other by vertical bar, comma, semi-colon, or any sort of whitespace.
+	 * The tokens come in short (-x) and long (--extend) varieties. Short tokens
+	 * may only have a single alphanumeric character after the dash. Case is
+	 * significant. Long tokens must match this pattern: [a-z0-9]+(-[a-z0-9]+)*.
+	 * That is, one or more alphanumeric characters broken up by single internal
+	 * dashes. No upper case. Note that -x and --x are not the same.
+	 * 
+	 * @param name the name of the value of the option.
+	 * 
+	 * @param method the name of a method of the target class to call with the
+	 * option when it is specified or defaulted. The method must have the
+	 * signature boolean method(CommandParser cp, Option option, String token,
+	 * File value) or void method(CommandParser cp, Option option, String
+	 * token, File value).
+	 * 
+	 * @param description a description of the option which is formatted into a
+	 * help message for the command.
+	 * 
+	 * @param flags some flag values which may be or'ed together.
+	 * 
+	 * @param defaultValue a default value for the option.
+	 * 
+	 * @param constraint a constraint expression for values of the option.
+	 * 
+	 * @throws Exception if there are problems with the tokens, the method, or
+	 * the flags.
+	 * 
+	 * @see Option#HIDDEN
+	 * @see Option#NONE
+	 * @see Option#REQUIRED
+	 * @see Option#SINGLETON
+	 */
+	public void defineFileOption( String tokens, String name, String method,
+		String description, int flags, File defaultValue, Constraint constraint )
+		throws Exception
+	{
+		define( new FileOption( this, tokens, name, method, description, flags,
+			defaultValue, constraint ) );
+	}
+
+	/**
+	 * Defines an integer option. The value of the integer option may be specified
+	 * as any valid integral number (e.g., -x123 would specify the integer
+	 * option -x as 123).
+	 * 
+	 * @param tokens a sequence of short and long tokens which are used to
+	 * specify the option (e.g., "-x|--extend"). The tokens are separated from
+	 * each other by vertical bar, comma, semi-colon, or any sort of whitespace.
+	 * The tokens come in short (-x) and long (--extend) varieties. Short tokens
+	 * may only have a single alphanumeric character after the dash. Case is
+	 * significant. Long tokens must match this pattern: [a-z0-9]+(-[a-z0-9]+)*.
+	 * That is, one or more alphanumeric characters broken up by single internal
+	 * dashes. No upper case. Note that -x and --x are not the same.
+	 * 
+	 * @param name the name of the value of the option.
+	 * 
+	 * @param method the name of a method of the target class to call with the
+	 * option when it is specified or defaulted. The method must have the
+	 * signature boolean method(CommandParser cp, Option option, String token,
+	 * Integer value) or void method(CommandParser cp, Option option, String
+	 * token, Integer value).
+	 * 
+	 * @param description a description of the option which is formatted into a
+	 * help message for the command.
+	 * 
+	 * @param flags some flag values which may be or'ed together.
+	 * 
+	 * @param defaultValue a default value for the option.
+	 * 
+	 * @param constraint a constraint expression for values of the option.
+	 * 
+	 * @throws Exception if there are problems with the tokens, the method, or
+	 * the flags.
+	 * 
+	 * @see Option#HIDDEN
+	 * @see Option#NONE
+	 * @see Option#REQUIRED
+	 * @see Option#SINGLETON
+	 */
+	public void defineIntegerOption( String tokens, String name, String method,
+		String description, int flags, Integer defaultValue, Constraint constraint )
+		throws Exception
+	{
+		define( new IntegerOption( this, tokens, name, method, description, flags,
+			defaultValue, constraint ) );
+	}
+
+	/**
+	 * @param tokens
+	 * @param method
+	 * @param description
+	 * @param flags
+	 * @throws Exception
+	 */
+	public void defineNullOption( String tokens, String method, String description,
+		int flags ) throws Exception
+	{
+		define( new NullOption( this, tokens, method, description, flags ) );
+	}
+
+	/**
+	 * Defines a string option. The value of the string option may be specified
+	 * as any valid characters (e.g., -xxyz would specify the string
+	 * option -x as xyz).
+	 * 
+	 * @param tokens a sequence of short and long tokens which are used to
+	 * specify the option (e.g., "-x|--extend"). The tokens are separated from
+	 * each other by vertical bar, comma, semi-colon, or any sort of whitespace.
+	 * The tokens come in short (-x) and long (--extend) varieties. Short tokens
+	 * may only have a single alphanumeric character after the dash. Case is
+	 * significant. Long tokens must match this pattern: [a-z0-9]+(-[a-z0-9]+)*.
+	 * That is, one or more alphanumeric characters broken up by single internal
+	 * dashes. No upper case. Note that -x and --x are not the same.
+	 * 
+	 * @param name the name of the value of the option.
+	 * 
+	 * @param method the name of a method of the target class to call with the
+	 * option when it is specified or defaulted. The method must have the
+	 * signature boolean method(CommandParser cp, Option option, String token,
+	 * String value) or void method(CommandParser cp, Option option, String
+	 * token, String value).
+	 * 
+	 * @param description a description of the option which is formatted into a
+	 * help message for the command.
+	 * 
+	 * @param flags some flag values which may be or'ed together.
+	 * 
+	 * @param defaultValue a default value for the option.
+	 * 
+	 * @param constraint a constraint expression for values of the option.
+	 * 
+	 * @throws Exception if there are problems with the tokens, the method, or
+	 * the flags.
+	 * 
+	 * @see Option#HIDDEN
+	 * @see Option#NONE
+	 * @see Option#REQUIRED
+	 * @see Option#SINGLETON
+	 */
+	public void defineStringOption( String tokens, String name, String method,
+		String description, int flags, String defaultValue, Constraint constraint )
+		throws Exception
+	{
+		define( new StringOption( this, tokens, name, method, description,
+			flags, defaultValue, constraint ) );
+	}
+
+	/**
+	 * Defines a mysterious thing.
+	 * 
+	 * @param tokens a sequence of short and long tokens which are used to
+	 * specify the option (e.g., "-x|--extend"). The tokens are separated from
+	 * each other by vertical bar, comma, semi-colon, or any sort of whitespace.
+	 * The tokens come in short (-x) and long (--extend) varieties. Short tokens
+	 * may only have a single alphanumeric character after the dash. Case is
+	 * significant. Long tokens must match this pattern: [a-z0-9]+(-[a-z0-9]+)*.
+	 * That is, one or more alphanumeric characters broken up by single internal
+	 * dashes. No upper case. Note that -x and --x are not the same.
+	 * 
+	 * @param names the names of the values of the option.
+	 * 
+	 * @param method the name of a method of the target class to call with the
+	 * option when it is specified or defaulted. The method must have the
+	 * signature boolean method(CommandParser cp, Option option, String token,
+	 * Object[] values) or void method(CommandParser cp, Option option, String
+	 * token, Object[] value).
+	 * 
+	 * @param description a description of the option which is formatted into a
+	 * help message for the command.
+	 * 
+	 * @param flags some flag values which may be or'ed together.
+	 * 
+	 * @param defaultValues default values for the option.
+	 * 
+	 * @param constraints constraint expressions for values of the option.
+	 * 
+	 * @throws Exception if there are problems with the tokens, the method, or
+	 * the flags.
+	 * 
+	 * @see Option#HIDDEN
+	 * @see Option#NONE
+	 * @see Option#REQUIRED
+	 * @see Option#SINGLETON
+	 */
+	public void defineStringArrayOption( String tokens, String[] names,
+		String method, String description, int flags, String[] defaultValues,
+		Constraint[] constraints ) throws Exception
+	{
+		define( new StringArrayOption( this, tokens, names, method,
+			description, flags, defaultValues, constraints ) );
+	}
+
+	/**
+	 * Defines a url option. The value of the url option may be specified
+	 * as any valid url (e.g., -xhttp://foo.com would specify the url
+	 * option -x as http://foo.com).
+	 * 
+	 * @param tokens a sequence of short and long tokens which are used to
+	 * specify the option (e.g., "-x|--extend"). The tokens are separated from
+	 * each other by vertical bar, comma, semi-colon, or any sort of whitespace.
+	 * The tokens come in short (-x) and long (--extend) varieties. Short tokens
+	 * may only have a single alphanumeric character after the dash. Case is
+	 * significant. Long tokens must match this pattern: [a-z0-9]+(-[a-z0-9]+)*.
+	 * That is, one or more alphanumeric characters broken up by single internal
+	 * dashes. No upper case. Note that -x and --x are not the same.
+	 * 
+	 * @param name the name of the value of the option.
+	 * 
+	 * @param method the name of a method of the target class to call with the
+	 * option when it is specified or defaulted. The method must have the
+	 * signature boolean method(CommandParser cp, Option option, String token,
+	 * URL value) or void method(CommandParser cp, Option option, String
+	 * token, URL value).
+	 * 
+	 * @param description a description of the option which is formatted into a
+	 * help message for the command.
+	 * 
+	 * @param flags some flag values which may be or'ed together.
+	 * 
+	 * @param defaultValue a default value for the option.
+	 * 
+	 * @param constraint a constraint expression for values of the option.
+	 * 
+	 * @throws Exception if there are problems with the tokens, the method, or
+	 * the flags.
+	 * 
+	 * @see Option#HIDDEN
+	 * @see Option#NONE
+	 * @see Option#REQUIRED
+	 * @see Option#SINGLETON
+	 */
+	public void defineUrlOption( String tokens, String name, String method,
+		String description, int flags, URL defaultValue, Constraint constraint )
+		throws Exception
+	{
+		define( new UrlOption( this, tokens, name, method, description, flags,
+			defaultValue, constraint ) );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/Constraint.java b/util/src/main/java/org/apache/etch/util/cmd/Constraint.java
new file mode 100644
index 0000000..934275f
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/Constraint.java
@@ -0,0 +1,36 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * Constraint allows situational conditions to be placed upon
+ * values otherwise acceptable given an item's type. Thus, you
+ * can have an item whose value is >= 0, or whose value is a
+ * readable file, etc.
+ */
+public interface Constraint
+{
+	/**
+	 * @param value
+	 * @throws Exception with a message if the value is bad.
+	 */
+	public void checkValue( Object value ) throws Exception;
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/DoubleOption.java b/util/src/main/java/org/apache/etch/util/cmd/DoubleOption.java
new file mode 100644
index 0000000..92603f8
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/DoubleOption.java
@@ -0,0 +1,54 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * An option whose value is a double.
+ */
+public class DoubleOption extends Option
+{
+	/**
+	 * @param cp
+	 * @param tokens
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param flags
+	 * @param defaultValue
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public DoubleOption( CommandParser cp, String tokens, String name, String method,
+		String description, int flags, Double defaultValue, Constraint constraint )
+		throws Exception
+	{
+		super( cp, tokens, name, method, PARAMS, description, flags, defaultValue, constraint );
+	}
+	
+	private final static Class<?>[] PARAMS =
+		{ CommandParser.class, Option.class, String.class, Double.class };
+
+	@Override
+	protected Object convertValue( String value )
+	{
+		return new Double( value );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/DoubleParameter.java b/util/src/main/java/org/apache/etch/util/cmd/DoubleParameter.java
new file mode 100644
index 0000000..37a5bf2
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/DoubleParameter.java
@@ -0,0 +1,51 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * A parameter whose value is a double.
+ */
+public class DoubleParameter extends Parameter
+{
+	/**
+	 * @param cp
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param isRequired
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public DoubleParameter( CommandParser cp, String name, String method,
+		String description, boolean isRequired, Constraint constraint ) throws Exception
+	{
+		super( cp, name, method, PARAMS, description, isRequired, constraint );
+	}
+	
+	private final static Class<?>[] PARAMS =
+		{ CommandParser.class, Parameter.class, Double.class };
+
+	@Override
+	public Object convertValue( String value )
+	{
+		return new Double( value );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/FileOption.java b/util/src/main/java/org/apache/etch/util/cmd/FileOption.java
new file mode 100644
index 0000000..0f69b4b
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/FileOption.java
@@ -0,0 +1,56 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+import java.io.File;
+
+/**
+ * An option whose value is a file.
+ */
+public class FileOption extends Option
+{
+	/**
+	 * @param cp
+	 * @param tokens
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param flags
+	 * @param defaultValue
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public FileOption( CommandParser cp, String tokens, String name, String method,
+		String description, int flags, File defaultValue, Constraint constraint )
+		throws Exception
+	{
+		super( cp, tokens, name, method, PARAMS, description, flags, defaultValue, constraint );
+	}
+	
+	private final static Class<?>[] PARAMS =
+		{ CommandParser.class, Option.class, String.class, File.class };
+
+	@Override
+	protected Object convertValue( String value )
+	{
+		return new File( value );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/FileParameter.java b/util/src/main/java/org/apache/etch/util/cmd/FileParameter.java
new file mode 100644
index 0000000..f78c48a
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/FileParameter.java
@@ -0,0 +1,53 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+import java.io.File;
+
+/**
+ * A parameter whose value is a file.
+ */
+public class FileParameter extends Parameter
+{
+	/**
+	 * @param cp
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param isRequired
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public FileParameter( CommandParser cp, String name, String method,
+		String description, boolean isRequired, Constraint constraint ) throws Exception
+	{
+		super( cp, name, method, PARAMS, description, isRequired, constraint );
+	}
+	
+	private final static Class<?>[] PARAMS =
+		{ CommandParser.class, Parameter.class, File.class };
+
+	@Override
+	public Object convertValue( String value )
+	{
+		return new File( value );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/IntRangeConstraint.java b/util/src/main/java/org/apache/etch/util/cmd/IntRangeConstraint.java
new file mode 100644
index 0000000..2ab90d8
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/IntRangeConstraint.java
@@ -0,0 +1,59 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * Description of IntRangeConstraint
+ */
+public class IntRangeConstraint implements Constraint
+{
+	/**
+	 * Constructs the IntRangeConstraint.
+	 *
+	 * @param min the minimum value allowed.
+	 * 
+	 * @param max the maximum value allowed.
+	 */
+	public IntRangeConstraint( int min, int max )
+	{
+		if (min > max)
+			throw new IllegalArgumentException( "min > max" );
+		this.min = min;
+		this.max = max;
+	}
+	
+	private final int min;
+	
+	private final int max;
+	
+	public void checkValue( Object value ) throws Exception
+	{
+		int v = ((Integer) value).intValue();
+		if (v < min || v > max)
+			throw new Exception( "value not in range "+min+" to "+max );
+	}
+	
+	@Override
+	public String toString()
+	{
+		return "value must be in range "+min+" to "+max;
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/IntegerOption.java b/util/src/main/java/org/apache/etch/util/cmd/IntegerOption.java
new file mode 100644
index 0000000..ac8e6ba
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/IntegerOption.java
@@ -0,0 +1,58 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * An option whose value is an integer.
+ */
+public class IntegerOption extends Option
+{
+	/**
+	 * Method should be declared as:
+	 * 
+	 * public boolean method( CommandParser cp, Option option, String token, Integer value );
+	 * 
+	 * @param cp
+	 * @param tokens
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param flags
+	 * @param defaultValue
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public IntegerOption( CommandParser cp, String tokens, String name, String method,
+		String description, int flags, Integer defaultValue, Constraint constraint )
+		throws Exception
+	{
+		super( cp, tokens, name, method, PARAMS, description, flags, defaultValue, constraint );
+	}
+	
+	private final static Class<?>[] PARAMS =
+		{ CommandParser.class, Option.class, String.class, Integer.class };
+
+	@Override
+	protected Object convertValue( String value )
+	{
+		return Integer.valueOf( value );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/IntegerParameter.java b/util/src/main/java/org/apache/etch/util/cmd/IntegerParameter.java
new file mode 100644
index 0000000..eb90731
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/IntegerParameter.java
@@ -0,0 +1,51 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * A parameter whose value is an integer.
+ */
+public class IntegerParameter extends Parameter
+{
+	/**
+	 * @param cp
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param isRequired
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public IntegerParameter( CommandParser cp, String name, String method,
+		String description, boolean isRequired, Constraint constraint ) throws Exception
+	{
+		super( cp, name, method, PARAMS, description, isRequired, constraint );
+	}
+	
+	private final static Class<?>[] PARAMS =
+		{ CommandParser.class, Parameter.class, Integer.class };
+
+	@Override
+	public Object convertValue( String value )
+	{
+		return Integer.valueOf( value );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/NullOption.java b/util/src/main/java/org/apache/etch/util/cmd/NullOption.java
new file mode 100644
index 0000000..a49996d
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/NullOption.java
@@ -0,0 +1,65 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+import org.apache.etch.util.Assertion;
+
+/**
+ * An option which has no value.
+ */
+public class NullOption extends Option
+{
+	/**
+	 * @param cp
+	 * @param tokens
+	 * @param method
+	 * @param description
+	 * @param flags
+	 * @throws Exception
+	 */
+	public NullOption( CommandParser cp, String tokens, String method,
+		String description, int flags ) throws Exception
+	{
+		super( cp, tokens, (String[]) null, method, PARAMS, description, flags, null, null );
+	}
+	
+	private final static Class<?>[] PARAMS =
+		{ CommandParser.class, Option.class, String.class };
+	
+	@Override
+	public boolean wantsValue()
+	{
+		return false;
+	}
+
+	@Override
+	protected Object convertValue( String value )
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	protected Object[] getArgs( String token, Object value )
+	{
+		Assertion.check( value == null, "value == null" );
+		return new Object[] { getCommandParser(), this, token };
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/OneOfConstraint.java b/util/src/main/java/org/apache/etch/util/cmd/OneOfConstraint.java
new file mode 100644
index 0000000..52fda5d
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/OneOfConstraint.java
@@ -0,0 +1,68 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+import java.util.HashSet;
+import java.util.Set;
+
+
+/**
+ * A Constraint which limits a value to one of a few
+ * choices.
+ */
+public class OneOfConstraint implements Constraint
+{
+	/**
+	 * Constructs the OneOfConstraint.
+	 *
+	 * @param value the allowed values
+	 */
+	public OneOfConstraint( String ... value )
+	{
+		set = new HashSet<String>();
+		for (String s: value)
+			set.add( s );
+	}
+
+	/**
+	 * Constructs the OneOfConstraint.
+	 *
+	 * @param set the set of allowed values.
+	 */
+	public OneOfConstraint( Set<String> set )
+	{
+		this.set = set;
+	}
+	
+	private final Set<String> set;
+	
+	@Override
+	public String toString()
+	{
+		return "one of "+set;
+	}
+	
+	public void checkValue( Object value ) throws Exception
+	{
+		if (!set.contains( value ))
+			throw new Exception( ""+value+" is not valid, expected one of "+set );
+	}
+}
\ No newline at end of file
diff --git a/util/src/main/java/org/apache/etch/util/cmd/OptParamBase.java b/util/src/main/java/org/apache/etch/util/cmd/OptParamBase.java
new file mode 100644
index 0000000..63405cd
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/OptParamBase.java
@@ -0,0 +1,288 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+import java.lang.reflect.Method;
+
+/**
+ * Shared base class of options and parameters.
+ */
+abstract public class OptParamBase
+{
+	/**
+	 * @param cp
+	 * @param name
+	 * @param method
+	 * @param params
+	 * @param description
+	 * @param isRequired
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public OptParamBase( CommandParser cp, String name, String method,
+		Class<?>[] params, String description, boolean isRequired,
+		Constraint constraint ) throws Exception
+	{
+		this.cp = cp;
+		names = new String[] { name };
+		this.method = findMethod( cp.program, method, params );
+		this.description = description;
+		this.isRequired = isRequired;
+		if (constraint != null)
+			constraints = new Constraint[] { constraint };
+		else
+			constraints = null;
+	}
+	
+	/**
+	 * @param cp
+	 * @param names
+	 * @param method
+	 * @param params
+	 * @param description
+	 * @param isRequired
+	 * @param constraints
+	 * @throws Exception
+	 */
+	public OptParamBase( CommandParser cp, String[] names, String method,
+		Class<?>[] params, String description, boolean isRequired,
+		Constraint[] constraints ) throws Exception
+	{
+		if (constraints != null && constraints.length != names.length)
+			throw new IllegalArgumentException(
+				"constraints.length != names.length" );
+		
+		this.cp = cp;
+		this.names = names;
+		this.method = findMethod( cp.program, method, params );
+		this.description = description;
+		this.isRequired = isRequired;
+		this.constraints = constraints;
+	}
+	
+	private final CommandParser cp;
+	
+	private final String[] names;
+
+	private final Method method;
+	
+	private final String description;
+	
+	private final boolean isRequired;
+	
+	private final Constraint[] constraints;
+	
+	/**
+	 * @return the command parser of this item.
+	 */
+	public CommandParser getCommandParser()
+	{
+		return cp;
+	}
+	
+	/**
+	 * @return the name of this item.
+	 */
+	public String[] getNames()
+	{
+		return names;
+	}
+	
+	/**
+	 * @return the description of this item.
+	 */
+	public String getDescription()
+	{
+		return description;
+	}
+	
+	/**
+	 * @return true if this item is required.
+	 */
+	public boolean isRequired()
+	{
+		return isRequired;
+	}
+	
+	//////////
+	// HELP //
+	//////////
+	
+	/**
+	 * Shows a very short synopsis of the item for the command line usage message.
+	 *
+	 */
+	abstract public void showShortDescription();
+	
+	/**
+	 * Shows the longer "help" description which appears underneath the
+	 * command line usage message.
+	 *
+	 */
+	abstract public void showLongDescription();
+
+	/**
+	 * Shows the text description of the item.
+	 */
+	protected void showDescription()
+	{
+		System.err.print( DESC_FLAG );
+		System.err.println( description );
+	}
+
+	/**
+	 * Shows whether the item is required or not.
+	 */
+	protected void showIsRequired()
+	{
+		if (isRequired())
+		{
+			System.err.print( DESC_FLAG );
+			System.err.println( "required (must be specified)." );
+		}
+	}
+	
+	/**
+	 * Shows the constraint if any.
+	 */
+	protected void showConstraint()
+	{
+		if (constraints != null)
+		{
+			int n = constraints.length;
+			System.err.print( DESC_FLAG );
+			
+			if (n > 1)
+				System.err.print( "constraint: {" );
+			else
+				System.err.print( "constraint: " );
+			
+			for (Constraint constraint: constraints)
+			{
+				System.err.print( ' ' );
+				System.err.print( constraint );
+			}
+			
+			if (n > 1)
+				System.err.println( " }" );
+			else
+				System.err.println();
+		}
+	}
+	
+	/**
+	 * Flag value to use at the beginning of the line for the
+	 * name of the item.
+	 */
+	protected final static String NAME_FLAG = "   ";
+	
+	/**
+	 * Flag value to use at beginning of the line for descriptive
+	 * text of an item.
+	 */
+	protected final static String DESC_FLAG = "      # ";
+	
+	///////////
+	// VALUE //
+	///////////
+	
+	/**
+	 * Invokes the constraint checkValue method if there is
+	 * a constraint.
+	 * 
+	 * @param who
+	 * 
+	 * @param values
+	 * 
+	 * @return true if the parameter is ok, false otherwise. If false
+	 * is returned, a message has been printed on System.err.
+	 */
+	public boolean checkValue( String who, Object[] values )
+	{
+		if (constraints != null)
+		{
+			int n = constraints.length;
+			for (int i = 0; i < n; i++)
+			{
+				Constraint constraint = constraints[i];
+				
+				if (constraint == null)
+					continue;
+				
+				try
+				{
+					constraint.checkValue( values[i] );
+				}
+				catch ( Exception e )
+				{
+					System.err.print( who );
+					System.err.print( ": validation of value " );
+					System.err.print( names[i] );
+					System.err.print( "='" );
+					System.err.print( values[i] );
+					System.err.print( "' failed: " );
+					System.err.println( e.getMessage() );
+					return false;
+				}
+			}
+		}
+		return true;
+	}
+	
+	/**
+	 * @param value
+	 * @return value converted as appropriate for this item
+	 */
+	abstract protected Object convertValue( String value );
+
+	////////////
+	// METHOD //
+	////////////
+
+	/**
+	 * @param program
+	 * @param method
+	 * @param params
+	 * @return the method for prog given params.
+	 * @throws Exception
+	 */
+	private static Method findMethod( Program program, String method,
+		Class<?>[] params ) throws Exception
+	{
+		return program.getClass().getMethod( method, params );
+	}
+
+	/**
+	 * @param args
+	 * @return value returned from method, or true if null returned.
+	 * @throws Exception
+	 */
+	public boolean callMethod( Object[] args )
+		throws Exception
+	{
+		Object result = method.invoke( cp.program, args );
+		
+		if (result == null)
+			return true;
+		
+		return ((Boolean) result).booleanValue();
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/Option.java b/util/src/main/java/org/apache/etch/util/cmd/Option.java
new file mode 100644
index 0000000..28a1262
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/Option.java
@@ -0,0 +1,425 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * A command line value which is introduced by a specified token.
+ * An option is not dependent upon position on the command line
+ * to be recognized (but still, position on the command line might
+ * be important).
+ */
+abstract public class Option extends OptParamBase
+{
+	/**
+	 * @param cp
+	 * @param tokens
+	 * @param name
+	 * @param method
+	 * @param params
+	 * @param description
+	 * @param flags
+	 * @param defaultValue
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public Option( CommandParser cp, String tokens, String name, String method,
+		Class<?>[] params, String description, int flags, Object defaultValue,
+		Constraint constraint ) throws Exception
+	{
+		super( cp, name, method, params, description, (flags & REQUIRED) != 0,
+			constraint );
+		
+		if (!setTokens( tokens ))
+			throw new IllegalArgumentException( "no tokens for option" );
+		
+		isArray = params.length > 3 && params[3].isArray();
+		this.flags = flags;
+		
+		if (defaultValue != null)
+			defaultValues = new Object[] { defaultValue };
+		else
+			defaultValues = null;
+		
+		if (constraint != null && defaultValue != null)
+			constraint.checkValue( defaultValue );
+	}
+	
+	/**
+	 * @param cp
+	 * @param tokens
+	 * @param names
+	 * @param method
+	 * @param params
+	 * @param description
+	 * @param flags
+	 * @param defaultValues
+	 * @param constraints
+	 * @throws Exception
+	 */
+	public Option( CommandParser cp, String tokens, String[] names, String method,
+		Class<?>[] params, String description, int flags, Object[] defaultValues,
+		Constraint[] constraints ) throws Exception
+	{
+		super( cp, names, method, params, description, (flags & REQUIRED) != 0,
+			constraints );
+		
+		if (!setTokens( tokens ))
+			throw new IllegalArgumentException( "no tokens for option" );
+		
+		if (defaultValues != null && defaultValues.length != names.length)
+			throw new IllegalArgumentException( "defaultValue.length != name.length" );
+		
+		isArray = params.length > 3 && params[3].isArray();
+		this.flags = flags;
+		this.defaultValues = defaultValues;
+		
+		if (constraints != null && defaultValues != null)
+		{
+			int n = constraints.length;
+			for (int i = 0; i < n; i++)
+			{
+				Constraint c = constraints[i];
+				Object v = defaultValues[i];
+				if (c != null)
+					c.checkValue( v );
+			}
+		}
+	}
+
+	private final boolean isArray;
+	
+	private final int flags;
+	
+	private final Object[] defaultValues;
+	
+	/**
+	 * The option has no special handling.
+	 */
+	public static final int NONE = 0;
+
+	/**
+	 * The option is hidden from the user. It must not be specified.
+	 * It must not be required or it must have a default value.
+	 */
+	public static final int HIDDEN = 1;
+
+	/**
+	 * The option may only be specified once.
+	 */
+	public static final int SINGLETON = 2;
+
+	/**
+	 * The option is required to be specified.
+	 */
+	public static final int REQUIRED = 4;
+	
+	/**
+	 * @return an iterator over the tokens of an option.
+	 */
+	public Iterator<String> getTokens()
+	{
+		return tokens.iterator();
+	}
+	
+	/**
+	 * @return true if the option is hidden.
+	 */
+	public boolean isHidden()
+	{
+		return matchFlags( HIDDEN );
+	}
+	
+	/**
+	 * @return true if the option may only appear once.
+	 */
+	public boolean isSingleton()
+	{
+		return matchFlags( SINGLETON );
+	}
+
+	/**
+	 * @param flag
+	 * @return true if the flag has been specified, false otherwise
+	 */
+	private boolean matchFlags( int flag )
+	{
+		return (flags & flag) != 0;
+	}
+	
+	/**
+	 * @return the default value of the option.
+	 */
+	public Object[] getDefaultValues()
+	{
+		return defaultValues;
+	}
+
+	@Override
+	public String toString()
+	{
+		return toString( primaryToken != null ? primaryToken : "(unknown)" );
+	}
+	
+	/**
+	 * @param token
+	 * @return the
+	 */
+	protected String toString( String token )
+	{
+		StringBuffer sb = new StringBuffer( token );
+		
+		String[] names = getNames();
+		if (names != null)
+		{
+			for (String name: names)
+			{
+				sb.append( ' ' );
+				sb.append( name );
+			}
+		}
+		
+		return sb.toString();
+	}
+
+	////////////
+	// TOKENS //
+	////////////
+
+	private boolean setTokens( String s )
+	{
+		tokens.clear();
+		primaryToken = null;
+		
+		StringTokenizer st = new StringTokenizer( s, "|,; \r\n\t" );
+		while (st.hasMoreTokens())
+		{
+			String t = st.nextToken();
+			tokens.add( t );
+			if (primaryToken == null)
+				primaryToken = t;
+		}
+		
+		return tokens.size() > 0;
+	}
+	
+	/**
+	 * @return the first token in the token list of the option.
+	 */
+	public String getPrimaryToken()
+	{
+		return primaryToken;
+	}
+	
+	private List<String> tokens = new ArrayList<String>();
+	
+	private String primaryToken;
+
+	//////////
+	// HELP //
+	//////////
+
+	@Override
+	public void showShortDescription()
+	{
+		System.err.print( isRequired() ? " {" : " [" );
+		
+		System.err.print( ' ' );
+		System.err.print( primaryToken );
+		
+		if (wantsValue())
+		{
+			for (String name: getNames())
+			{
+				System.err.print( ' ' );
+				System.err.print( name );
+			}
+		}
+		
+		System.err.print( isRequired() ? " }" : " ]" );
+	}
+	
+	@Override
+	public void showLongDescription()
+	{
+		Iterator<String> i = tokens.iterator();
+		while (i.hasNext())
+		{
+			System.err.print( NAME_FLAG );
+			System.err.print( i.next() );
+			if (wantsValue())
+			{
+				for (String name: getNames())
+				{
+					System.err.print( ' ' );
+					System.err.print( name );
+				}
+			}
+			System.err.println();
+		}
+		
+		showDescription();
+		
+		showIsRequired();
+		
+		showConstraint();
+		
+		if (isSingleton())
+		{
+			System.err.print( DESC_FLAG );
+			System.err.println( "singleton (may only be specified once)." );
+		}
+		
+		if (defaultValues != null)
+		{
+			int n = defaultValues.length;
+			
+			System.err.print( DESC_FLAG );
+			
+			if (n > 1)
+				System.err.print( "default: {" );
+			else
+				System.err.print( "default: " );
+			
+			for (Object defaultValue: defaultValues)
+			{
+				System.err.print( ' ' );
+				System.err.print( defaultValue );
+			}
+			
+			if (n > 1)
+				System.err.println( " }" );
+			else
+				System.err.println();
+		}
+	}
+
+	///////////
+	// VALUE //
+	///////////
+	
+	/**
+	 * @return true if this option needs a value, false otherwise.
+	 */
+	public boolean wantsValue()
+	{
+		return true;
+	}
+
+	/**
+	 * @param token
+	 * @param value value specified on the token (e.g., --count=23)
+	 * @param tkns
+	 * @return value from tokens converted as appropriate.
+	 */
+	public Object[] getAndConvertValue( String token, String value, Iterator<String> tkns )
+	{
+//		System.out.printf( "looking for value for token %s: value = %s\n", token, value  );
+		Object[] values = new Object[getNames().length];
+		int i = 0;
+		for (String name: getNames())
+		{
+			if (value == null && !tkns.hasNext())
+			{
+				System.err.println( "option '"+toString( token )+"': missing value "+name );
+				return null;
+			}
+			values[i++] = convertValue( value != null ? value : tkns.next() );
+			value = null;
+		}
+		return values;
+	}
+	
+	@Override
+	public boolean checkValue( String token, Object[] values )
+	{
+		return super.checkValue( "option '"+toString( token )+"'", values );
+	}
+
+	/**
+	 * @param token
+	 * @param values
+	 * @param hiddenOk
+	 * @return value returned by called method.
+	 * @throws Exception
+	 */
+	public boolean deliverValue( String token, Object[] values, boolean hiddenOk )
+		throws Exception
+	{
+		try
+		{
+			if (!checkOkToDeliver( token, hiddenOk ))
+				return false;
+			
+			if (isArray)
+				return callMethod( getArgs( token, values ) );
+			
+			return callMethod( getArgs( token, values != null ? values[0] : null ) );
+		}
+		catch ( InvocationTargetException e )
+		{
+			Throwable t = e.getTargetException();
+			if (t instanceof Exception)
+				throw (Exception) t;
+			if (t instanceof RuntimeException)
+				throw (RuntimeException) t;
+			throw new RuntimeException( "caught exception: "+t, t );
+		}
+	}
+
+	/**
+	 * @param token
+	 * @param hiddenOk
+	 * @return false if flags prevent delivery of the option value.
+	 */
+	private boolean checkOkToDeliver( String token, boolean hiddenOk )
+	{
+		// allow hidden option to be specified. just don't show it in help.
+//		if (isHidden() && !hiddenOk)
+//		{
+//			getCommandParser().report( "option '"+toString( token )+"' not allowed", null, null );
+//			return false;
+//		}
+		
+		if (getCommandParser().isAlreadySpecified( this, true ) && isSingleton())
+		{
+			getCommandParser().report( "option '"+toString( token )+"' not allowed more than once", null, null );
+			return false;
+		}
+		
+		return true;
+	}
+
+	/**
+	 * @param token
+	 * @param value
+	 * @return the args to pass to the method.
+	 */
+	protected Object[] getArgs( String token, Object value )
+	{
+		return new Object[] { getCommandParser(), this, token, value };
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/OrConstraint.java b/util/src/main/java/org/apache/etch/util/cmd/OrConstraint.java
new file mode 100644
index 0000000..a35df53
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/OrConstraint.java
@@ -0,0 +1,68 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * Description of OrConstraint.
+ */
+public class OrConstraint implements Constraint
+{
+	/**
+	 * Constructs the OrConstraint.
+	 * @param a
+	 * @param b
+	 */
+	public OrConstraint( Constraint a, Constraint b )
+	{
+		this.a = a;
+		this.b = b;
+	}
+	
+	private final Constraint a;
+	
+	private final Constraint b;
+	
+	public void checkValue( Object value ) throws Exception
+	{
+		try
+		{
+			a.checkValue( value );
+		}
+		catch ( Exception ea )
+		{
+			try
+			{
+				b.checkValue( value );
+			}
+			catch ( Exception eb )
+			{
+				throw new Exception( "failed both constraints: "+
+					ea.getMessage()+" AND "+eb.getMessage() );
+			}
+		}
+	}
+	
+	@Override
+	public String toString()
+	{
+		return "("+a+") OR ("+b+")";
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/Parameter.java b/util/src/main/java/org/apache/etch/util/cmd/Parameter.java
new file mode 100644
index 0000000..7a4a10d
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/Parameter.java
@@ -0,0 +1,120 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * A command line value which is specified by position. A parameter
+ * is dependent upon position on the command line to be recognized.
+ */
+public abstract class Parameter extends OptParamBase
+{
+	/**
+	 * @param cp
+	 * @param name
+	 * @param method
+	 * @param params
+	 * @param description
+	 * @param isRequired
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public Parameter( CommandParser cp, String name, String method,
+		Class<?>[] params, String description, boolean isRequired,
+		Constraint constraint ) throws Exception
+	{
+		super( cp, name, method, params, description, isRequired, constraint );
+	}
+
+	@Override
+	public String toString()
+	{
+		return getNames()[0];
+	}
+
+	//////////
+	// HELP //
+	//////////
+
+	@Override
+	public void showShortDescription()
+	{
+		System.err.print( ' ' );
+		System.err.print( getNames()[0] );
+	}
+
+	@Override
+	public void showLongDescription()
+	{
+		System.err.print( NAME_FLAG );
+		System.err.println( getNames()[0] );
+		
+		showDescription();
+		
+		showIsRequired();
+		
+		showConstraint();
+	}
+
+	///////////
+	// VALUE //
+	///////////
+
+	/**
+	 * @param value
+	 * @return true if the value is ok, false otherwise.
+	 */
+	public boolean checkValue( Object value )
+	{
+		return super.checkValue( "parameter '"+toString()+"'",
+			new Object[] { value } );
+	}
+
+	/**
+	 * @param value
+	 * @return value returned by called method.
+	 * @throws Exception
+	 */
+	public boolean deliverValue( Object value ) throws Exception
+	{
+		try
+		{
+			return callMethod( getArgs( value ) );
+		}
+		catch ( InvocationTargetException e )
+		{
+			Throwable x = e.getTargetException();
+			if (x instanceof Exception)
+				throw (Exception) x;
+			throw new RuntimeException( x );
+		}
+	}
+	
+	/**
+	 * @param value
+	 * @return the args to pass to the method.
+	 */
+	private Object[] getArgs( Object value )
+	{
+		return new Object[] { getCommandParser(), this, value };
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/ParityConstraint.java b/util/src/main/java/org/apache/etch/util/cmd/ParityConstraint.java
new file mode 100644
index 0000000..5fac175
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/ParityConstraint.java
@@ -0,0 +1,53 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * Description of ParityConstraint.
+ */
+public class ParityConstraint implements Constraint
+{
+	/**
+	 * Constructs the ParityConstraint.
+	 *
+	 * @param wantsOdd
+	 */
+	public ParityConstraint( boolean wantsOdd )
+	{
+		this.wantsOdd = wantsOdd;
+	}
+	
+	private final boolean wantsOdd;
+	
+	public void checkValue( Object value ) throws Exception
+	{
+		int v = ((Integer) value).intValue();
+		boolean valueIsOdd = (v & 1) != 0;
+		if (valueIsOdd != wantsOdd)
+			throw new Exception( wantsOdd ? "is not odd" : "is not even" );
+	}
+
+	@Override
+	public String toString()
+	{
+		return wantsOdd ? "must be odd" : "must be even";
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/Program.java b/util/src/main/java/org/apache/etch/util/cmd/Program.java
new file mode 100644
index 0000000..dfd0431
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/Program.java
@@ -0,0 +1,147 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * Description of Program
+ */
+abstract public class Program
+{
+	/**
+	 * @param program
+	 * @param args
+	 * @throws Exception
+	 */
+	protected static void main( final Program program, String[] args )
+		throws Exception
+	{
+		CommandParser cp = new CommandParser( program );
+		
+		cp.defineNullOption( program.getHelpTokens(), "doHelp",
+			"print help message and exit.",
+			Option.NONE );
+		
+		program.defineOptionsAndParameters( cp );
+		
+		if (!cp.parse( args ))
+		{
+			program.exit( 1, program.toString(), "cmdLineParseFailure", true );
+			return;
+		}
+		
+		Runtime.getRuntime().addShutdownHook(
+			new Thread()
+			{
+				@Override
+				public void run()
+				{
+					program.shutdown( program.shutdownSource,
+						program.shutdownReason, program.shutdownEmergency );
+				}
+			});
+		
+		program.run();
+	}
+
+	/**
+	 * @param code the exit code.
+	 * @param source the source of the request.
+	 * @param reason the reason for the request.
+	 * @param emergency perform minimal shutdown if true.
+	 */
+	public void exit( int code, String source, String reason,
+		boolean emergency )
+	{
+		shutdownSource = source;
+		shutdownReason = reason;
+		shutdownEmergency = emergency;
+		System.exit( code );
+	}
+	
+	/**
+	 * The source of the request.
+	 */
+	String shutdownSource = "runtime";
+	
+	/**
+	 * The reason for the request.
+	 */
+	String shutdownReason = "unknown";
+	
+	/**
+	 * Full shutdown (false) or minimal (true)?
+	 */
+	boolean shutdownEmergency = false;
+
+	/**
+	 * @return the list of tokens the user might specify to get help.
+	 * The default list of tokens is "-h|--help".
+	 */
+	protected String getHelpTokens()
+	{
+		return "-h|--help";
+	}
+
+	/**
+	 * Prints the help message for the program.
+	 * @param cp
+	 * @param option
+	 * @param token
+	 * @return false indicating the program should exit.
+	 */
+	public boolean doHelp( CommandParser cp, Option option, String token )
+	{
+		cp.showHelp( false );
+		return false;
+	}
+
+	@Override
+	public String toString()
+	{
+		return getClass().getName().toString();
+	}
+	
+	/**
+	 * Gives the program a chance to define its options and parameters.
+	 * @param cp
+	 * @throws Exception
+	 */
+	abstract protected void defineOptionsAndParameters( CommandParser cp )
+		throws Exception;
+	
+	/**
+	 * Runs the program after successful command line parsing.
+	 * @throws Exception
+	 */
+	abstract protected void run() throws Exception;
+	
+	/**
+	 * Shuts down the program in an orderly way when System.exit is called,
+	 * or when the program is killed by external command (^C) or unix kill.
+	 * @param source the source of the request
+	 * @param reason the reason for the shutdown
+	 * @param emergency only a minimal amount of shutdown should be performed
+	 */
+	protected void shutdown( String source, String reason, boolean emergency )
+	{
+		// nothing to do.
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/StringArrayIterator.java b/util/src/main/java/org/apache/etch/util/cmd/StringArrayIterator.java
new file mode 100644
index 0000000..ed58069
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/StringArrayIterator.java
@@ -0,0 +1,69 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Simply an Iterator for String[].
+ */
+public class StringArrayIterator implements Iterator<String>
+{
+	/**
+	 * @param array
+	 */
+	public StringArrayIterator( String[] array )
+	{
+		this.array = array;
+	}
+	
+	private final String[] array;
+	
+	private int index;
+	
+	/* (non-Javadoc)
+	 * @see java.util.Iterator#hasNext()
+	 */
+	public boolean hasNext()
+	{
+		return index < array.length;
+	}
+
+	/* (non-Javadoc)
+	 * @see java.util.Iterator#next()
+	 */
+	public String next()
+	{
+		if (index >= array.length)
+			throw new NoSuchElementException();
+		
+		return array[index++];
+	}
+
+	/* (non-Javadoc)
+	 * @see java.util.Iterator#remove()
+	 */
+	public void remove()
+	{
+		throw new UnsupportedOperationException();
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/StringArrayOption.java b/util/src/main/java/org/apache/etch/util/cmd/StringArrayOption.java
new file mode 100644
index 0000000..035edd2
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/StringArrayOption.java
@@ -0,0 +1,55 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * An option whose value is a string.
+ */
+public class StringArrayOption extends Option
+{
+	/**
+	 * @param cp
+	 * @param tokens
+	 * @param names
+	 * @param method
+	 * @param description
+	 * @param flags
+	 * @param defaultValues
+	 * @param constraints
+	 * @throws Exception
+	 */
+	public StringArrayOption( CommandParser cp, String tokens, String[] names,
+		String method, String description, int flags, String[] defaultValues,
+		Constraint[] constraints ) throws Exception
+	{
+		super( cp, tokens, names, method, PARAMS, description, flags,
+			defaultValues, constraints );
+	}
+	
+	private final static Class<?>[] PARAMS =
+		{ CommandParser.class, Option.class, String.class, Object[].class };
+
+	@Override
+	protected Object convertValue( String value )
+	{
+		return value;
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/StringLengthConstraint.java b/util/src/main/java/org/apache/etch/util/cmd/StringLengthConstraint.java
new file mode 100644
index 0000000..5820962
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/StringLengthConstraint.java
@@ -0,0 +1,59 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * Description of StringLengthConstraint
+ */
+public class StringLengthConstraint implements Constraint
+{
+	/**
+	 * Constructs the StringLengthConstraint.
+	 *
+	 * @param min the minimum value allowed.
+	 * 
+	 * @param max the maximum value allowed.
+	 */
+	public StringLengthConstraint( int min, int max )
+	{
+		if (min > max)
+			throw new IllegalArgumentException( "min > max" );
+		this.min = min;
+		this.max = max;
+	}
+	
+	private final int min;
+	
+	private final int max;
+	
+	public void checkValue( Object value ) throws Exception
+	{
+		int v = ((String) value).length();
+		if (v < min || v > max)
+			throw new Exception( "length not in range "+min+" to "+max );
+	}
+
+	@Override
+	public String toString()
+	{
+		return "length must be in range "+min+" to "+max;
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/StringOption.java b/util/src/main/java/org/apache/etch/util/cmd/StringOption.java
new file mode 100644
index 0000000..c750990
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/StringOption.java
@@ -0,0 +1,55 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * An option whose value is a string.
+ */
+public class StringOption extends Option
+{
+	/**
+	 * @param cp
+	 * @param tokens
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param flags
+	 * @param defaultValue
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public StringOption( CommandParser cp, String tokens, String name, String method,
+		String description, int flags, String defaultValue, Constraint constraint )
+		throws Exception
+	{
+		super( cp, tokens, name, method, PARAMS, description, flags,
+			defaultValue, constraint );
+	}
+	
+	private final static Class<?>[] PARAMS =
+		{ CommandParser.class, Option.class, String.class, String.class };
+
+	@Override
+	protected Object convertValue( String value )
+	{
+		return value;
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/StringParameter.java b/util/src/main/java/org/apache/etch/util/cmd/StringParameter.java
new file mode 100644
index 0000000..988b699
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/StringParameter.java
@@ -0,0 +1,51 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+/**
+ * A parameter whose value is a string.
+ */
+public class StringParameter extends Parameter
+{
+	/**
+	 * @param cp
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param isRequired
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public StringParameter( CommandParser cp, String name, String method,
+		String description, boolean isRequired, Constraint constraint ) throws Exception
+	{
+		super( cp, name, method, PARAMS, description, isRequired, constraint );
+	}
+	
+	private final static Class<?>[] PARAMS =
+		{ CommandParser.class, Parameter.class, String.class };
+
+	@Override
+	public Object convertValue( String value )
+	{
+		return value;
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/UrlOption.java b/util/src/main/java/org/apache/etch/util/cmd/UrlOption.java
new file mode 100644
index 0000000..dbbbc8b
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/UrlOption.java
@@ -0,0 +1,57 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+import org.apache.etch.util.URL;
+
+/**
+ * An option whose value is a url.
+ */
+public class UrlOption extends Option
+{
+	/**
+	 * @param cp
+	 * @param tokens
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param flags
+	 * @param defaultValue
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public UrlOption( CommandParser cp, String tokens, String name,
+		String method, String description, int flags, URL defaultValue,
+		Constraint constraint ) throws Exception
+	{
+		super( cp, tokens, name, method, PARAMS, description, flags,
+			defaultValue, constraint );
+	}
+	
+	private final static Class<?>[] PARAMS =
+		{ CommandParser.class, Option.class, String.class, URL.class };
+
+	@Override
+	protected Object convertValue( String value )
+	{
+		return new URL( value );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/cmd/UrlParameter.java b/util/src/main/java/org/apache/etch/util/cmd/UrlParameter.java
new file mode 100644
index 0000000..f655774
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/cmd/UrlParameter.java
@@ -0,0 +1,53 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+import org.apache.etch.util.URL;
+
+/**
+ * A parameter whose value is a url.
+ */
+public class UrlParameter extends Parameter
+{
+	/**
+	 * @param cp
+	 * @param name
+	 * @param method
+	 * @param description
+	 * @param isRequired
+	 * @param constraint
+	 * @throws Exception
+	 */
+	public UrlParameter( CommandParser cp, String name, String method,
+		String description, boolean isRequired, Constraint constraint ) throws Exception
+	{
+		super( cp, name, method, PARAMS, description, isRequired, constraint );
+	}
+	
+	private final static Class<?>[] PARAMS =
+		{ CommandParser.class, Parameter.class, URL.class };
+
+	@Override
+	public Object convertValue( String value )
+	{
+		return new URL( value );
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/Who.java b/util/src/main/java/org/apache/etch/util/core/Who.java
new file mode 100644
index 0000000..81ef235
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/Who.java
@@ -0,0 +1,30 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core;
+
+/**
+ * Abstraction of sender used by the various sources of data,
+ * packets, or messages.
+ */
+public interface Who
+{
+	// nothing else.
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/io/Connection.java b/util/src/main/java/org/apache/etch/util/core/io/Connection.java
new file mode 100644
index 0000000..5ad6d38
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/Connection.java
@@ -0,0 +1,349 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import java.io.IOException;
+import java.net.SocketAddress;
+import java.net.SocketException;
+
+import org.apache.etch.util.Monitor;
+import org.apache.etch.util.Runner;
+import org.apache.etch.util.RunnerHandler;
+import org.apache.etch.util.Todo;
+import org.apache.etch.util.TodoManager;
+
+
+/**
+ * Implementation of runner which handles a network connection.
+ * @param <H> the event handler type.
+ */
+abstract public class Connection<H extends Session>
+	extends Runner implements Transport<H>, RunnerHandler
+{
+	/////////////
+	// QUERIES //
+	/////////////
+
+	/** Source query to get the local address. */
+	public static final String LOCAL_ADDRESS = "LOCAL_ADDRESS";
+
+	/** Source query to get the remote address. */
+	public static final String REMOTE_ADDRESS = "REMOTE_ADDRESS";
+	
+	////////////
+	// EVENTS //
+	////////////
+
+	/**
+	 * Host name to specify to select listening on all interfaces.
+	 * The value is "0.0.0.0".
+	 */
+	public static final String ALL_INTFS = "0.0.0.0";
+	
+	/**
+	 * @param s
+	 * @return null if s is null or ALL_INTFS ("0.0.0.0").
+	 */
+	protected static String translateHost( String s )
+	{
+		if (s != null && s.equals( ALL_INTFS ))
+			return null;
+		return s;
+	}
+
+	/**
+	 * Constructs the Connection.
+	 */
+	public Connection()
+	{
+		setHandler( this );
+	}
+	
+	public void started()
+	{
+		// ignore
+	}
+	
+	public void stopped()
+	{
+		// ignore
+	}
+
+	public void exception( String what, final Exception e )
+	{
+		TodoManager.addTodo( new Todo()
+		{
+			public void doit( TodoManager m ) throws Exception
+			{
+				session.sessionNotify( e );
+			}
+			
+			public void exception( TodoManager mgr, Exception ex )
+			{
+				e.printStackTrace();
+				if (ex != e)
+					ex.printStackTrace();
+			}
+		} );
+	}
+
+	@Override
+	protected boolean run0( boolean first ) throws Exception
+	{
+		boolean ok = openSocket( !first );
+//		Log.report( "openSocketDone", "result", ok, "c", this, "t", Thread.currentThread() );
+		if (!ok)
+			return false;
+		
+		try
+		{
+			setupSocket();
+//			Log.report( "setupSocketDone", "c", this );
+		}
+		catch ( Exception e )
+		{
+			fireException( "setup", e );
+			close( true );
+			return true;
+		}
+
+		try
+		{
+//			Log.report( "beforeFireUp", "c", this );
+			fireUp();
+			readSocket();
+//			Log.report( "readSocketDone", "c", this );
+			return true;
+		}
+		catch ( SocketException e )
+		{
+//			Log.report( "readSocketDone", "c", this, "e", e );
+			
+			if ("socket closed".equalsIgnoreCase( e.getMessage() ))
+				return true;
+			
+			fireException( "run", e );
+			close( true );
+			return true;
+		}
+		catch ( Exception e )
+		{
+			fireException( "run", e );
+			close( true );
+			return true;
+		}
+		finally
+		{
+//			Log.report( "beforeFireDown", "c", this );
+			fireDown();
+			close( false );
+//			Log.report( "closeDone", "c", this );
+		}
+	}
+
+	/**
+	 * Opens the socket of a connection.
+	 * @param reconnect true if we are trying to reconnect, false if this
+	 * is the first time.
+	 * @return true if we should reconnect, false if we should stop.
+	 * @throws Exception
+	 */
+	abstract protected boolean openSocket( boolean reconnect ) throws Exception;
+	
+	/**
+	 * Sets up a newly opened socket. This may involve setting socket
+	 * options and opening input and output streams.
+	 * @throws Exception
+	 */
+	abstract protected void setupSocket() throws Exception;
+
+	/**
+	 * Performs the usual and customary operations on a socket, such
+	 * as read or accept.
+	 * @throws Exception
+	 */
+	abstract protected void readSocket() throws Exception;
+
+	/**
+	 * Terminates operations on the socket.
+	 * @param reset true if the socket should be terminated immediately.
+	 * False if the pending output data should be allowed to linger.
+	 * @throws Exception
+	 */
+	abstract public void close( boolean reset ) throws Exception;
+
+	/**
+	 * Terminates operations on the socket. Same as close( false );
+	 * @throws Exception
+	 * @see #close(boolean)
+	 */
+	public void close() throws Exception
+	{
+		close( false );
+	}
+	
+	public Object transportQuery( Object query ) throws Exception
+	{
+		if (query == LOCAL_ADDRESS)
+			return localAddress();
+
+		if (query == REMOTE_ADDRESS)
+			return remoteAddress();
+		
+		if (query instanceof WaitUp)
+		{
+			waitUp( ((WaitUp) query).maxDelay );
+			return null;
+		}
+		
+		if (query instanceof WaitDown)
+		{
+			waitDown( ((WaitDown) query).maxDelay );
+			return null;
+		}
+		
+		throw new UnsupportedOperationException( "unknown query: "+query );
+	}
+
+	/**
+	 * @return the local address
+	 * @throws IOException
+	 */
+	abstract public SocketAddress localAddress() throws IOException;
+
+	/**
+	 * @return the remote address
+	 * @throws IOException
+	 */
+	abstract public SocketAddress remoteAddress() throws IOException;
+	
+	public void transportControl( Object control, Object value ) throws Exception
+	{
+		if (control == START)
+		{
+			start();
+			return;
+		}
+
+		if (control == START_AND_WAIT_UP)
+		{
+			start();
+			waitUp( (Integer) value );
+			return;
+		}
+
+		if (control == STOP)
+		{
+			stop();
+			return;
+		}
+
+		if (control == STOP_AND_WAIT_DOWN)
+		{
+			stop();
+			waitDown( (Integer) value );
+			return;
+		}
+		
+		if (control == RESET)
+		{
+			close( true );
+			return;
+		}
+
+		throw new UnsupportedOperationException( "unknown control: "+control );
+	}
+	
+	public void transportNotify( Object event ) throws Exception
+	{
+		// nothing to do.
+	}
+
+	private void fireUp() throws Exception
+	{
+		status.set( Session.UP );
+		TodoManager.addTodo( new Todo()
+		{
+			public void doit( TodoManager m ) throws Exception
+			{
+				session.sessionNotify( Session.UP );
+			}
+			
+			public void exception( TodoManager mgr, Exception e )
+			{
+				e.printStackTrace();
+			}
+		} );
+	}
+
+	private void fireDown() throws Exception
+	{
+		status.set( Session.DOWN );
+		TodoManager.addTodo( new Todo()
+		{
+			public void doit( TodoManager m ) throws Exception
+			{
+				session.sessionNotify( Session.DOWN );
+			}
+			
+			public void exception( TodoManager mgr, Exception e )
+			{
+				e.printStackTrace();
+			}
+		} );
+	}
+	
+	public H getSession()
+	{
+		return session;
+	}
+	
+	public void setSession( H session )
+	{
+		this.session = session;
+	}
+	
+	/**
+	 * The session for the connection.
+	 */
+	protected H session;
+	
+	/**
+	 * Waits until the connection is up.
+	 * @param maxDelay time in milliseconds to wait.
+	 * @throws Exception
+	 */
+	public void waitUp( int maxDelay ) throws Exception
+	{
+		status.waitUntilEq( Session.UP, maxDelay );
+	}
+	
+	/**
+	 * @param maxDelay time in milliseconds to wait.
+	 * @throws Exception
+	 */
+	public void waitDown( int maxDelay ) throws Exception
+	{
+		status.waitUntilEq( Session.DOWN, maxDelay );
+	}
+	
+	private final Monitor<String> status = new Monitor<String>( "status", Session.DOWN );
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/io/InetWho.java b/util/src/main/java/org/apache/etch/util/core/io/InetWho.java
new file mode 100644
index 0000000..af74d02
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/InetWho.java
@@ -0,0 +1,73 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import java.net.InetAddress;
+
+import org.apache.etch.util.core.Who;
+
+
+
+/**
+ * Who for an inet address / port.
+ */
+public class InetWho implements Who
+{
+	/**
+	 * @param addr
+	 * @param port
+	 */
+	public InetWho( InetAddress addr, int port )
+	{
+		this.addr = addr;
+		this.port = port;
+	}
+	
+	private final InetAddress addr;
+	
+	private final int port;
+
+	/**
+	 * @return the address of who.
+	 */
+	public InetAddress getInetAddress()
+	{
+		return addr;
+	}
+
+	/**
+	 * @return the port of who.
+	 */
+	public int getPort()
+	{
+		return port;
+	}
+
+	/**
+	 * @param addr
+	 * @param port
+	 * @return true if the specified addr and port match this who.
+	 */
+	public boolean matches( InetAddress addr, int port )
+	{
+		return addr.equals( addr ) && port == port;
+	}
+}
\ No newline at end of file
diff --git a/util/src/main/java/org/apache/etch/util/core/io/Packetizer.java b/util/src/main/java/org/apache/etch/util/core/io/Packetizer.java
new file mode 100644
index 0000000..8b924f9
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/Packetizer.java
@@ -0,0 +1,313 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import java.io.IOException;
+
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.Who;
+
+
+/**
+ * Packetizes a stream data source. Reads a packet header:
+ * a 32-bit flag and a 32-bit length, both big-endian, verifies
+ * the flag, and then, using the length from the header,
+ * reads the packet data and passes it to the packet handler.
+ * As a packet source, accepts a packet and prepends a packet
+ * header to it before delivering it to a data source.
+ */
+public final class Packetizer implements SessionData, TransportPacket
+{
+	/**
+	 * URI term to specify max packet size.
+	 */
+	public final static String MAX_PKT_SIZE_TERM = "Packetizer.maxPktSize";
+	
+	private final static int SIG = 0xdeadbeef;
+	
+	private final static int HEADER_SIZE = 8;
+	
+	/**
+	 * The default maximum packet size that will be accepted, 16376 bytes.
+	 */
+	public final static int DEFAULT_MAX_PKT_SIZE = 16384 - HEADER_SIZE;
+	
+	/**
+	 * Constructs the Packetizer with null packet handler and uri specified
+	 * or defaulted maximum packet size.
+	 * @param transport used to deliver data to the peer.
+	 * @param uri
+	 * @param resources
+	 */
+	public Packetizer( TransportData transport, String uri, Resources resources )
+	{
+		this( transport, new URL( uri ), resources );
+	}
+	
+	/**
+	 * Constructs the Packetizer with null packet handler and uri specified
+	 * or defaulted maximum packet size.
+	 * 
+	 * @param transport used to deliver data to the peer.
+	 * @param uri
+	 * @param resources
+	 * 
+	 * @see #MAX_PKT_SIZE_TERM
+	 * @see #DEFAULT_MAX_PKT_SIZE
+	 */
+	public Packetizer( TransportData transport, URL uri, Resources resources )
+	{
+		this( transport, uri.getIntegerTerm( MAX_PKT_SIZE_TERM, DEFAULT_MAX_PKT_SIZE ) );
+	}
+
+	/**
+	 * Constructs the Packetizer with the specified packet handler and maximum
+	 * packet size.
+	 * 
+	 * @param handler the handler to receive the packets.
+	 * 
+	 * @param maxPktSize the maximum packet size that will be accepted.
+	 * Must be >= 0. If maxPktSize == 0, there is no limit.
+	 */
+	private Packetizer( TransportData transport, int maxPktSize )
+	{
+		if (maxPktSize < 0)
+			throw new IllegalArgumentException( "maxPktSize < 0" );
+		
+		this.transport = transport;
+		this.maxPktSize = maxPktSize;
+		
+		transport.setSession( this );
+	}
+	
+	private final TransportData transport;
+	
+	private final int maxPktSize;
+	
+	/**
+	 * @return the transport.
+	 */
+	public TransportData getTransport()
+	{
+		return transport;
+	}
+	
+	@Override
+	public String toString()
+	{
+		return String.format( "Packetizer/%s", transport );
+	}
+
+	public void sessionData( Who sender, FlexBuffer buf ) throws Exception
+	{
+		// there are two options here. one is that we have no buffered data
+		// and the entire packet is contained within the buf. in that case
+		// we could optimize the daylights out of the process and directly
+		// drop the packet on the handler.
+		
+		while (buf.avail() > 0)
+		{
+			if (wantHeader)
+			{
+				// do we have enough to make a header?
+				
+				if (savedBuf.length() + buf.avail() >= HEADER_SIZE)
+				{
+					int pktSize;
+					
+					if (savedBuf.length() == 0)
+					{
+						// savedBuf is empty, entire header in buf.
+						
+						pktSize = processHeader( buf, false );
+					}
+					else // header split across savedBuf and buf
+					{
+						// move just enough data from buf to savedBuf to have a header.
+						
+						int needFromBuf = HEADER_SIZE - savedBuf.length();
+						savedBuf.put( buf, needFromBuf );
+						savedBuf.setIndex( 0 );
+						
+						pktSize = processHeader( savedBuf, true );
+					}
+					
+					if (pktSize == 0)
+						continue;
+					
+					bodyLen = pktSize;
+					wantHeader = false;
+				}
+				else // want header, but there's not enough to make it.
+				{
+					// save buf in savedBuf.
+					
+					savedBuf.setIndex( savedBuf.length() );
+					savedBuf.put( buf );
+				}
+			}
+			else if (savedBuf.length() + buf.avail() >= bodyLen)
+			{
+				// want body, and there's enough to make it.
+				
+				// three possible cases: the body is entirely in savedBuf,
+				// the body is split, or the body is entirely in buf. assert
+				// that the body cannot entirely be in savedBuf, or else
+				// we'd have processed it last time.
+				assert savedBuf.length() < bodyLen;
+				
+				if (savedBuf.length() == 0)
+				{
+					// savedBuf is empty, entire body in buf.
+
+					int length = buf.length();
+					int index = buf.index();
+					buf.setLength( index+bodyLen );
+					
+					session.sessionPacket( sender, buf );
+					
+					buf.setLength( length );
+					buf.setIndex( index+bodyLen );
+					
+					wantHeader = true;
+				}
+				else // body split across savedBuf and buf
+				{
+					// move just enough data from buf to savedBuf to have a body.
+					
+					int needFromBuf = bodyLen - savedBuf.length();
+					savedBuf.put( buf, needFromBuf );
+					savedBuf.setIndex( 0 );
+					
+					session.sessionPacket( sender, savedBuf );
+					
+					savedBuf.reset();
+					wantHeader = true;
+				}
+			}
+			else // want body, but there's not enough to make it.
+			{
+				// save buf in savedBuf.
+				
+				savedBuf.put( buf );
+			}
+		}
+		// buf is now empty, and there's nothing else to do.
+		assert buf.avail() == 0;
+	}
+	
+	private int processHeader( FlexBuffer buf, boolean reset ) throws IOException
+    {
+		int sig = buf.getInt();
+		if (sig != SIG)
+			throw new IOException( "bad SIG" );
+		
+		int pktSize = buf.getInt();
+		
+		if (reset)
+			buf.reset();
+		
+		if (pktSize < 0 || maxPktSize > 0 && pktSize > maxPktSize)
+			throw new IOException( "pktSize < 0 || (maxPktSize > 0 && pktSize > maxPktSize)" );
+		
+		return pktSize;
+    }
+
+	private boolean wantHeader = true;
+	
+	private int bodyLen;
+	
+	private final FlexBuffer savedBuf = new FlexBuffer();
+
+	public void transportPacket( Who recipient, FlexBuffer buf ) throws Exception
+	{
+		// data-ize the packet.
+		
+		// assert index is at the start of the header.
+		int dataSize = buf.avail();
+		if (dataSize < HEADER_SIZE)
+			throw new IllegalArgumentException( "dataSize < HEADER_SIZE" );
+		
+		int pktSize = dataSize - HEADER_SIZE;
+		if (maxPktSize > 0 && pktSize > maxPktSize)
+			throw new IOException( "maxPktSize > 0 && pktSize > maxPktSize" );
+		
+		int index = buf.index();
+		buf.putInt( SIG );
+		buf.putInt( pktSize );
+		buf.setIndex( index );
+		transport.transportData( recipient, buf );
+	}
+
+	public int headerSize()
+	{
+		return HEADER_SIZE;
+	}
+
+	public Object sessionQuery( Object query ) throws Exception
+	{
+		return session.sessionQuery( query );
+	}
+
+	public void sessionControl( Object control, Object value ) throws Exception
+	{
+		session.sessionControl( control, value );
+	}
+
+	public void sessionNotify( Object event ) throws Exception
+	{
+		session.sessionNotify( event );
+	}
+
+	////////////////////
+	// Source methods //
+	////////////////////
+
+	public Object transportQuery( Object query ) throws Exception
+	{
+		return transport.transportQuery( query );
+	}
+
+	public void transportControl( Object control, Object value ) throws Exception
+	{
+		transport.transportControl( control, value );
+	}
+
+	public void transportNotify( Object event ) throws Exception
+	{
+		transport.transportNotify( event );
+	}
+
+	public SessionPacket getSession()
+	{
+		return session;
+	}
+
+	public void setSession( SessionPacket session )
+	{
+		this.session = session;
+	}
+	
+	private SessionPacket session;
+}
+
diff --git a/util/src/main/java/org/apache/etch/util/core/io/Session.java b/util/src/main/java/org/apache/etch/util/core/io/Session.java
new file mode 100644
index 0000000..e21aa37
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/Session.java
@@ -0,0 +1,99 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+/**
+ * Out-of-band query, control, and notification interface for sessions.
+ */
+public interface Session
+{
+	/**
+	 * Gets a configuration or operational value from the handler. The
+	 * request is passed up the chain of sessions until some session
+	 * recognizes the query, whereupon it returns the requested value.
+	 * 
+	 * @param query an object representing a query, which could be as
+	 * simple as a string, integer, or enum, or more complex such as
+	 * a class with instance variables for query terms.
+	 * 
+	 * @return the requested value, or null if not defined.
+	 * 
+	 * @throws UnsupportedOperationException if the query is not recognized
+	 * by any session (which is to say, if the last session in the session
+	 * chain does not recognize it, it should throw this exception). Typically
+	 * this would be a service's client or server implementation.
+	 * 
+	 * @throws Exception
+	 */
+	public Object sessionQuery( Object query ) throws Exception;
+	
+	/**
+	 * Sets a configuration or operational value in the session. The
+	 * request is passed up the chain of sessions until some session
+	 * recognizes the control, whereupon it stores the specified value
+	 * and returns.
+	 * 
+	 * @param control an object representing a control, which could be as
+	 * simple as a string, integer, or enum, or more complex such as
+	 * a class with instance variables for control terms.
+	 * 
+	 * @param value the value to set.
+	 * 
+	 * @throws IllegalArgumentException if the value is not the right
+	 * type or if the value is inappropriate.
+	 * 
+	 * @throws UnsupportedOperationException if the control is not recognized
+	 * by any session (which is to say, if the last session in the session
+	 * chain does not recognize it, it should throw this exception). Typically
+	 * this would be a service's client or server implementation.
+	 * 
+	 * @throws Exception
+	 */
+	public void sessionControl( Object control, Object value ) throws Exception;
+	
+	/**
+	 * Notifies the chain of sessions of the specified event. Unlike query
+	 * and control operations above, events are always passed up to the
+	 * top to allow all sessions to notice them.
+	 * 
+	 * @param event a class which represents the event, possibly with
+	 * parameters. The simplest event could be a string, integer,
+	 * or enum, but any class instance will do (as long as some session
+	 * in the chain expects it).
+	 * 
+	 * @throws Exception
+	 */
+	public void sessionNotify( Object event ) throws Exception;
+
+	///////////////////////
+	// Well-known events //
+	///////////////////////
+	
+	/**
+	 * Session event reporting the transport is up.
+	 */
+	public final static String UP = "UP";
+	
+	/**
+	 * Session event reporting the transport is down.
+	 */
+	public final static String DOWN = "DOWN";
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/io/SessionData.java b/util/src/main/java/org/apache/etch/util/core/io/SessionData.java
new file mode 100644
index 0000000..edf5b0e
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/SessionData.java
@@ -0,0 +1,39 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.core.Who;
+
+/**
+ * Interface used to deliver packets to the session from the transport.
+ */
+public interface SessionData extends Session
+{
+	/**
+	 * Delivers data to the session from the transport.
+	 * @param sender the sender of the data, for transports which allow
+	 * multiple senders. This is who to return any response to.
+	 * @param buf a FlexBuffer positioned at the data.
+	 * @throws Exception
+	 */
+	public void sessionData( Who sender, FlexBuffer buf ) throws Exception;
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/io/SessionListener.java b/util/src/main/java/org/apache/etch/util/core/io/SessionListener.java
new file mode 100644
index 0000000..57a78dd
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/SessionListener.java
@@ -0,0 +1,35 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+/**
+ * Interface used to deliver new connections to the session from the listener.
+ * @param <T> the type of the connection for the session.
+ */
+public interface SessionListener<T> extends Session
+{
+	/**
+	 * Delivers a socket to the session from the listener.
+	 * @param connection
+	 * @throws Exception
+	 */
+	public void sessionAccepted( T connection ) throws Exception;
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/io/SessionPacket.java b/util/src/main/java/org/apache/etch/util/core/io/SessionPacket.java
new file mode 100644
index 0000000..f7a1704
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/SessionPacket.java
@@ -0,0 +1,39 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.core.Who;
+
+/**
+ * Interface used to deliver packets to the session from the transport.
+ */
+public interface SessionPacket extends Session
+{
+	/**
+	 * Delivers a packet to the session from the transport.
+	 * @param sender the sender of the packet, for transports which allow
+	 * multiple senders. This is who to return any response to.
+	 * @param buf a FlexBuffer positioned at the packet.
+	 * @throws Exception
+	 */
+	public void sessionPacket( Who sender, FlexBuffer buf ) throws Exception;
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/io/TcpConnection.java b/util/src/main/java/org/apache/etch/util/core/io/TcpConnection.java
new file mode 100644
index 0000000..e48ecc3
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/TcpConnection.java
@@ -0,0 +1,175 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.ConnectException;
+import java.net.Socket;
+import java.net.SocketException;
+
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+
+
+/**
+ * Implementation of connection which handles a tcp connection.
+ */
+public class TcpConnection extends TcpTransport
+{
+	/**
+	 * Constructs the Connection from a uri.
+	 * @param socket
+	 * @param uri
+	 * @param resources
+	 */
+	public TcpConnection( Socket socket, String uri, Resources resources )
+	{
+		this( socket, new URL( uri ), resources );
+	}
+	
+	/**
+	 * Constructs the Connection from a uri.
+	 * @param socket
+	 * @param uri
+	 * @param resources
+	 */
+	public TcpConnection( Socket socket, URL uri, Resources resources )
+	{
+		super( uri, resources );
+		
+		if (socket == null)
+		{
+			String h = uri.getHost();
+			if (h == null)
+				throw new IllegalArgumentException( "host == null" );
+			
+			Integer p = uri.getPort();
+			if (p == null)
+				throw new IllegalArgumentException( "port == null" );
+			
+			if (p <= 0 || p > 65535)
+				throw new IllegalArgumentException( "port <= 0 || port > 65535" );
+			
+			this.socket = null;
+			host = h;
+			port = p;
+		}
+		else
+		{
+			this.socket = socket;
+			host = null;
+			port = 0;
+		}
+	}
+
+	private final String host;
+	
+	private final int port;
+	
+	@Override
+	public String toString()
+	{
+		Socket s = socket;
+		
+		if (s != null)
+			return String.format(
+				"TcpConnection(up, %s:%d, %s:%d)",
+				s.getLocalAddress(), s.getLocalPort(),
+				s.getInetAddress(), s.getPort() );
+		
+		return String.format( "TcpConnection(down, %s:%d)", host, port );
+	}
+
+	@Override
+	protected boolean isServer()
+	{
+		return host == null;
+	}
+
+	@Override
+	protected Socket newSocket() throws Exception
+	{
+		try
+		{
+			return new Socket( host, port );
+		}
+		catch ( ConnectException e )
+		{
+			ConnectException x = new ConnectException( "Connection refused: "+host+":"+port );
+			x.initCause( e );
+			throw x;
+		}
+	}
+
+	@Override
+	protected void readSocket() throws Exception
+	{
+		final InputStream is = inputStream;
+		if (is == null)
+			throw new IOException( "socket closed" );
+		
+		// TODO allow setting input buffer size.
+		final FlexBuffer buf = new FlexBuffer( new byte[8192] );
+		
+		try
+		{
+			while (isStarted())
+			{
+//				System.out.println( "reading" );
+				int n = is.read( buf.getBuf() );
+//				System.out.println( "read "+n );
+				
+				if (n <= 0)
+					break;
+				
+				buf.setLength( n );
+				buf.setIndex( 0 );
+				fireData( buf );
+			}
+		}
+		catch ( SocketException e )
+		{
+//			Log.report( "readSocketFailed",
+//				"s.local", s.getLocalSocketAddress(),
+//				"s.remote", s.getRemoteSocketAddress(),
+//				"e", e.toString() );
+			
+			String msg = e.getMessage();
+			if (msg == null)
+				throw e;
+			
+			msg = msg.toLowerCase();
+			
+			if (msg.indexOf( "socket closed" ) >= 0)
+				return;
+			
+			if (msg.indexOf( "recv failed" ) >= 0)
+				return;
+			
+			if (msg.indexOf( "connection reset" ) >= 0)
+				return;
+			
+			throw e;
+		}
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/io/TcpListener.java b/util/src/main/java/org/apache/etch/util/core/io/TcpListener.java
new file mode 100644
index 0000000..08ce6ac
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/TcpListener.java
@@ -0,0 +1,227 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import java.io.IOException;
+import java.net.BindException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+
+
+/**
+ * Implementation of a connection which handles a socket listener.
+ */
+public class TcpListener extends Connection<SessionListener<Socket>>
+	implements Transport<SessionListener<Socket>>
+{
+	/**
+	 * Query term for URI to specify backlog value to ServerSocket. The value
+	 * is "TcpListener.backlog". The backlog must be >= 0 and somewhat
+	 * reasonable. The value 0 specifies the system default, the same as if you
+	 * leave the term off altogether.
+	 * 
+	 * Example: tcp://host:port?TcpListener.backlog=250
+	 * 
+	 * @see #TcpListener(String, Resources)
+	 */
+	public final static String BACKLOG = "TcpListener.backlog";
+	
+	/**
+	 * Constructs a TcpListener, initialized from the URI. Listens on the host
+	 * and port specified in the URI. To listen on all interfaces, specify
+	 * host as ALL_INTFS ("0.0.0.0"). If port is specified or defaulted to 0,
+	 * an unused port will be selected.
+	 * @param uri
+	 * @param resources
+	 */
+	public TcpListener( String uri, Resources resources )
+	{
+		this( new URL( uri ), resources );
+	}
+	
+	/**
+	 * Constructs a TcpListener, initialized from the URI. Listens on the host
+	 * and port specified in the URI. To listen on all interfaces, specify
+	 * host as ALL_INTFS ("0.0.0.0"). If port is specified or defaulted to 0,
+	 * an unused port will be selected.
+	 * @param uri
+	 * @param resources 
+	 * @see URL#getHost()
+	 * @see URL#getPort()
+	 * @see URL#getIntegerTerm(String, int)
+	 * @see #BACKLOG
+	 * @see #ALL_INTFS
+	 * @see #localAddress()
+	 */
+	public TcpListener( URL uri, Resources resources )
+	{
+		this( translateHost( uri.getHost() ), uri.getPort(),
+			uri.getIntegerTerm( BACKLOG, 0 ) );
+	}
+
+	/**
+	 * Constructs the TcpListener.
+	 * @param host address to listen to. Null means any local address.
+	 * @param port port to listen on. Port must be >= 0. Port of 0
+	 * means allocate an available port.
+	 * @param backlog max number of pending connection requests.
+	 */
+	private TcpListener( String host, int port, int backlog )
+	{
+		if (port < 0 || port > 65535)
+			throw new IllegalArgumentException( "port < 0 || port > 65535" );
+		
+		if (backlog < 0)
+			throw new IllegalArgumentException( "backlog < 0" );
+		
+		this.host = host;
+		this.port = port;
+		this.backlog = backlog;
+	}
+	
+	private final String host;
+	
+	private final int port;
+	
+	private final int backlog;
+	
+	@Override
+	protected void stop0() throws Exception
+	{
+		close( true );
+		super.stop0();
+	}
+	
+	private ServerSocket checkSocket() throws IOException
+	{
+		ServerSocket ss = serverSocket;
+		if (ss == null)
+			throw new SocketException( "socket closed" );
+		return ss;
+	}
+
+	private ServerSocket serverSocket;
+	
+	@Override
+	public String toString()
+	{
+		ServerSocket s = serverSocket;
+		
+		if (s != null)
+			return String.format( "TcpListener(up, %s, %d)",
+				s.getInetAddress(), s.getLocalPort() );
+		
+		return String.format( "TcpListener(down, %s, %d)", host, port );
+	}
+
+	@Override
+	protected synchronized boolean openSocket( boolean reconnect ) throws Exception
+	{
+		boolean first = true;
+		while (isStarted())
+		{
+			if (reconnect || !first)
+				return false;
+			
+			try
+			{
+				InetAddress h = host != null ? InetAddress.getByName( host ) : null;
+				try
+				{
+					serverSocket = new ServerSocket( port, backlog, h );
+					return true;
+				}
+				catch ( BindException e )
+				{
+					BindException x = new BindException( "Cannot assign requested address: "+h+":"+port );
+					x.initCause( e );
+					throw x;
+				}
+			}
+			catch ( Exception e )
+			{
+				if (first)
+				{
+					first = false;
+					fireException( "open", e );
+				}
+			}
+		}
+		return false;
+	}
+
+	@Override
+	protected void setupSocket() throws Exception
+	{
+		// nothing to do.
+	}
+
+	@Override
+	protected void readSocket() throws Exception
+	{
+		ServerSocket ss = checkSocket();
+		while (isStarted())
+		{
+			Socket s = ss.accept();
+			try
+			{
+				if (session == null)
+					throw new NullPointerException( "session == null" );
+				session.sessionAccepted( s );
+			}
+			catch ( Exception e )
+			{
+				s.close();
+				fireException( "sessionAccepted", e );
+			}
+		}
+	}
+
+	@Override
+	public void close( boolean reset ) throws Exception
+	{
+		ServerSocket ss = serverSocket;
+		if (ss != null)
+		{
+			serverSocket = null;
+			ss.close();
+		}
+	}
+
+	@Override
+	public SocketAddress localAddress() throws IOException
+	{
+		return checkSocket().getLocalSocketAddress();
+	}
+
+	@Override
+	public SocketAddress remoteAddress()
+	{
+		// ignore.
+		return null;
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/io/TcpOptions.java b/util/src/main/java/org/apache/etch/util/core/io/TcpOptions.java
new file mode 100644
index 0000000..e7f5cc3
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/TcpOptions.java
@@ -0,0 +1,187 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+
+/**
+ * TCP connection options.
+ */
+public class TcpOptions
+{
+	/**
+	 * Constructs TcpOptions from uri and resources.
+	 * 
+	 * @param uri
+	 * @param resources
+	 */
+	public TcpOptions( URL uri, Resources resources )
+	{
+		autoFlush = uri.getBooleanTerm( AUTO_FLUSH, false );
+		bufferSize = checkBufferSize( uri.getIntegerTerm( BUFFER_SIZE, 0 ) );
+		keepAlive = uri.getBooleanTerm( KEEP_ALIVE, false );
+		lingerTime = checkLingerTime( uri.getIntegerTerm( LINGER_TIME, 30 ) );
+		noDelay = uri.getBooleanTerm( NO_DELAY, true );
+		reconnectDelay = checkReconnectDelay( uri.getIntegerTerm(
+			RECONNECT_DELAY, 0 ) );
+		trafficClass = checkTrafficClass( uri.getIntegerTerm( TRAFFIC_CLASS, 0 ) );
+	}
+
+	/**
+	 * Term on the uri which specifies the auto flush flag. The term string is
+	 * "TcpTransport.autoFlush". The value is "true" or "false". The default is
+	 * "false". Auto-flush only applies when the stream is buffered. True means
+	 * that any "sent" data is automatically pushed to the operating systems
+	 * without buffering.
+	 */
+	public final static String AUTO_FLUSH = "TcpTransport.autoFlush";
+
+	/**
+	 * Term on the uri which specifies the output buffer size in bytes. The term
+	 * string is "TcpTransport.bufferSize". The value is an integer between 0
+	 * and 65536. The default is 0, which means no output buffering.
+	 */
+	public final static String BUFFER_SIZE = "TcpTransport.bufferSize";
+
+	/**
+	 * Term on the uri which specifies the keep alive flag. The term string is
+	 * "TcpTransport.keepAlive". The value is "true" or "false". The default is
+	 * "false". Here keep alive refers to TCP specified keep alive, which is not
+	 * the same as any application level keep alive.
+	 */
+	public final static String KEEP_ALIVE = "TcpTransport.keepAlive";
+
+	/**
+	 * Term on the uri which specifies the linger on close time in seconds. The
+	 * term string is "TcpTransport.lingerTime". The value is an integer between
+	 * -1 and 65535. The default is 30. The value -1 means "no linger on close".
+	 * The value determines how long close will wait for buffered but
+	 * unacknowledged data to be delivered. When the time expires, the
+	 * connection will be forcefully closed. (The difference between a linger of
+	 * -1 and a linger of 0 is subtle, but comes down to a close with a linger
+	 * of -1 means perform forceful close while a close with a linger of 0 means
+	 * perform a graceful close if there is no buffered data and a forceful
+	 * close if there is buffered data. A forceful close is send RST, while a
+	 * graceful close means send FIN and wait for FINACK.)
+	 */
+	public final static String LINGER_TIME = "TcpTransport.lingerTime";
+
+	/**
+	 * Term on the uri which specifies the no delay flag. The term string is
+	 * "TcpTransport.noDelay". The value is "true" or "false". The default is
+	 * "true". When true, the operating system will make a best effort to
+	 * transmit data ASAP. When false, data might be delayed somewhat in order
+	 * to allow for more efficient transmission by combining packets (see
+	 * Nagle's Algorithm).
+	 */
+	public final static String NO_DELAY = "TcpTransport.noDelay";
+
+	/**
+	 * Term on the uri which specifies the reconnect delay in milliseconds. The
+	 * term string is "TcpTransport.reconnectDelay". The value is an integer >=
+	 * 0. The default is 0. The value 0 means no automatic reconnection is
+	 * desired.
+	 */
+	public final static String RECONNECT_DELAY = "TcpTransport.reconnectDelay";
+
+	/**
+	 * Term on the uri which specifies the traffic class. The term string is
+	 * "TcpTransport.trafficClass". The value is an integer between 0 and 255.
+	 * The default is 0. The value of this field is network and service specific
+	 * value. It is mapped to the IPv4 type of service (TOS) field and the IPv6
+	 * traffic class field. See also Differentiated Services (DSCP).
+	 */
+	public final static String TRAFFIC_CLASS = "TcpTransport.trafficClass";
+
+	/**
+	 * The auto flush setting for this connection. If true, each call to send
+	 * must automatically call flush.
+	 */
+	public final boolean autoFlush;
+
+	private static int checkBufferSize( int bufferSize )
+	{
+		if (bufferSize < 0 || bufferSize > 65536)
+			throw new IllegalArgumentException(
+				"bufferSize < 0 || bufferSize > 65536" );
+		return bufferSize;
+	}
+
+	/**
+	 * The output buffer size to use for this connection. The value is specified
+	 * as bytes, 0 means unbuffered output. If using buffered output, you'll
+	 * want to disable auto flush and call flush manually only when needed. Only
+	 * meaningful for stream protocols and implementations which use a stream
+	 * interface to the operating system.
+	 */
+	public final int bufferSize;
+
+	/** The tcp keep alive setting for this connection. */
+	public final boolean keepAlive;
+
+	private static int checkLingerTime( int lingerTime )
+	{
+		if (lingerTime < -1 || lingerTime > 240)
+			throw new IllegalArgumentException(
+				"lingerTime < -1 || lingerTime > 240" );
+		return lingerTime;
+	}
+
+	/**
+	 * The tcp linger time setting for this connection. Time in seconds, -1
+	 * means disable.
+	 */
+	public final int lingerTime;
+
+	/**
+	 * The tcp no delay setting for this connection. True disables nagle's
+	 * algorithm and causes all sends to be made asap.
+	 */
+	public final boolean noDelay;
+
+	private static int checkReconnectDelay( int reconnectDelay )
+	{
+		if (reconnectDelay < 0)
+			throw new IllegalArgumentException( "reconnectDelay < 0" );
+		return reconnectDelay;
+	}
+
+	/**
+	 * The reconnect delay for this connection. Time in milliseconds, 0 means do
+	 * not reconnect.
+	 */
+	public final int reconnectDelay;
+
+	private static int checkTrafficClass( int trafficClass )
+	{
+		if (trafficClass < 0 || trafficClass > 255)
+			throw new IllegalArgumentException(
+				"trafficClass < 0 || trafficClass > 255" );
+		return trafficClass;
+	}
+
+	/**
+	 * The traffic class for this connection. 0-255, 0 means normal handling.
+	 * Also called type of service or dscp.
+	 */
+	public final int trafficClass;
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/io/TcpTransport.java b/util/src/main/java/org/apache/etch/util/core/io/TcpTransport.java
new file mode 100644
index 0000000..e74590e
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/TcpTransport.java
@@ -0,0 +1,382 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.Who;
+
+
+/**
+ * Constants and methods related to tcp transport.
+ */
+abstract public class TcpTransport extends Connection<SessionData>
+	implements TransportData
+{
+	/**
+	 * Constructs the TcpTransport. Pulls common parameters off the uri.
+	 *
+	 * @param uri
+	 * @param resources
+	 */
+	protected TcpTransport( URL uri, Resources resources )
+	{
+		options = new TcpOptions( uri, resources );
+	}
+	
+	private final TcpOptions options;
+	
+	@Override
+	protected final void stop0() throws Exception
+	{
+		try
+		{
+			close( false );
+		}
+		catch ( Exception e )
+		{
+			// ignore
+		}
+		super.stop0();
+	}
+
+	/**
+	 * The socket for this connection.
+	 */
+	protected Socket socket;
+
+	/**
+	 * @return the socket for this connection if it is good.
+	 * @throws SocketException if the socket is bad.
+	 */
+	protected final Socket checkSocket() throws SocketException
+	{
+		Socket s = socket;
+		
+		if (s == null)
+			throw new SocketException( "socket closed" );
+		
+		if (s.isClosed())
+			throw new SocketException( "socket closed" );
+		
+		return s;
+	}
+	
+	@Override
+	public final void close( boolean reset )
+	{
+		// Log.report( "close" );
+
+		Socket s = socket;
+		if (s != null)
+		{
+			try
+			{
+				try
+				{
+					if (reset)
+					{
+						s.setSoLinger( false, 0 );
+					}
+					else
+					{
+						flush();
+						shutdownOutput();
+					}
+				}
+				finally
+				{
+					// Log.report( "closing" );
+					s.close();
+					// Log.report( "closed" );
+				}
+			}
+			catch ( IOException e )
+			{
+				// ignore.
+			}
+			finally
+			{
+				inputStream = null;
+				outputStream = null;
+				socket = null;
+			}
+		}
+	}
+
+	/**
+	 * Sends some data to the remote end. If the connection is buffered, the
+	 * data is saved until the buffer is full or the buffer is flushed. If the
+	 * autoFlush setting is true, send automatically flushes the data. If the
+	 * connection is not buffered, the data is sent to the operating system
+	 * immediately. The operating system may or may not transmit the data
+	 * immediately, depending upon the noDelay setting.
+	 * 
+	 * @param buf the bytes to be sent.
+	 * @throws Exception if there is a problem transmitting the data. Such a
+	 * problem causes the current connection to be reset.
+	 * @see #flush()
+	 * @see TcpOptions#AUTO_FLUSH
+	 * @see TcpOptions#BUFFER_SIZE
+	 * @see TcpOptions#NO_DELAY
+	 */
+	public final void send( byte[] buf ) throws Exception
+	{
+		send( buf, 0, buf.length );
+	}
+
+	/**
+	 * Sends some data to the remote end. If the connection is buffered, the
+	 * data is saved until the buffer is full or the buffer is flushed. If the
+	 * autoFlush setting is true, send automatically flushes the data. If the
+	 * connection is not buffered, the data is sent to the operating system
+	 * immediately. The operating system may or may not transmit the data
+	 * immediately, depending upon the noDelay setting.
+	 * @param buf the bytes to be sent.
+	 * @param off the offset into buf of the first byte to send.
+	 * @param len the number of bytes to send.
+	 * @throws Exception if there is a problem transmitting the data. Such a
+	 * problem causes the current connection to be reset.
+	 * @see #flush()
+	 * @see TcpOptions#AUTO_FLUSH
+	 * @see TcpOptions#BUFFER_SIZE
+	 * @see TcpOptions#NO_DELAY
+	 */
+	public final void send( byte[] buf, int off, int len )
+		throws Exception
+	{
+		try
+		{
+			OutputStream os = checkOutputStream();
+			os.write( buf, off, len );
+			if (options.autoFlush)
+				os.flush();
+		}
+		catch ( IOException e )
+		{
+			close( true );
+			throw e;
+		}
+		catch ( RuntimeException e )
+		{
+			close( true );
+			throw e;
+		}
+	}
+
+	/**
+	 * Pushes any buffered data to the wire.
+	 * @throws IOException
+	 */
+	public final void flush() throws IOException
+	{
+		try
+		{
+			checkOutputStream().flush();
+		}
+		catch ( IOException e )
+		{
+			close( true );
+			throw e;
+		}
+		catch ( RuntimeException e )
+		{
+			close( true );
+			throw e;
+		}
+	}
+
+	/**
+	 * @return the output stream if it is still good.
+	 * @throws IOException if the output stream is not good.
+	 */
+	protected final OutputStream checkOutputStream() throws IOException
+	{
+		OutputStream os = outputStream;
+		if (os == null)
+			throw new IOException( "closed" );
+		return os;
+	}
+
+	/**
+	 * Reports some data to the session.
+	 * @param buf
+	 * @throws Exception
+	 */
+	protected final void fireData( FlexBuffer buf ) throws Exception
+	{
+		session.sessionData( null, buf );
+	}
+
+	/**
+	 * This input stream for this connection.
+	 */
+	protected InputStream inputStream;
+
+	/**
+	 * The output stream for this connection.
+	 */
+	protected OutputStream outputStream;
+
+	@Override
+	public SocketAddress localAddress() throws IOException
+	{
+		return checkSocket().getLocalSocketAddress();
+	}
+
+	@Override
+	public final SocketAddress remoteAddress() throws IOException
+	{
+		return checkSocket().getRemoteSocketAddress();
+	}
+
+	public final void transportData( Who recipient, FlexBuffer buf ) throws Exception
+	{
+		send( buf.getBuf(), buf.index(), buf.avail() );
+	}
+
+	@Override
+	protected final void setupSocket() throws Exception
+	{
+		Socket s = checkSocket();
+		
+		s.setKeepAlive( options.keepAlive );
+		s.setSoLinger( options.lingerTime >= 0, options.lingerTime >= 0 ? options.lingerTime : 0 );
+		s.setTcpNoDelay( options.noDelay );
+		s.setTrafficClass( options.trafficClass );
+		
+		inputStream = s.getInputStream();
+		
+		outputStream = s.getOutputStream();
+		if (options.bufferSize > 0)
+			outputStream = new BufferedOutputStream( outputStream, options.bufferSize );
+	}
+
+	/**
+	 * Shuts down the input channel. This side will get an eof reading the
+	 * input. The other side will not be able to tell.
+	 * @throws IOException
+	 */
+	public void shutdownInput() throws IOException
+	{
+		checkSocket().shutdownInput();
+	}
+
+	/**
+	 * Shuts down the output channel. This side will get an error trying to
+	 * send. The other side will get an eof reading the input.
+	 * @throws IOException
+	 */
+	public void shutdownOutput() throws IOException
+	{
+		checkSocket().shutdownOutput();
+	}
+	
+	/**
+	 * @return a new socket for this connection.
+	 * @throws Exception
+	 */
+	abstract protected Socket newSocket() throws Exception;
+	
+	/**
+	 * @return true if this is a listener initiated connection.
+	 */
+	abstract protected boolean isServer();
+	
+	@Override
+	public Object transportQuery( Object query ) throws Exception
+	{
+		if (query == IS_SERVER)
+			return isServer();
+		
+		return super.transportQuery( query );
+	}
+
+	@Override
+	protected synchronized boolean openSocket( boolean reconnect )
+		throws InterruptedException
+	{
+		// if a one time connection from a server socket listener, just
+		// return the existing socket.
+		if (!reconnect && socket != null)
+			return true;
+		
+		// if a one time connection from a server socket listener, and
+		// this is a reconnect, then bail.
+		if (reconnect && isServer())
+			return false;
+		
+		// if a reconnect but no retries allowed, then bail.
+		if (reconnect && options.reconnectDelay == 0)
+			return false;
+		
+		// ok, we don't have an existing socket, and this is either the first
+		// connection attempt or a reconnect with delay > 0.
+		
+		boolean first = true;
+		
+		while (isStarted())
+		{
+			// if reconnect is false and first is true, this is our
+			// very first attempt to connect. otherwise, we are trying
+			// to reconnect a broken link or establish a link where we
+			// have already failed at least once.
+			
+			if (reconnect || !first)
+			{
+				if (options.reconnectDelay == 0)
+					return false;
+				
+				wait( options.reconnectDelay );
+				
+				if (!isStarted())
+					break;
+			}
+			
+			// try to open a socket.
+			
+			try
+			{
+				socket = newSocket();
+				return true;
+			}
+			catch ( Exception e )
+			{
+				if (first)
+				{
+					first = false;
+					fireException( "open", e );
+				}
+			}
+		}
+		
+		return false;
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/io/TlsConnection.java b/util/src/main/java/org/apache/etch/util/core/io/TlsConnection.java
new file mode 100644
index 0000000..a00bac8
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/TlsConnection.java
@@ -0,0 +1,241 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Socket;
+import java.net.SocketException;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+
+
+/**
+ * Implementation of connection which handles a secure tcp connection.
+ */
+public class TlsConnection extends TcpTransport
+{
+	/**
+	 * Term on uri which specifies whether server certificate should be authenticated.
+	 */
+    public static final String AUTH_REQD = "TlsConnection.authReqd";
+	
+	/**
+	 * Constructs the Connection from a uri.
+	 * @param socket
+	 * @param uri
+	 * @param resources
+	 */
+	public TlsConnection( SSLSocket socket, String uri, Resources resources )
+	{
+		this( socket, new URL( uri ), resources );
+	}
+	
+	/**
+	 * Constructs the Connection from a uri.
+	 * @param socket
+	 * @param uri
+	 * @param resources
+	 */
+	public TlsConnection( SSLSocket socket, URL uri, Resources resources )
+	{
+		super( uri, resources );
+		setDefaultAuthReqd( uri.getBooleanTerm( AUTH_REQD, true ) );
+		
+		if (socket == null)
+		{
+			String h = uri.getHost();
+			if (h == null)
+				throw new IllegalArgumentException( "host == null" );
+			
+			Integer p = uri.getPort();
+			if (p == null)
+				throw new IllegalArgumentException( "port == null" );
+			
+			if (p <= 0 || p > 65535)
+				throw new IllegalArgumentException( "port <= 0 || port > 65535" );
+			
+			this.socket = null;
+			host = h;
+			port = p;
+		}
+		else
+		{
+			this.socket = socket;
+			host = null;
+			port = 0;
+		}
+	}
+
+	private final String host;
+	
+	private final int port;
+
+	private void setDefaultAuthReqd( boolean authReqd )
+	{
+		this.authReqd = authReqd;
+	}
+    
+    private boolean authReqd;
+	
+	@Override
+	public String toString()
+	{
+		Socket s = socket;
+		
+		if (s != null)
+			return String.format(
+				"TlsConnection(up, %s:%d, %s:%d)",
+				s.getLocalAddress(), s.getLocalPort(),
+				s.getInetAddress(), s.getPort() );
+		
+		return String.format( "TlsConnection(down, %s:%d)", host, port );
+	}
+
+	@Override
+	protected boolean isServer()
+	{
+		return host == null;
+	}
+
+	@Override
+	protected Socket newSocket() throws Exception
+	{
+		SSLSocketFactory sslsocketfactory = null;
+		if (authReqd)
+		{
+			sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
+		}
+		else
+		{
+			TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager()
+			{
+				public java.security.cert.X509Certificate[] getAcceptedIssuers()
+				{
+					return null;
+				}
+
+				public void checkClientTrusted(
+					java.security.cert.X509Certificate[] certs, String authType )
+				{
+					// ignore
+				}
+
+				public void checkServerTrusted(
+					java.security.cert.X509Certificate[] certs, String authType )
+				{
+					// ignore
+				}
+			} };
+			SSLContext sslc = SSLContext.getInstance( "SSLv3" );
+			sslc.init( null, trustAllCerts, null );
+			sslsocketfactory = sslc.getSocketFactory();
+		}
+		return sslsocketfactory.createSocket( host, port );
+	}
+
+	@Override
+	protected void readSocket() throws Exception
+	{
+		final InputStream is = inputStream;
+		if (is == null)
+			throw new IOException( "socket closed" );
+		
+		// TODO allow setting input buffer size.
+		final FlexBuffer buf = new FlexBuffer( new byte[8192] );
+		
+		try
+		{
+			while (isStarted())
+			{
+//				System.out.println( "reading" );
+				int n = is.read( buf.getBuf() );
+//				System.out.println( "read "+n );
+				
+				if (n <= 0)
+					break;
+				
+				buf.setLength( n );
+				buf.setIndex( 0 );
+				fireData( buf );
+			}
+		}
+		catch ( SSLHandshakeException ex )
+		{
+			SSLHandshakeException exc = new SSLHandshakeException(
+				" Problem in setting up SSL Connection. Either disable"
+					+ " server authentication by using flag TlsConnection.authReqd=false in uri or provide"
+					+ " a truststore location which contains the valid certificate" );
+			// exc.setStackTrace( ex.getStackTrace() );
+			throw exc;
+		}
+		catch ( SocketException e )
+		{
+//			Log.report( "readSocketFailed",
+//				"s.local", s.getLocalSocketAddress(),
+//				"s.remote", s.getRemoteSocketAddress(),
+//				"e", e.toString() );
+			
+			String msg = e.getMessage();
+			if (msg == null)
+				throw e;
+			
+			msg = msg.toLowerCase();
+			
+			if (msg.indexOf( "socket closed" ) >= 0)
+				return;
+			
+			if (msg.indexOf( "Socket is closed" ) >= 0)
+				return;
+			
+			if (msg.indexOf( "recv failed" ) >= 0)
+				return;
+			
+			if (msg.indexOf( "connection reset" ) >= 0)
+				return;
+			
+			throw e;
+		}
+	}
+	
+	@Override
+	public void shutdownInput() throws IOException
+	{
+//		checkSocket().shutdownInput();
+		checkSocket().close();
+	}
+	
+	@Override
+	public void shutdownOutput() throws IOException
+	{
+//		checkSocket().shutdownOutput();
+		checkSocket().close();
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/io/TlsListener.java b/util/src/main/java/org/apache/etch/util/core/io/TlsListener.java
new file mode 100644
index 0000000..d67b9e7
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/TlsListener.java
@@ -0,0 +1,296 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.BindException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.security.KeyStore;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+
+
+/**
+ * Implementation of a connection which handles a secure socket listener.
+ */
+public class TlsListener extends Connection<SessionListener<Socket>>
+	implements Transport<SessionListener<Socket>>
+{
+	/**
+	 * Query term for URI to specify backlog value to ServerSocket. The value
+	 * is "TlsListener.backlog". The backlog must be >= 0 and somewhat
+	 * reasonable. The value 0 specifies the system default, the same as if you
+	 * leave the term off altogether.
+	 * 
+	 * Example: tls://host:port?TlsListener.backlog=250
+	 * 
+	 * @see #TlsListener(String, Resources)
+	 */
+	public final static String BACKLOG = "TlsListener.backlog";
+	
+	/**
+	 * Constructs a TlsListener, initialized from the URI. Listens on the host
+	 * and port specified in the URI. To listen on all interfaces, specify
+	 * host as ALL_INTFS ("0.0.0.0"). If port is specified or defaulted to 0,
+	 * an unused port will be selected.
+	 * @param uri
+	 * @param resources
+	 */
+	public TlsListener( String uri, Resources resources )
+	{
+		this( new URL( uri ), resources );
+	}
+	
+	/**
+	 * Constructs a TlsListener, initialized from the URI. Listens on the host
+	 * and port specified in the URI. To listen on all interfaces, specify
+	 * host as ALL_INTFS ("0.0.0.0"). If port is specified or defaulted to 0,
+	 * an unused port will be selected.
+	 * @param uri
+	 * @param resources 
+	 * @see URL#getHost()
+	 * @see URL#getPort()
+	 * @see URL#getIntegerTerm(String, int)
+	 * @see #BACKLOG
+	 * @see #ALL_INTFS
+	 * @see #localAddress()
+	 */
+	public TlsListener( URL uri, Resources resources )
+	{
+		this( translateHost( uri.getHost() ), uri.getPort(),
+			uri.getIntegerTerm( BACKLOG, 0 ) );
+	}
+
+	/**
+	 * Constructs the TlsListener.
+	 * @param host address to listen to. Null means any local address.
+	 * @param port port to listen on. Port must be >= 0. Port of 0
+	 * means allocate an available port.
+	 * @param backlog max number of pending connection requests.
+	 */
+	private TlsListener( String host, int port, int backlog )
+	{
+		if (port < 0 || port > 65535)
+			throw new IllegalArgumentException( "port < 0 || port > 65535" );
+		
+		if (backlog < 0)
+			throw new IllegalArgumentException( "backlog < 0" );
+		
+		this.host = host;
+		this.port = port;
+		this.backlog = backlog;
+	}
+	
+	private final String host;
+	
+	private final int port;
+	
+	private final int backlog;
+	
+	private String KEYSTORE = null;
+	private char[] KEYSTOREPW = null;
+	private char[] KEYPAIRPWD = null;
+	
+	@Override
+	protected void stop0() throws Exception
+	{
+		close( true );
+		super.stop0();
+	}
+	
+	private SSLServerSocket checkSocket() throws IOException
+	{
+		SSLServerSocket ss = sslServerSocket;
+		if (ss == null)
+			throw new SocketException( "socket closed" );
+		return ss;
+	}
+
+	private SSLServerSocket sslServerSocket;
+	
+	@Override
+	public String toString()
+	{
+		SSLServerSocket s = sslServerSocket;
+		
+		if (s != null)
+			return String.format( "TlsListener(up, %s, %d)",
+				s.getInetAddress(), s.getLocalPort() );
+
+		return String.format( "TlsListener(down, %s, %d)", host, port );
+		
+	}
+
+	@Override
+	protected synchronized boolean openSocket( boolean reconnect ) throws Exception
+	{
+		boolean first = true;
+		while (isStarted())
+		{
+			if (reconnect || !first)
+				return false;
+			
+			try
+			{
+				InetAddress h = host != null ? InetAddress.getByName( host ) : null;
+				try
+				{
+	//				serverSocket = new ServerSocket( port, backlog, h );
+					initializeSSLVariables();
+					KeyStore keystore = KeyStore.getInstance("JKS");
+					keystore.load(new FileInputStream(KEYSTORE), KEYSTOREPW);
+					KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+					kmf.init(keystore, KEYPAIRPWD);
+					SSLContext sslc = SSLContext.getInstance("SSLv3");
+					sslc.init(kmf.getKeyManagers(), null, null);
+					SSLServerSocketFactory sslServerSocketFactory = sslc.getServerSocketFactory();
+					
+			/*		SSLServerSocketFactory sslServerSocketFactory =
+		                   (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();   */
+		            sslServerSocket =
+		                    (SSLServerSocket) sslServerSocketFactory.createServerSocket( port, backlog, h);
+				}
+				catch ( BindException e )
+				{
+					throw new BindException( "Address already in use: "+h+":"+port );
+				}
+				catch (IOException ex)
+				{
+					IOException exc = new IOException(" Problem in setting up SSL Connection. In order to use SSL " +
+						 " please specify valid keystore location and password using VM arguments." );
+					exc.setStackTrace( ex.getStackTrace() );
+					fireException("open",exc);
+					return false;
+				}
+				
+				return true;
+			}
+			catch ( Exception e )
+			{
+				if (first)
+				{
+					first = false;
+					fireException( "open", e );
+				}
+			}
+		}
+		return false;
+	}
+
+	@Override
+	protected void setupSocket() throws Exception
+	{
+		// nothing to do.
+	}
+
+	@Override
+	protected void readSocket() throws Exception
+	{
+		SSLServerSocket ss = checkSocket();
+		while (isStarted())
+		{
+			SSLSocket s = (SSLSocket) ss.accept();
+			try
+			{
+				if (session == null)
+					throw new NullPointerException( "session == null" );
+				session.sessionAccepted( s );
+			}
+			catch ( Exception e )
+			{
+				s.close();
+				fireException( "sessionAccepted", e );
+			}
+		}
+	}
+
+	@Override
+	public void close( boolean reset ) throws Exception
+	{
+		SSLServerSocket ss = sslServerSocket;
+		if (ss != null)
+		{
+			sslServerSocket = null;
+			ss.close();
+		}
+	}
+
+	@Override
+	public SocketAddress localAddress() throws IOException
+	{
+		return checkSocket().getLocalSocketAddress();
+	}
+
+	@Override
+	public SocketAddress remoteAddress()
+	{
+		// ignore.
+		return null;
+	}
+	
+	private void initializeSSLVariables () throws Exception
+	{
+		 String keyStore = System.getProperty("javax.net.ssl.keyStore");
+		  if(keyStore == null) {
+//			  System.out.println("javax.net.ssl.keyStore is not defined");
+			  throw new Exception(" keyStore variable is not defined. Please define keystore location using" +
+			  		" VM Arguments");
+		  }
+		  else
+		  {
+			  KEYSTORE = keyStore;
+//			  System.out.println("javax.net.ssl.keyStore = " + KEYSTORE);
+		  }
+		  
+		  String keypwd = System.getProperty("javax.net.ssl.keyStorePassword");
+		  if(keypwd == null)
+		  {
+//			  System.out.println("javax.net.ssl.keyStorePassword is not defined");
+			  throw new Exception(" KeyStore Password is not define. Please define keystore password using" +
+		  		" VM Arguments");
+		  }
+		  else
+		  {
+			  KEYSTOREPW = keypwd.toCharArray();
+		  }
+		  		  
+		  String keypairpwd = System.getProperty("javax.net.ssl.keyPairPassword");
+		  if(keypairpwd == null) {
+//		   System.out.println("javax.net.ssl.keyPairPassword is not defined");
+		   KEYPAIRPWD = KEYSTOREPW;
+		  }
+		  else {
+			  KEYPAIRPWD = keypairpwd.toCharArray();
+		  }
+	}
+
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/io/Transport.java b/util/src/main/java/org/apache/etch/util/core/io/Transport.java
new file mode 100644
index 0000000..ec2d0d9
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/Transport.java
@@ -0,0 +1,189 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+/**
+ * Out-of-band query, control, and notification interface for transports.
+ * @param <S> the subclass of Session for this Transport.
+ */
+public interface Transport<S extends Session>
+{
+	/**
+	 * Name of value factory in resources.
+	 */
+	public static final String VALUE_FACTORY = "Transport.valueFactory";
+
+	/**
+	 * Returns the session for this transport.
+	 * @return the session for this transport.
+	 */
+	public S getSession();
+	
+	/**
+	 * Sets the session for this transport.
+	 * @param session session to receive data from the transport.
+	 */
+	public void setSession( S session );
+		
+	/**
+	 * Gets a configuration or operational value from the transport. The
+	 * request is passed down the chain of transports until some transport
+	 * recognizes the query, whereupon it returns the requested value.
+	 * 
+	 * @param query an object representing a query, which could be as
+	 * simple as a string, integer, or enum, or more complex such as
+	 * a class with instance variables for query terms.
+	 * 
+	 * @return the requested value, or null if not defined.
+	 * 
+	 * @throws UnsupportedOperationException if the query is not recognized
+	 * by any transport (which is to say, if the last transport in the transport
+	 * chain does not recognize it, it should throw this exception). Typically
+	 * this would be some sort of transport mechanism such as tcp, udp, jms,
+	 * http, sip, etc.
+	 * 
+	 * @throws Exception
+	 */
+	public Object transportQuery( Object query ) throws Exception;
+	
+	/**
+	 * Sets a configuration or operational value in the transport. The
+	 * request is passed down the chain of transports until some transport
+	 * recognizes the control, whereupon it stores the specified value
+	 * and returns.
+	 * 
+	 * @param control an object representing a control, which could be as
+	 * simple as a string, integer, or enum, or more complex such as
+	 * a class with instance variables for control terms.
+	 * 
+	 * @param value the value to set.
+	 * 
+	 * @throws IllegalArgumentException if the value is not the right
+	 * type or if the value is inappropriate.
+	 * 
+	 * @throws UnsupportedOperationException if the control is not recognized
+	 * by any transport (which is to say, if the last transport in the transport
+	 * chain does not recognize it, it should throw this exception). Typically
+	 * this would be some sort of transport mechanism such as tcp, udp, jms,
+	 * http, sip, etc.
+	 * 
+	 * @throws Exception
+	 */
+	public void transportControl( Object control, Object value ) throws Exception;
+	
+	/**
+	 * Notifies the chain of transports of the specified event. Unlike query
+	 * and control operations above, events are always passed down to the
+	 * bottom to allow all transports to notice them (though it is possible
+	 * that an event might be delayed for a bit).
+	 * 
+	 * @param event a class which represents the event, possibly with
+	 * parameters. The simplest event could be a string, integer, or enum,
+	 * but any class instance will do (as long as some transport in the
+	 * chain expects it).
+	 * 
+	 * @throws Exception
+	 */
+	public void transportNotify( Object event ) throws Exception;
+
+	///////////////////////////////////////////////
+	// Well-known queries, controls, and events. //
+	///////////////////////////////////////////////
+	
+	/**
+	 * Transport control which starts the transport stack. The argument
+	 * should be null.
+	 */
+	public final static String START = "START";
+	
+	/**
+	 * Transport control which starts the transport stack and waits
+	 * for it to come up. The argument should be the integer number of
+	 * milliseconds to wait before giving up.
+	 */
+	public final static String START_AND_WAIT_UP = "START_AND_WAIT_UP";
+	
+	/**
+	 * Transport query which waits for the transport stack to come up.
+	 */
+	public class WaitUp
+	{
+		/**
+		 * @param maxDelay max delay in milliseconds.
+		 */
+		public WaitUp( int maxDelay )
+		{
+			this.maxDelay = maxDelay;
+		}
+		
+		/**
+		 * max delay in milliseconds.
+		 */
+		public final int maxDelay;
+	}
+	
+	/**
+	 * Transport control which stops the transport stack. The argument
+	 * should be null, or a Boolean reset (true for instant close,
+	 * false for a nicer, gentler close).
+	 */
+	public final static String STOP = "STOP";
+
+	/**
+	 * Transport control which stops the transport stack and waits
+	 * for it to go down. The argument should be the integer number of
+	 * milliseconds to wait before giving up.
+	 */
+	public final static String STOP_AND_WAIT_DOWN = "STOP_AND_WAIT_DOWN";
+
+	/**
+	 * Transport control which resets the transport stack (e.g., closes the
+	 * socket) without stopping it. If it is set to reconnect, then it will do
+	 * that. Only meaningful for connection oriented transports. Others types
+	 * will ignore this.
+	 */
+	public static final String RESET = "RESET";
+
+	/**
+	 * Transport query which asks is this a listener initiated connection or
+	 * is this a client initiated connection.
+	 */
+	public static final String IS_SERVER = "IS_SERVER";
+
+	/**
+	 * Transport query which waits for the transport stack to go down.
+	 */
+	public class WaitDown
+	{
+		/**
+		 * @param maxDelay max delay in milliseconds.
+		 */
+		public WaitDown( int maxDelay )
+		{
+			this.maxDelay = maxDelay;
+		}
+
+		/**
+		 * max delay in milliseconds.
+		 */
+		public final int maxDelay;
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/io/TransportData.java b/util/src/main/java/org/apache/etch/util/core/io/TransportData.java
new file mode 100644
index 0000000..76c3647
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/TransportData.java
@@ -0,0 +1,39 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.core.Who;
+
+/**
+ * Interface used to deliver data to the transport from the session.
+ */
+public interface TransportData extends Transport<SessionData>
+{
+	/**
+	 * Delivers the data to the transport.
+	 * @param recipient specifies the recipient when there is the possibility
+	 * of more than one.
+	 * @param buf the FlexBuffer positioned on the data.
+	 * @throws Exception
+	 */
+	public void transportData( Who recipient, FlexBuffer buf ) throws Exception;
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/io/TransportPacket.java b/util/src/main/java/org/apache/etch/util/core/io/TransportPacket.java
new file mode 100644
index 0000000..d41e2bc
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/TransportPacket.java
@@ -0,0 +1,46 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.core.Who;
+
+/**
+ * Interface used to deliver packets to the transport from the session.
+ */
+public interface TransportPacket extends Transport<SessionPacket>
+{
+	/**
+	 * Returns the size of the packet header for the transport.
+	 * @return the size of the packet header for the transport.
+	 */
+	public int headerSize();
+	
+	/**
+	 * Delivers the packet to the transport after adding the packet header.
+	 * @param recipient specifies the recipient when there is the possibility
+	 * of more than one.
+	 * @param buf the FlexBuffer positioned on the packet, including space for
+	 * the header.
+	 * @throws Exception
+	 */
+	public void transportPacket( Who recipient, FlexBuffer buf ) throws Exception;
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/io/UdpConnection.java b/util/src/main/java/org/apache/etch/util/core/io/UdpConnection.java
new file mode 100644
index 0000000..9acf223
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/io/UdpConnection.java
@@ -0,0 +1,241 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
+
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.Who;
+
+
+/**
+ * Implementation of connection which handles a udp connection.
+ */
+public class UdpConnection extends Connection<SessionPacket>
+	implements TransportPacket
+{
+	/**
+	 * Term on the uri which specifies the default traffic class.
+	 * @see #setDefaultTrafficClass(int)
+	 */
+	private static final String TRAFFIC_CLASS = "UdpConnection.trafficClass";
+	
+	/**
+	 * Constructs the Connection from a uri.
+	 * @param uri
+	 * @param resources
+	 * @throws Exception
+	 */
+	public UdpConnection( String uri, Resources resources )
+		throws Exception
+	{
+		URL u = new URL( uri );
+		
+		listen = u.getBooleanTerm( "listen", false );
+		
+		host = translateHost( u.getHost() );
+		if (!listen && host == null)
+			throw new IllegalArgumentException( "host == null" );
+		
+		port = u.getPort();
+		if (port == null)
+			throw new IllegalArgumentException( "port == null" );
+		
+		if (port <= 0 || port > 65535)
+			throw new IllegalArgumentException( "port <= 0 || port > 65535" );
+		
+		setDefaultTrafficClass( u.getIntegerTerm( TRAFFIC_CLASS, 0 ) );
+		
+		// there are three ways to do this:
+		// 1. bound socket, unconnected (listening to anyone on well-known host/port
+		// 2. bound socket, connected (listening to someone on well-known host/port)
+		// 3. unbound socket, connected (listening to someone on assigned host/port)
+	}
+	
+	private final String host;
+	
+	private final Integer port;
+	
+	private final boolean listen;
+	
+	private DatagramSocket socket;
+	
+	// TODO assign defaultRecipient a value somehow
+	private Who defaultRecipient;
+	
+	/**
+	 * Sets the default value for the traffic class (or type of service
+	 * or dscp). For example, call signaling traffic is classified as
+	 * DSCP CS3 (011000) with resulting traffic class value of 01100000,
+	 * 0x60, or 96. For more on DSCP see RFC 2474 (supercedes TOS defined
+	 * in RFC 791)
+	 * @param trafficClass traffic class or type of service or dscp. The
+	 * default is 0, which implies normal handling.
+	 */
+	public void setDefaultTrafficClass( int trafficClass )
+	{
+		this.trafficClass = trafficClass;
+	}
+	
+	private int trafficClass = 0;
+
+	@Override
+	protected synchronized boolean openSocket( boolean reconnect ) throws Exception
+	{
+		if (socket != null)
+			socket.close();
+		
+		socket = new DatagramSocket();
+		
+		if (listen)
+			socket.bind( host != null ? new InetSocketAddress( host, port ) : new InetSocketAddress( port ) );
+		else
+			socket.connect( new InetSocketAddress( host, port ) );
+		
+		if (!reconnect && socket != null)
+			return true;
+		
+		return false;
+	}
+
+	@Override
+	protected void setupSocket() throws Exception
+	{
+		DatagramSocket s = checkSocket();
+		
+		s.setTrafficClass( trafficClass );
+	}
+
+	@Override
+	protected void readSocket() throws Exception
+	{
+		final DatagramSocket s = checkSocket();
+		// TODO allow buffer size to be specified.
+		final FlexBuffer buf = new FlexBuffer( new byte[8192] );
+		final DatagramPacket p = new DatagramPacket( new byte[0], 0 );
+		
+		try
+		{
+			while (isStarted())
+			{
+				p.setData( buf.getBuf() );
+				
+				s.receive( p );
+				
+				buf.setIndex( 0 );
+				buf.setLength( p.getLength() );
+				
+				if (s.isConnected())
+					session.sessionPacket( null, buf );
+				else
+					session.sessionPacket( getWho( p.getAddress(), p.getPort() ), buf );
+			}
+		}
+		catch ( SocketException e )
+		{
+			if ("socket closed".equalsIgnoreCase( e.getMessage()))
+				return;
+			throw e;
+		}
+	}
+
+	private DatagramSocket checkSocket() throws IOException
+	{
+		DatagramSocket s = socket;
+		if (s == null || s.isClosed())
+			throw new SocketException( "socket closed" );
+		return s;
+	}
+	
+	private Who getWho( InetAddress address, int port )
+	{
+		if (lastWho == null || !lastWho.matches( address, port ))
+			lastWho = new InetWho( address, port );
+		return lastWho;
+	}
+	
+	private InetWho lastWho;
+	
+	private final DatagramPacket outp = new DatagramPacket( new byte[0], 0 );
+
+	public void transportPacket( Who recipient, FlexBuffer buf ) throws IOException
+	{
+//		System.out.printf( "packet( %s, buf( %d, %d ))", recipient, buf.index(), buf.avail() );
+		if (socket.isConnected())
+		{
+			outp.setData( buf.getBuf(), buf.index(), buf.avail() );
+			socket.send( outp );
+			return;
+		}
+		
+		if (recipient == null)
+			recipient = defaultRecipient;
+		
+		if (recipient != null)
+		{
+			InetWho iw = (InetWho) recipient;
+			outp.setData( buf.getBuf(), buf.index(), buf.avail() );
+			outp.setAddress( iw.getInetAddress() );
+			outp.setPort( iw.getPort() );
+			socket.send( outp );
+			
+			return;
+		}
+		
+		throw new IllegalArgumentException( "no recipient" );
+	}
+
+	public int headerSize()
+	{
+		return 0;
+	}
+
+	@Override
+	public void close( boolean reset )
+	{
+		DatagramSocket s = socket;
+		if (s != null)
+		{
+			socket = null;
+			s.close();
+		}
+	}
+
+	@Override
+	public SocketAddress localAddress()
+	{
+		return socket.getLocalSocketAddress();
+	}
+
+	@Override
+	public SocketAddress remoteAddress()
+	{
+		return socket.getRemoteSocketAddress();
+	}
+}
\ No newline at end of file
diff --git a/util/src/main/java/org/apache/etch/util/core/nio/AbstractHandler.java b/util/src/main/java/org/apache/etch/util/core/nio/AbstractHandler.java
new file mode 100644
index 0000000..3bfd549
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/nio/AbstractHandler.java
@@ -0,0 +1,261 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+
+/**
+ * Abstract implementation of Handler.
+ * @param <T>
+ */
+public class AbstractHandler<T extends SelectableChannel>
+	implements Handler<T>
+{
+	/**
+	 * @param channel
+	 */
+	public AbstractHandler( T channel )
+	{
+		this.channel = channel;
+	}
+	
+	private final T channel;
+
+	public final T channel()
+	{
+		return channel;
+	}
+
+	public final void registered( Selector selector, SelectionKey key )
+	{
+		this.selector = selector;
+		this.key = key;
+		registered();
+	}
+
+	private Selector selector;
+	
+	private SelectionKey key;
+	
+	/**
+	 * @return the Selector of the handler.
+	 */
+	public final Selector selector()
+	{
+		return selector;
+	}
+
+	public final SelectionKey key()
+	{
+		return key;
+	}
+	
+	/**
+	 * Notifies the handler that it has been registered with a selector.
+	 */
+	protected void registered()
+	{
+		// nothing to do.
+	}
+
+	public final int getLastInterestOps()
+	{
+		return lastInterestOps;
+	}
+
+	public final void setLastInterestOps( int ops )
+	{
+		lastInterestOps = ops;
+	}
+
+	private int lastInterestOps;
+	
+	public final void selected() throws Exception
+	{
+		SelectionKey k = key;
+		if (k == null)
+			return;
+		
+		int ops = k.readyOps();
+		
+		if ((ops & SelectionKey.OP_ACCEPT) != 0)
+		{
+			doAccept();
+			return;
+		}
+		
+		if ((ops & SelectionKey.OP_CONNECT) != 0)
+		{
+			doConnect();
+			return;
+		}
+		
+		if ((ops & SelectionKey.OP_READ) != 0)
+			doRead();
+		
+		if ((ops & SelectionKey.OP_WRITE) != 0)
+			doWrite();
+	}
+
+	protected void doAccept() throws Exception
+	{
+		throw new IOException( "doAccept not implemented" );
+	}
+
+	protected void doConnect() throws Exception
+	{
+		throw new IOException( "doConnect not implemented" );
+	}
+
+	protected void doRead() throws Exception
+	{
+		throw new IOException( "doRead not implemented" );
+	}
+
+	protected void doWrite() throws Exception
+	{
+		throw new IOException( "doWrite not implemented" );
+	}
+
+	public final int getInterestOps() throws Exception
+	{
+		if (canAccept())
+			return SelectionKey.OP_ACCEPT;
+		
+		if (canConnect())
+			return SelectionKey.OP_CONNECT;
+		
+		int ops = canRead() ? SelectionKey.OP_READ : 0;
+		
+		if (canWrite())
+			ops |= SelectionKey.OP_WRITE;
+		
+		return ops;
+	}
+	
+	/**
+	 * @return true if this handler can accept. Called from
+	 * {@link #getInterestOps()}.
+	 * @throws Exception 
+	 */
+	protected boolean canAccept() throws Exception
+	{
+		return false;
+	}
+	
+	/**
+	 * @return true if this handler can connect. Called from
+	 * {@link #getInterestOps()}.
+	 * @throws Exception 
+	 */
+	protected boolean canConnect() throws Exception
+	{
+		return false;
+	}
+	
+	/**
+	 * @return true if this handler can read. Called from
+	 * {@link #getInterestOps()}.
+	 * @throws Exception 
+	 */
+	protected boolean canRead() throws Exception
+	{
+		return false;
+	}
+	
+	/**
+	 * @return true if this handler can write. Called from
+	 * {@link #getInterestOps()}.
+	 * @throws Exception 
+	 */
+	protected boolean canWrite() throws Exception
+	{
+		return false;
+	}
+
+	/**
+	 * Updates the interest ops of the channel.
+	 */
+	public final void updateInterestOps()
+	{
+		Selector s = selector;
+		if (s == null)
+			throw new IllegalStateException( "selector == null" );
+		s.updateInterestOps( this );
+	}
+	
+	/**
+	 * Cancels the registration of this handler.
+	 */
+	public final void cancel()
+	{
+		Selector s = selector;
+		if (s != null)
+			s.cancel( this );
+		else
+			canceled( null );
+	}
+	
+	public void canceled( Exception e )
+	{
+		try
+		{
+			if (e != null)
+				reportException( e );
+			
+			if (key != null)
+				key.cancel();
+			
+			channel.close();
+		}
+		catch ( Exception e1 )
+		{
+			reportException( e1 );
+		}
+		finally
+		{
+			selector = null;
+			key = null;
+		}
+	}
+
+	public void reportException( Exception e )
+	{
+		if (e instanceof IOException)
+		{
+			if (e instanceof EOFException)
+				return;
+			
+			String msg = e.getMessage();
+			if (msg != null)
+			{
+				if (msg.equals( "An existing connection was forcibly closed by the remote host" ))
+					return;
+			}
+		}
+		
+		System.err.printf( "%s: caught exception: %s\n", this, e );
+		e.printStackTrace();
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/nio/AcceptHandler.java b/util/src/main/java/org/apache/etch/util/core/nio/AcceptHandler.java
new file mode 100644
index 0000000..df617db
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/nio/AcceptHandler.java
@@ -0,0 +1,89 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+import java.io.EOFException;
+import java.net.InetSocketAddress;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+/**
+ * Selector.Handler for a tcp listening port.
+ */
+public class AcceptHandler extends AbstractHandler<ServerSocketChannel>
+{
+	/**
+	 * @param channel
+	 * @param factory 
+	 */
+	public AcceptHandler( ServerSocketChannel channel, StreamHandlerFactory factory )
+	{
+		super( channel );
+		this.factory = factory;
+	}
+	
+	private final StreamHandlerFactory factory;
+	
+	@Override
+	public String toString()
+	{
+		return String.format( "AcceptHandler(%s)", channel().socket().getLocalSocketAddress() );
+	}
+	
+	@Override
+	protected boolean canAccept()
+	{
+		return true;
+	}
+
+	@Override
+	protected final void doAccept() throws Exception
+	{
+		SocketChannel sc = channel().accept();
+		try
+		{
+			sc.configureBlocking( false );
+			acceptedChannel( sc );
+		}
+		catch ( EOFException e )
+		{
+			sc.close();
+		}
+		catch ( Exception e )
+		{
+			e.printStackTrace();
+			sc.close();
+		}
+	}
+	
+	protected void acceptedChannel( SocketChannel sc ) throws Exception
+	{
+		selector().register( factory.newStreamHandler( sc, false ) );
+	}
+
+	/**
+	 * @return the listening address of this accept handler.
+	 */
+	public InetSocketAddress getLocalSocketAddress()
+	{
+		return (InetSocketAddress) channel().socket().getLocalSocketAddress();
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/nio/AcceptHandlerFactory.java b/util/src/main/java/org/apache/etch/util/core/nio/AcceptHandlerFactory.java
new file mode 100644
index 0000000..227e85f
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/nio/AcceptHandlerFactory.java
@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+import java.nio.channels.ServerSocketChannel;
+
+/**
+ * Factory to create StreamHandler for AcceptHandler.
+ */
+public interface AcceptHandlerFactory
+{
+	/**
+	 * Creates a new AcceptHandler for a ServerSocketChannel.
+	 * @param channel a channel managed by AcceptHandler.
+	 * @return an AcceptHandler for the specified channel.
+	 * @throws Exception 
+	 */
+	public AcceptHandler newAcceptHandler( ServerSocketChannel channel )
+		throws Exception;
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/nio/ByteBufferPool.java b/util/src/main/java/org/apache/etch/util/core/nio/ByteBufferPool.java
new file mode 100644
index 0000000..cf9ed23
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/nio/ByteBufferPool.java
@@ -0,0 +1,390 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.etch.util.AlarmListener;
+import org.apache.etch.util.AlarmManager;
+import org.apache.etch.util.Todo;
+import org.apache.etch.util.TodoManager;
+
+
+/**
+ * A shared pool of buffers.
+ */
+public class ByteBufferPool implements AlarmListener
+{
+	/**
+	 * Constructs a ByteBufferPool.
+	 * @param bufferSize the size of each individual buffer.
+	 * @param min the minimum number of buffers to keep in the pool.
+	 * @param limit the maximum number of buffers to allow.
+	 * @param interval the number of milliseconds between history tickle.
+	 * @param length the length of history to maintain.
+	 */
+	public ByteBufferPool( int bufferSize, int min, int limit,
+		int interval, int length )
+	{
+		if (bufferSize <= 0)
+			throw new IllegalArgumentException( "bufferSize <= 0" );
+		
+		if (interval < 0)
+			throw new IllegalArgumentException( "interval < 0" );
+		
+		if (interval == 0 || length == 0)
+		{
+			// if either is 0, force both to 0.
+			interval = 0;
+			length = 0;
+		}
+		
+		this.bufferSize = bufferSize;
+		this.interval = interval;
+		
+		history = new History( min, limit, length );
+		
+		if (interval > 0)
+			AlarmManager.staticAdd( this, null, interval );
+	}
+
+	/** The size of buffers to allocate. */
+	private final int bufferSize;
+	
+	/** Time in milliseconds between history tickles. */
+	private final int interval;
+
+	private final History history;
+
+	/**
+	 * @return the size of the buffers being managed.
+	 */
+	public int bufferSize()
+	{
+		return bufferSize;
+	}
+
+	/**
+	 * @return the minimum number of buffers to maintain.
+	 */
+	public int min()
+	{
+		return history.min();
+	}
+
+	/**
+	 * @return the maximum number of buffers to allocate.
+	 */
+	public int limit()
+	{
+		return history.limit();
+	}
+
+	/**
+	 * @return the history tickle interval in ms.
+	 */
+	public int interval()
+	{
+		return interval;
+	}
+
+	/**
+	 * @return the history tickle length.
+	 */
+	public int length()
+	{
+		return history.length();
+	}
+
+	/**
+	 * Allocates a buffer from the pool.
+	 * 
+	 * @param notify object to be notified when a buffer is released into the
+	 * pool.
+	 * @return a buffer from the pool or null if the pool is empty and notify is
+	 * not null.
+	 * @throws IOException the pool is empty and notify is null.
+	 */
+	public ByteBuffer alloc( Notify notify ) throws IOException
+	{
+		synchronized (saved)
+		{
+			if (!history.used( 1 ))
+			{
+				if (notify == null)
+					throw new IOException( "out of buffers" );
+
+				// notify != null
+				register( notify );
+				return null;
+			}
+
+			try
+			{
+				return allocBuf();
+			}
+			catch ( Error e )
+			{
+				history.used( -1 );
+				throw e;
+			}
+			catch ( RuntimeException e )
+			{
+				history.used( -1 );
+				throw e;
+			}
+		}
+	}
+
+	/**
+	 * Allocates some buffers from the pool.
+	 * 
+	 * @param notify object to be notified when a buffer is released into the
+	 * pool.
+	 * @param count the number of buffers required.
+	 * @return an array of allocated buffers.
+	 * @throws IOException
+	 */
+	public ByteBuffer[] alloc( Notify notify, int count ) throws IOException
+	{
+		if (count <= 0)
+			throw new IllegalArgumentException( "count <= 0" );
+
+		if (count > history.limit())
+			throw new IllegalArgumentException( "count > limit" );
+
+		synchronized (saved)
+		{
+			if (!history.used( count ))
+			{
+				if (notify == null)
+					throw new IOException( "out of buffers" );
+
+				// notify != null
+				register( notify );
+				return null;
+			}
+
+			ByteBuffer[] bufs = new ByteBuffer[count];
+			
+			try
+			{
+				for (int i = 0; i < count; i++)
+					bufs[i] = allocBuf();
+			}
+			catch ( Error e )
+			{
+				release( bufs );
+				throw e;
+			}
+			catch ( RuntimeException e )
+			{
+				release( bufs );
+				throw e;
+			}
+			
+			return bufs;
+		}
+	}
+
+	/**
+	 * Releases a buffer back into the pool. If there are waiters for a buffer
+	 * being released into the pool, they are notified.
+	 * 
+	 * @param buf
+	 */
+	public void release( ByteBuffer buf )
+	{
+		synchronized (saved)
+		{
+			releaseBuf( buf );
+			notifyWaiters();
+		}
+	}
+
+	/**
+	 * Releases some buffers back into the pool. If there are waiters for a
+	 * buffer being released into the pool, they are notified.
+	 * 
+	 * @param bufs
+	 */
+	public void release( ByteBuffer[] bufs )
+	{
+		if (bufs == null || bufs.length == 0)
+			return;
+
+		synchronized (saved)
+		{
+			for (ByteBuffer buf : bufs)
+				releaseBuf( buf );
+
+			notifyWaiters();
+		}
+	}
+
+	private ByteBuffer allocBuf()
+	{
+		// used has already been incremented.
+		
+		// we need a buffer, get a saved one if any...
+
+		if (!saved.isEmpty())
+		{
+			ByteBuffer buf = saved.remove( saved.size() - 1 );
+			buf.clear();
+			return buf;
+		}
+
+		ByteBuffer buf = ByteBuffer.allocateDirect( bufferSize );
+		history.alloc( 1 );
+		return buf;
+	}
+
+	private void releaseBuf( ByteBuffer buf )
+	{
+		if (buf == null)
+			return;
+		
+		history.used( -1 );
+
+		// save the buffer if there aren't already too many, drop the rest.
+		
+		if (saved.size() < history.suggested())
+			saved.add( buf );
+		else
+			history.alloc( -1 );
+	}
+	
+	private void trimSaved()
+	{
+		synchronized (saved)
+		{
+			int n = history.suggested();
+			while (saved.size() > n)
+			{
+				saved.remove( saved.size()-1 );
+				history.alloc( -1 );
+			}
+		}
+	}
+
+	private final List<ByteBuffer> saved = new ArrayList<ByteBuffer>();
+
+	/**
+	 * Registers for notification of available buffer. Note that when you are
+	 * notified, your registration is canceled. You can always re-register in
+	 * the bufferAvailable method.
+	 * 
+	 * @param notify
+	 */
+	public void register( Notify notify )
+	{
+		synchronized (waiters)
+		{
+			waiters.add( notify );
+		}
+	}
+
+	/**
+	 * Removes a registration for notification of available buffer.
+	 * 
+	 * @param notify
+	 */
+	public void unregister( Notify notify )
+	{
+		synchronized (waiters)
+		{
+			waiters.remove( notify );
+		}
+	}
+
+	private void notifyWaiters()
+	{
+		final Notify[] notifies;
+
+		synchronized (waiters)
+		{
+			int n = waiters.size();
+			if (n == 0)
+				return;
+
+			notifies = waiters.toArray( new Notify[n] );
+			waiters.clear();
+		}
+
+		TodoManager.addTodo( new Todo()
+		{
+			public void doit( TodoManager mgr ) throws Exception
+			{
+				for (Notify n : notifies)
+					n.bufferAvailable( ByteBufferPool.this );
+			}
+
+			public void exception( TodoManager mgr, Exception e )
+			{
+				e.printStackTrace();
+			}
+		} );
+	}
+
+	private final List<Notify> waiters = new LinkedList<Notify>();
+
+	public int wakeup( AlarmManager manager, Object state, long due )
+	{
+		history.tickle();
+		trimSaved();
+		return interval;
+	}
+	
+	/**
+	 * Called when this ByteBufferPool is no longer active. Removes the history
+	 * tickle.
+	 */
+	public void shutdown()
+	{
+		AlarmManager.staticRemove( this );
+	}
+
+	/**
+	 * Interface to notify interested parties about available buffers.
+	 */
+	public interface Notify
+	{
+		/**
+		 * Notifies that the pool has an available buffer.
+		 * 
+		 * @param pool
+		 */
+		public void bufferAvailable( ByteBufferPool pool );
+	}
+
+	/**
+	 * @return the count of buffers currently allocated.
+	 */
+	public int used()
+	{
+		return history.getUsed();
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/nio/Handler.java b/util/src/main/java/org/apache/etch/util/core/nio/Handler.java
new file mode 100644
index 0000000..ff98fc3
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/nio/Handler.java
@@ -0,0 +1,95 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+
+/**
+ * A handler which wraps a SelectableChannel.
+ * @param <T> the subclass of SelectableChannel for this Handler.
+ */
+public interface Handler<T extends SelectableChannel>
+{
+	/**
+	 * @return the handler's channel.
+	 */
+	public T channel();
+
+	/**
+	 * @return the computed interest ops.
+	 * @throws Exception 
+	 */
+	public int getInterestOps() throws Exception;
+
+	/**
+	 * @return the last computed interest ops saved per
+	 * {@link #setLastInterestOps(int)}.
+	 */
+	public int getLastInterestOps();
+
+	/**
+	 * Saves the last computed interest ops set in the selection key.
+	 * @param ops
+	 */
+	public void setLastInterestOps( int ops );
+
+	/**
+	 * Notifies the handler that it has been registered with the Selector.
+	 * @param selector the Selector holding the registration.
+	 * @param key the selection key.
+	 * @throws Exception 
+	 */
+	public void registered( Selector selector, SelectionKey key )
+		throws Exception;
+
+	/**
+	 * @return the selection key of the channel.
+	 */
+	public SelectionKey key();
+
+	/**
+	 * Notifies the handler that it has been selected. When selected returns,
+	 * the {@link #getInterestOps()} method will be called to get any updates
+	 * to the interests. If this method throws an exception, the Handler will
+	 * be canceled.
+	 * @throws Exception 
+	 */
+	public void selected() throws Exception;
+
+	/**
+	 * Notifies the handler that its registration has been canceled. Any
+	 * Selector or SelectionKey information should be forgotten, and perhaps
+	 * the channel should be closed.
+	 * @param e an exception which caused the cancellation.
+	 * @throws Exception 
+	 */
+	public void canceled( Exception e ) throws Exception;
+	
+	/**
+	 * Reports an exception which is causing this handler to be canceled. The
+	 * exception is by default reported to the selector if still registered,
+	 * or printed on stderr if not registered. Override this method to report
+	 * the problem some other way.
+	 * @param e
+	 */
+	public void reportException( Exception e );
+}
\ No newline at end of file
diff --git a/util/src/main/java/org/apache/etch/util/core/nio/History.java b/util/src/main/java/org/apache/etch/util/core/nio/History.java
new file mode 100644
index 0000000..abd3a29
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/nio/History.java
@@ -0,0 +1,241 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+/**
+ * History keeps track of pooled resource allocations, plus maintains historical
+ * information to better judge what a reasonable pool size for resources is.
+ */
+public class History
+{
+	/**
+	 * Constructs a History.
+	 * @param min the minimum number of used items.
+	 * @param limit the maximum number of used items.
+	 * @param len the length of the history of used items over time.
+	 */
+	public History( int min, int limit, int len )
+	{
+		if (min < 0)
+			throw new IllegalArgumentException( "min < 0" );
+		
+		if (limit < min)
+			throw new IllegalArgumentException( "limit < min" );
+
+		if (len < 0)
+			throw new IllegalArgumentException( "len < 0" );
+
+		this.min = min;
+		this.limit = limit;
+		history = new int[len];
+		
+		init();
+	}
+
+	/** The minimum number of used items. */
+	private final int min;
+
+	/** The maximum number of used items. */
+	private final int limit;
+
+	/** The history of used items over time. */
+	private final int[] history;
+
+	/**
+	 * @return the maximum number of used items.
+	 */
+	public int limit()
+	{
+		return limit;
+	}
+
+	/**
+	 * @return the minimum number of used items.
+	 */
+	public int min()
+	{
+		return min;
+	}
+	
+	/**
+	 * @return the length of the history.
+	 */
+	public int length()
+	{
+		return history.length;
+	}
+
+	/**
+	 * Adjusts the number of items being used. This is the number of items which
+	 * have been allocated but not yet released.
+	 * 
+	 * @param k positive if items are being allocated, negative if items are
+	 * being released. Items might be released by being returned to some system
+	 * facility, or they might be saved in a pool.
+	 * @return true if the new value of used does not exceed the limit.
+	 * @throws IllegalStateException if the new value of used would be < 0.
+	 */
+	public boolean used( int k )
+	{
+		if (k == 0)
+			throw new IllegalArgumentException( "k == 0" );
+
+		int newUsed = used + k;
+
+		if (newUsed > limit)
+			return false; // overflow
+
+		if (newUsed < 0)
+			throw new IllegalStateException( "newUsed < 0" );
+
+		used = newUsed;
+		bump( used );
+		return true;
+	}
+
+	/**
+	 * @return the number of items being used.
+	 */
+	public int getUsed()
+	{
+		return used;
+	}
+
+	private int used;
+
+	/**
+	 * Adjusts the number of items actually allocated or freed from some system
+	 * facility rather than just from a pool. The number of used items
+	 * can never exceed the number allocated. The number of allocated items
+	 * equals used plus the current size of the pool.
+	 * 
+	 * @param k positive if items are being allocated, negative if items are
+	 * being released.
+	 */
+	public void alloc( int k )
+	{
+		if (k == 0)
+			throw new IllegalArgumentException( "k == 0" );
+
+		int newAlloc = alloc + k;
+
+		if (newAlloc > limit)
+			throw new IllegalStateException( "newAlloc > limit" );
+
+		if (newAlloc < 0)
+			throw new IllegalStateException( "newAlloc < 0" );
+
+		alloc = newAlloc;
+	}
+
+	/**
+	 * @return the number of items allocated.
+	 */
+	public int getAlloc()
+	{
+		return alloc;
+	}
+
+	private int alloc;
+
+	/**
+	 * Initialize (or re-initialize) the history.
+	 */
+	public void init()
+	{
+		synchronized (history)
+		{
+			int h = Math.max( min, used );
+			
+			for (int i = 0; i < history.length; i++)
+				history[i] = h;
+
+			highwatermark = h;
+			suggested = h;
+		}
+	}
+
+	/**
+	 * Tickles the history. The oldest value of history is discarded, and the
+	 * others are all pushed down one, and the newest value is initialized to
+	 * min. This should be called periodically on a regular schedule.
+	 */
+	public void tickle()
+	{
+		synchronized (history)
+		{
+			if (history.length == 0)
+				return;
+			
+			System.arraycopy( history, 0, history, 1, history.length - 1 );
+			history[0] = highwatermark;
+			highwatermark = Math.max( min, used );
+
+			// recalculate suggested size
+
+			suggested = recalc( history );
+		}
+	}
+
+	/**
+	 * Recalculates the suggested size for pool of allocated but unused items.
+	 * Various algorithms might be used, including those that might use average
+	 * history (the default) or something based on 1st or 2nd order derivitives
+	 * of that.
+	 * 
+	 * @return recalculated suggested size for pool of allocated but unused
+	 * items.
+	 */
+	protected int recalc( int[] hstry )
+	{
+		int sum = 0;
+		for (int h : hstry)
+			sum += h;
+		return sum / hstry.length;
+	}
+
+	/**
+	 * Updates the high water mark in light of a new value of used.
+	 * 
+	 * @param value the new value of used.
+	 */
+	private void bump( int value )
+	{
+		synchronized (history)
+		{
+			if (value > highwatermark)
+				highwatermark = value;
+		}
+	}
+
+	private int highwatermark;
+
+	private int suggested;
+
+	/**
+	 * @return the suggested size of a pool for quick allocation. This
+	 * might be statically configured or based on recent activity.
+	 */
+	public int suggested()
+	{
+		return suggested;
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/nio/Selector.java b/util/src/main/java/org/apache/etch/util/core/nio/Selector.java
new file mode 100644
index 0000000..1382e8b
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/nio/Selector.java
@@ -0,0 +1,446 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+import java.io.IOException;
+import java.nio.channels.CancelledKeyException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ClosedSelectorException;
+import java.nio.channels.SelectionKey;
+import java.util.LinkedList;
+
+import org.apache.etch.util.Assertion;
+
+
+/**
+ * An experiment in selection.
+ */
+public class Selector extends Thread
+{
+	/**
+	 * Maximum number of keys allowed in this Selector.
+	 */
+	public static final int MAX_KEYS = 64;
+
+	/**
+	 * Constructs the selector.
+	 * @param id a unique id for this selector.
+	 * @param ss the containing super selector.
+	 * @throws IOException 
+	 */
+	public Selector( int id, SuperSelector ss ) throws IOException
+	{
+		this.id = id;
+		this.ss = ss;
+		selector = java.nio.channels.Selector.open();
+		ssAdd();
+	}
+	
+	private final int id;
+	
+	private final SuperSelector ss;
+
+	private final java.nio.channels.Selector selector;
+
+	/**
+	 * @return the unique id of this selector.
+	 */
+	public int id()
+	{
+		return id;
+	}
+	
+	@Override
+	public String toString()
+	{
+		return "Selector."+id;
+	}
+
+	////////////
+	// THREAD //
+	////////////
+
+	@Override
+	public void run()
+	{
+		try
+		{
+			while (selector.isOpen())
+			{
+				runActions();
+				
+				int n;
+				while ( true )
+				{
+					try
+					{
+						n = selector.select();
+						break;
+					}
+					catch( IOException e )
+					{
+						// Workaround, see sun bug 6693490
+						//System.out.println("****** caught IOException");
+						if ( e.getMessage() != null && e.getMessage().indexOf("File exists") != -1 )
+							continue;
+						throw e;
+					}
+				}
+//				Log.report( "selected", "selector", this, "n", n );
+				if (n > 0)
+				{
+					for (SelectionKey key : selector.selectedKeys())
+						handleSelection( key );
+					selector.selectedKeys().clear();
+				}
+			}
+		}
+		catch ( ClosedSelectorException e )
+		{
+			// ignore.
+		}
+		catch ( Exception e )
+		{
+			reportException( e );
+		}
+		finally
+		{
+			ss.remove( this );
+			try
+			{
+				// TODO remove and cancel all the keys
+				selector.close();
+			}
+			catch ( Exception e )
+			{
+				reportException( e );
+			}
+		}
+	}
+	
+	private void reportException( Exception e )
+	{
+		System.err.printf( "%s: caught exception: %s\n", this, e );
+		e.printStackTrace();
+	}
+
+	//////////////////
+	// SAFE ACTIONS //
+	//////////////////
+
+	/**
+	 * Schedules a registration of the handler with this Selector if it
+	 * isn't full, creates a new Selector if this Selector is full.
+	 * @param handler
+	 */
+	public void register( final Handler<?> handler )
+	{
+		checkNotShutdown();
+		
+		enqueueAction( false, new Action()
+		{
+			public void run()
+			{
+				try
+				{
+					actionRegister( handler );
+				}
+				catch ( Exception e )
+				{
+					try
+					{
+						actionCancel( handler, e );
+					}
+					catch ( Exception e1 )
+					{
+						handler.reportException( e1 );
+					}
+				}
+			}
+		} );
+	}
+
+	private void checkNotShutdown()
+	{
+		if (shutdown)
+			throw new IllegalStateException( "shutdown" );
+	}
+
+	/**
+	 * Schedules an update to the handler's interest ops with this Selector.
+	 * @param handler
+	 */
+	public void updateInterestOps( final Handler<?> handler )
+	{
+		enqueueAction( false, new Action()
+		{
+			public void run()
+			{
+				try
+				{
+					actionUpdateInterestOps( handler );
+				}
+				catch ( Exception e )
+				{
+					try
+					{
+						actionCancel( handler, e );
+					}
+					catch ( Exception e1 )
+					{
+						handler.reportException( e1 );
+					}
+				}
+			}
+		} );
+	}
+
+	/**
+	 * Schedules a cancel of the handler with this Selector.
+	 * @param handler
+	 */
+	public void cancel( final Handler<?> handler )
+	{
+		enqueueAction( true, new Action()
+		{
+			public void run()
+			{
+				try
+				{
+					actionCancel( handler, null );
+				}
+				catch ( Exception e )
+				{
+					handler.reportException( e );
+				}
+			}
+		} );
+	}
+
+	/**
+	 * Shuts down the selector.
+	 */
+	public void shutdown()
+	{
+		if (shutdown)
+			return;
+		
+		shutdown = true;
+		
+		enqueueAction( false, new Action()
+		{
+			public void run()
+			{
+				try
+				{
+					actionShutdown();
+				}
+				catch ( Exception e )
+				{
+					reportException( e );
+				}
+			}
+		} );
+	}
+	
+	private boolean shutdown;
+
+	////////////////////
+	// UNSAFE ACTIONS //
+	////////////////////
+
+	private void actionRegister( Handler<?> handler ) throws Exception
+	{
+		// this action is called from the selector thread.
+		
+		int n = selector.keys().size();
+		if (n >= MAX_KEYS)
+		{
+			ss.register( handler );
+			return;
+		}
+
+		int ops = handler.getInterestOps();
+		
+		Assertion.check( !handler.channel().isRegistered(), "!handler.channel().isRegistered()" );
+		Assertion.check( handler.key() == null, "handler.key() == null" );
+		
+		SelectionKey key = handler.channel().register( selector, ops, handler );
+		handler.setLastInterestOps( ops );
+		handler.registered( this, key );
+	}
+
+	private void actionUpdateInterestOps( Handler<?> handler ) throws Exception
+	{
+		// this action is called from the selector thread.
+		
+		SelectionKey key = handler.key();
+		if (key != null)
+		{
+			int ops = handler.getInterestOps();
+			if (ops != handler.getLastInterestOps())
+			{
+				key.interestOps( ops );
+				handler.setLastInterestOps( ops );
+			}
+		}
+	}
+
+	private void actionCancel( Handler<?> handler, Exception e ) throws Exception
+	{
+		// this action is called from the selector thread.
+		
+		handler.canceled( e );
+	}
+	
+	private void actionShutdown() throws Exception
+	{
+		selector.close();
+	}
+
+	/////////////////
+	// ACTION LIST //
+	/////////////////
+
+	private void runActions()
+	{
+		Action action;
+		while ((action = dequeueAction()) != null)
+			action.run();
+		ssUpdate();
+	}
+	
+	private void ssAdd()
+	{
+		size = selector.keys().size();
+		ss.add( this, MAX_KEYS-size );
+	}
+
+	private void ssUpdate()
+	{
+		size = selector.keys().size();
+		ss.update( this, MAX_KEYS-size );
+	}
+	
+	private int size;
+
+	private void enqueueAction( boolean priority, Action action )
+	{
+		synchronized (actions)
+		{
+			boolean wasEmpty = actions.isEmpty();
+			
+			if (priority)
+				actions.addFirst( action );
+			else
+				actions.addLast( action );
+			
+			if (wasEmpty)
+				selector.wakeup();
+		}
+	}
+
+	private Action dequeueAction()
+	{
+		synchronized (actions)
+		{
+			return actions.poll();
+		}
+	}
+
+	private final LinkedList<Action> actions = new LinkedList<Action>();
+	
+	//////////////////////
+	// HANDLE SELECTION //
+	//////////////////////
+	
+	private void handleSelection( SelectionKey key )
+	{
+		Handler<?> handler = (Handler<?>) key.attachment();
+		
+		if (handler == null)
+		{
+			try
+			{
+				key.channel().close();
+			}
+			catch ( IOException e )
+			{
+				reportException( e );
+			}
+			return;
+		}
+
+		try
+		{
+			handler.selected();
+			actionUpdateInterestOps( handler );
+		}
+		catch ( ClosedChannelException e )
+		{
+			// ignore
+		}
+		catch ( CancelledKeyException e )
+		{
+			// ignore
+		}
+		catch ( Exception e )
+		{
+			try
+			{
+				actionCancel( handler, e );
+			}
+			catch ( Exception e1 )
+			{
+				handler.reportException( e1 );
+			}
+		}
+	}
+
+	/**
+	 * Performs an action on a handler, such as registering it with the
+	 * selector, updating its interest ops, or closing it.
+	 */
+	public interface Action
+	{
+		/**
+		 * Runs the action when the selector is available to control.
+		 */
+		public void run();
+	}
+
+	/**
+	 * Dumps the handlers in this selector.
+	 */
+	public void dump()
+	{
+		for (SelectionKey k: selector.keys())
+		{
+			Object a = k.attachment();
+			if (a == null)
+			{
+				System.out.printf( "%s: channel %s\n", this, k.channel() );
+				continue;
+			}
+			System.out.printf( "%s: attachment %s\n", this, a );
+		}
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/nio/StreamHandler.java b/util/src/main/java/org/apache/etch/util/core/nio/StreamHandler.java
new file mode 100644
index 0000000..4c7b71c
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/nio/StreamHandler.java
@@ -0,0 +1,110 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+
+/**
+ * Handler for TCP stream channels.
+ */
+public class StreamHandler extends AbstractHandler<SocketChannel>
+{
+	/**
+	 * Constructs the StreamHandler.
+	 * @param channel
+	 * @param wantsConnect
+	 * @throws IOException
+	 */
+	public StreamHandler( SocketChannel channel, boolean wantsConnect )
+		throws IOException
+	{
+		super( channel );
+		
+		this.wantsConnect = wantsConnect;
+		
+		if (!wantsConnect)
+			connected();
+	}
+	
+	private boolean wantsConnect;
+	
+	@Override
+	protected final boolean canConnect()
+	{
+		return wantsConnect;
+	}
+	
+	@Override
+	protected final void doConnect() throws IOException
+	{
+		wantsConnect = !channel().finishConnect();
+		
+		if (!wantsConnect)
+			connected();
+	}
+	
+	protected void connected() throws IOException
+	{
+		// nothing to do.
+	}
+
+	/**
+	 * Reads from the channel of this handler.
+	 * @param rbuf the ByteBuffer to read into.
+	 * @return the count of bytes read.
+	 * @throws IOException
+	 */
+	public int read( ByteBuffer rbuf ) throws IOException
+	{
+		return channel().read( rbuf );
+	}
+
+	/**
+	 * Writes to the channel of this handler.
+	 * @param wbuf the ByteBuffer to write from. It is flipped first, and
+	 * compacted after.
+	 * @return the count of bytes written.
+	 * @throws IOException
+	 */
+	public int write( ByteBuffer wbuf ) throws IOException
+	{
+		try
+		{
+			wbuf.flip();
+			return wbuf.hasRemaining() ? channel().write( wbuf ) : 0;
+		}
+		finally
+		{
+			wbuf.compact();
+		}
+	}
+
+	/**
+	 * Shuts down output on the channel of this handler.
+	 * @throws IOException
+	 */
+	public void shutdownOutput() throws IOException
+	{
+		channel().socket().shutdownOutput();
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/nio/StreamHandlerFactory.java b/util/src/main/java/org/apache/etch/util/core/nio/StreamHandlerFactory.java
new file mode 100644
index 0000000..bee0bc8
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/nio/StreamHandlerFactory.java
@@ -0,0 +1,42 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+import java.io.IOException;
+import java.nio.channels.SocketChannel;
+
+/**
+ * Factory to create StreamHandler for AcceptHandler.
+ */
+public interface StreamHandlerFactory
+{
+	/**
+	 * Creates a new StreamHandler for a SocketChannel.
+	 * @param channel a channel accepted by AcceptHandler.
+	 * @param wantsConnect true if this socket is connecting and
+	 * needs a connected event to be selected.
+	 * @return a StreamHandler for the specified channel.
+	 * @throws IOException if a StreamHandler cannot be made.
+	 * @throws Exception 
+	 */
+	public StreamHandler newStreamHandler( SocketChannel channel,
+		boolean wantsConnect ) throws Exception;
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/nio/SuperSelector.java b/util/src/main/java/org/apache/etch/util/core/nio/SuperSelector.java
new file mode 100644
index 0000000..5be921d
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/nio/SuperSelector.java
@@ -0,0 +1,359 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.TreeMap;
+
+import org.apache.etch.util.Assertion;
+
+
+/**
+ * Models the external api of a Selector while keeping a list of available
+ * selectors and their load.
+ */
+public class SuperSelector
+{
+	/**
+	 * Marks the SuperSelector as open for business.
+	 */
+	public void start()
+	{
+		checkStarted( false );
+		started = true;
+	}
+	
+	private void checkStarted( boolean expected )
+	{
+		if (expected != started)
+			throw new IllegalStateException( expected ? "not started" : "started" );
+	}
+
+	private boolean started;
+	
+	/**
+	 * Shuts down the SuperSelector, closing all the existing selectors and
+	 * handlers.
+	 */
+	public void shutdown()
+	{
+		started = false;
+	}
+	
+	/**
+	 * Adds the Selector to the set of available selectors, it is new created.
+	 * @param selector
+	 * @param avail the number of available slots.
+	 */
+	public void add( Selector selector, int avail )
+	{
+		checkStarted( true );
+		Key k = new Key( avail, selector );
+		if (!sel2keys.containsKey( selector ))
+		{
+			sel2keys.put( selector, k );
+			keysAdd( k );
+		}
+	}
+
+	private final Map<Selector, Key> sel2keys =
+		Collections.synchronizedMap( new HashMap<Selector, Key>() );
+
+	/**
+	 * Updates the Selector's capacity in the set of available selectors.
+	 * @param selector
+	 * @param avail the number of available slots.
+	 */
+	public void update( Selector selector, int avail )
+	{
+		checkStarted( true );
+		
+		Key k = sel2keys.get( selector );
+		Assertion.check( k != null, "k != null" );
+		
+		synchronized (_keys)
+		{
+			if (avail != k.avail())
+			{
+				keysRemove( k );
+				k.setAvail( avail );
+				keysAdd( k );
+			}
+		}
+	}
+
+	/**
+	 * Removes the Selector from the set of available selectors. It is dead.
+	 * @param selector 
+	 */
+	public void remove( Selector selector )
+	{
+		Key k = sel2keys.remove( selector );
+		if (k != null)
+			keysRemove( k );
+	}
+	
+	private void keysAdd( Key k )
+	{
+		synchronized (_keys)
+		{
+			if (k.avail() > 0)
+			{
+				Key o = _keys.put( k, k );
+//				System.out.printf( "add %s => %s\n", k, o );
+				Assertion.check( o == null, "o == null" );
+			}
+			else
+			{
+				Assertion.check( _keys.get( k ) == null, "_keys.get( k ) == null" );
+			}
+		}
+	}
+
+	private void keysRemove( Key k )
+	{
+		synchronized (_keys)
+		{
+			Key o = _keys.remove( k );
+//			System.out.printf( "remove %s => %s\n", k, o );
+			Assertion.check( o == k || o == null, "o == k || o == null" );
+		}
+	}
+	
+	private Selector getSelector() throws IOException
+	{
+		synchronized (_keys)
+		{
+			try
+			{
+				Key k = _keys.firstKey();
+				keysRemove( k );
+				k.setAvail( k.avail()-1 );
+				keysAdd( k );
+				return k.selector;
+			}
+			catch ( NoSuchElementException e )
+			{
+				Selector s = new Selector( _id++, this );
+				// constructor calls us back at #add(Selector, int)
+				s.start();
+				return s;
+			}
+		}
+	}
+	
+	private final TreeMap<Key, Key> _keys = new TreeMap<Key, Key>();
+	
+	private int _id;
+
+	/**
+	 * Registers the handler with an available Selector. This may be called by
+	 * an external thread or by one of the Selector threads.
+	 * @param handler
+	 * @throws IOException 
+	 */
+	public void register( Handler<?> handler ) throws IOException
+	{
+		checkStarted( true );
+		getSelector().register( handler );
+		
+	}
+
+	/**
+	 * @param addr
+	 * @param backlog
+	 * @param factory
+	 * @return a new AcceptHandler already registered with this selector.
+	 * @throws Exception
+	 */
+	public AcceptHandler newAcceptHandler( InetSocketAddress addr, int backlog,
+		AcceptHandlerFactory factory ) throws Exception
+	{
+		ServerSocketChannel ssc = ServerSocketChannel.open();
+		ssc.configureBlocking( false );
+		ServerSocket ss = ssc.socket();
+		ss.bind( addr, backlog );
+		AcceptHandler ah = factory.newAcceptHandler( ssc );
+		register( ah );
+		return ah;
+	}
+	
+	/**
+	 * @param addr
+	 * @param factory
+	 * @return a new StreamHandler already registered with this selector.
+	 * @throws Exception
+	 */
+	public StreamHandler newStreamHandler( InetSocketAddress addr,
+		StreamHandlerFactory factory ) throws Exception
+	{
+		SocketChannel sc = SocketChannel.open();
+		sc.configureBlocking( false );
+		StreamHandler sh = factory.newStreamHandler( sc, true );
+		register( sh );
+		sc.connect( addr );
+		return sh;
+	}
+
+	/**
+	 * @param sc
+	 * @param factory
+	 * @return a new StreamHandler already registered with this selector.
+	 * @throws Exception
+	 */
+	public StreamHandler newStreamHandler( SocketChannel sc,
+		StreamHandlerFactory factory ) throws Exception
+	{
+		sc.configureBlocking( false );
+		StreamHandler sh = factory.newStreamHandler( sc, false );
+		register( sh );
+		return sh;
+	}
+	
+	private static class Key implements Comparable<Key>
+	{
+		public Key( int avail, Selector selector )
+		{
+			_avail = avail;
+			this.selector = selector;
+		}
+
+		private int _avail;
+		
+		private final Selector selector;
+		
+		@Override
+		public String toString()
+		{
+			return String.format( "Key(%d, %s)", _avail, selector );
+		}
+		
+		public int avail()
+		{
+			return _avail;
+		}
+
+		public void setAvail( int avail )
+		{
+			_avail = avail;
+		}
+		
+		@Override
+		public int hashCode()
+		{
+			return _avail ^ selector.hashCode();
+		}
+		
+		@Override
+		public boolean equals( Object obj )
+		{
+			if (obj == this)
+				return true;
+			
+			if (obj == null || obj.getClass() != Key.class)
+				return false;
+			
+			Key k = (Key) obj;
+			return _avail == k._avail && selector == k.selector;
+		}
+
+		public int compareTo( Key k )
+		{
+			if (_avail < k._avail)
+				return -1;
+			
+			if (_avail > k._avail)
+				return 1;
+			
+			// avail == k.avail
+			
+			if (selector.id() < k.selector.id())
+				return -1;
+			
+			if (selector.id() > k.selector.id())
+				return 1;
+			
+			return 0;
+		}
+	}
+
+	/**
+	 * 
+	 */
+	public void dump()
+	{
+		synchronized (_keys)
+		{
+			for (Key k: _keys.values())
+				System.out.printf( "key: %d %s\n", k.avail(), k.selector );
+			
+			for (Key k: _keys.values())
+				k.selector.dump();
+		}
+	}
+
+	/**
+	 * @return the statically configured Selector, or one newly configured if
+	 * none.
+	 */
+	public static SuperSelector get()
+	{
+		if (selector == null)
+		{
+			synchronized (sync)
+			{
+				if (selector == null)
+				{
+					selector = new SuperSelector();
+					selector.start();
+				}
+			}
+		}
+		return selector;
+	}
+	
+	/**
+	 * Replaces the current statically configured selector with a new one.
+	 * @param newSelector
+	 * @return the old statically configured selected.
+	 */
+	public static SuperSelector put( SuperSelector newSelector )
+	{
+		synchronized (sync)
+		{
+			SuperSelector oldSelector = selector;
+			selector = newSelector;
+			return oldSelector;
+		}
+	}
+	
+	private static SuperSelector selector;
+	
+	private final static Object sync = new Object();
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/nio/Tcp2Connection.java b/util/src/main/java/org/apache/etch/util/core/nio/Tcp2Connection.java
new file mode 100644
index 0000000..504f831
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/nio/Tcp2Connection.java
@@ -0,0 +1,596 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+import java.util.LinkedList;
+
+import org.apache.etch.util.AlarmListener;
+import org.apache.etch.util.AlarmManager;
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.Monitor;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.Todo;
+import org.apache.etch.util.TodoManager;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.Session;
+import org.apache.etch.util.core.io.SessionData;
+import org.apache.etch.util.core.io.TcpConnection;
+import org.apache.etch.util.core.io.TcpOptions;
+import org.apache.etch.util.core.io.TransportData;
+
+
+/**
+ * A TCP-based transport based on selectors.
+ */
+public class Tcp2Connection implements TransportData, StreamHandlerFactory, AlarmListener
+{
+	/**
+	 * @param uri
+	 * @param resources
+	 */
+	public Tcp2Connection( String uri, Resources resources )
+	{
+		this( new URL( uri ), resources );
+	}
+
+	/**
+	 * @param uri
+	 * @param resources
+	 */
+	public Tcp2Connection( URL uri, Resources resources )
+	{
+		selector = (SuperSelector) resources.get( "selector" );
+		bufferPool = (ByteBufferPool) resources.get( "bufferPool" );
+		options = new TcpOptions( uri, resources );
+
+		connection = (SocketChannel) resources.remove( "connection" );
+
+		if (connection == null)
+		{
+			String h = uri.getHost();
+			if (h == null)
+				throw new IllegalArgumentException( "host == null" );
+
+			Integer p = uri.getPort();
+			if (p == null)
+				throw new IllegalArgumentException( "port == null" );
+
+			if (p <= 0 || p > 65535)
+				throw new IllegalArgumentException( "port <= 0 || port > 65535" );
+
+			host = h;
+			port = p;
+		}
+		else
+		{
+			host = null;
+			port = 0;
+		}
+	}
+
+	private final SuperSelector selector;
+	
+	private final ByteBufferPool bufferPool;
+
+	private final TcpOptions options;
+
+	private SocketChannel connection;
+
+	private final String host;
+
+	private final int port;
+
+	@Override
+	public String toString()
+	{
+		try
+		{
+			Socket s = checkSocket();
+			return String.format( "Tcp2Connection(up, %s:%d, %s:%d)", s
+				.getLocalAddress(), s.getLocalPort(), s.getInetAddress(), s
+				.getPort() );
+		}
+		catch ( IOException e )
+		{
+			return String.format( "Tcp2Connection(down, %s:%d)", host, port );
+		}
+	}
+
+	protected boolean isServer()
+	{
+		return host == null;
+	}
+
+	// ///////////
+	// SESSION //
+	// ///////////
+
+	public SessionData getSession()
+	{
+		return session;
+	}
+
+	public void setSession( SessionData session )
+	{
+		this.session = session;
+	}
+
+	private SessionData session;
+
+	// /////////////
+	// TRANSPORT //
+	// /////////////
+
+	public Object transportQuery( Object query ) throws Exception
+	{
+		if (query == IS_SERVER)
+			return isServer();
+
+		if (query == TcpConnection.LOCAL_ADDRESS)
+			return localAddress();
+
+		if (query == TcpConnection.REMOTE_ADDRESS)
+			return remoteAddress();
+
+		if (query instanceof WaitUp)
+		{
+			waitUp( ((WaitUp) query).maxDelay );
+			return null;
+		}
+
+		if (query instanceof WaitDown)
+		{
+			waitDown( ((WaitDown) query).maxDelay );
+			return null;
+		}
+
+		throw new UnsupportedOperationException( "unknown query: " + query );
+	}
+
+	public void transportControl( Object control, Object value )
+		throws Exception
+	{
+		if (control == START)
+		{
+			start();
+			return;
+		}
+
+		if (control == START_AND_WAIT_UP)
+		{
+			start();
+			waitUp( (Integer) value );
+			return;
+		}
+
+		if (control == STOP)
+		{
+			stop();
+			return;
+		}
+
+		if (control == STOP_AND_WAIT_DOWN)
+		{
+			stop();
+			waitDown( (Integer) value );
+			return;
+		}
+
+		if (control == RESET)
+		{
+			close( true );
+			return;
+		}
+
+		throw new UnsupportedOperationException( "unknown control: " + control );
+	}
+
+	public void transportNotify( Object event ) throws Exception
+	{
+		// nothing to do.
+	}
+
+	public void transportData( Who recipient, FlexBuffer buf ) throws Exception
+	{
+		int n = buf.avail();
+		if (n == 0)
+			return;
+		
+		MyStreamHandler h = checkHandler();
+
+		// TODO better job with buffers
+		
+		ByteBuffer bb = ByteBuffer.allocateDirect( n );
+		bb.put( buf.getBuf(), buf.index(), n );
+		
+		bb.flip();
+		h.writeBuf( bb );
+	}
+
+	// //////////////////
+	// IMPLEMENTATION //
+	// //////////////////
+
+	void start() throws Exception
+	{
+		synchronized (startedSync)
+		{
+			if (started)
+				throw new IllegalStateException( "started" );
+			
+			started = true;
+			restart();
+		}
+	}
+	
+	private void restart() throws Exception
+	{
+		if (host != null)
+		{
+//			MyStreamHandler h = (MyStreamHandler)
+			selector.newStreamHandler( new InetSocketAddress( host, port ), this );
+			//setHandler( h ); // fireUp will do it
+			return;
+		}
+
+		SocketChannel c = connection;
+		if (c != null)
+		{
+			connection = null;
+//			MyStreamHandler h = (MyStreamHandler)
+			selector.newStreamHandler( c, this );
+			//setHandler( h ); // fireUp will do it
+			return;
+		}
+
+		throw new IOException( "cannot start, no connection" );
+	}
+
+	private boolean started;
+	
+	private final Object startedSync = new Object();
+
+	private MyStreamHandler setHandler( MyStreamHandler newHandler )
+	{
+		synchronized (handlerSync)
+		{
+			if (newHandler == handler)
+				return null;
+			
+			if (newHandler != null && handler != null)
+				throw new IllegalStateException(
+					"newHandler != null && handler != null && newHandler != handler" );
+			
+			MyStreamHandler oldHandler = handler;
+			handler = newHandler;
+			return oldHandler;
+		}
+	}
+
+	private MyStreamHandler handler;
+	
+	private final Object handlerSync = new Object();
+
+	void stop() throws IOException
+	{
+		started = false;
+		
+		MyStreamHandler h = setHandler( null );
+		if (h != null)
+		{
+			h.shutdownOutput();
+			h.cancel();
+		}
+	}
+
+	void close( boolean reset )
+	{
+		MyStreamHandler h = setHandler( null );
+		if (h != null)
+		{
+			if (reset)
+			{
+				try
+				{
+					h.setLinger( false, 0 );
+				}
+				catch ( Exception e )
+				{
+					e.printStackTrace();
+				}
+			}
+			h.cancel();
+		}
+	}
+
+	private void fireUp( MyStreamHandler h )
+	{
+		setHandler( h );
+		status.set( Session.UP );
+		
+		TodoManager.addTodo( new Todo()
+		{
+			public void doit( TodoManager m ) throws Exception
+			{
+				session.sessionNotify( Session.UP );
+			}
+
+			public void exception( TodoManager m, Exception e )
+			{
+				e.printStackTrace();
+			}
+		} );
+	}
+
+	private void fireDown()
+	{
+		setHandler( null );
+		status.set( Session.DOWN );
+		
+		if (started && host != null && options.reconnectDelay > 0)
+			AlarmManager.staticAdd( this, 0, options.reconnectDelay );
+		
+		TodoManager.addTodo( new Todo()
+		{
+			public void doit( TodoManager m ) throws Exception
+			{
+				session.sessionNotify( Session.DOWN );
+			}
+
+			public void exception( TodoManager m, Exception e )
+			{
+				e.printStackTrace();
+			}
+		} );
+	}
+
+	private void fireException( String what, final Exception e )
+	{
+		TodoManager.addTodo( new Todo()
+		{
+			public void doit( TodoManager m ) throws Exception
+			{
+				session.sessionNotify( e );
+			}
+
+			public void exception( TodoManager m, Exception ex )
+			{
+				e.printStackTrace();
+				if (ex != e)
+					ex.printStackTrace();
+			}
+		} );
+	}
+
+	void waitUp( int maxDelay ) throws Exception
+	{
+		status.waitUntilEq( Session.UP, maxDelay );
+	}
+
+	void waitDown( int maxDelay ) throws Exception
+	{
+		status.waitUntilEq( Session.DOWN, maxDelay );
+	}
+
+	private final Monitor<String> status = new Monitor<String>( "status",
+		Session.DOWN );
+
+	SocketAddress remoteAddress() throws IOException
+	{
+		return checkSocket().getRemoteSocketAddress();
+	}
+
+	SocketAddress localAddress() throws IOException
+	{
+		return checkSocket().getLocalSocketAddress();
+	}
+
+	private Socket checkSocket() throws IOException
+	{
+		Socket s = checkChannel().socket();
+		if (s == null)
+			throw new IOException( "no socket" );
+		return s;
+	}
+
+	private SocketChannel checkChannel() throws IOException
+	{
+		SocketChannel c = checkHandler().channel();
+		if (c == null)
+			throw new IOException( "no channel" );
+		return c;
+	}
+
+	private MyStreamHandler checkHandler() throws IOException
+	{
+		MyStreamHandler h = handler;
+		if (h == null)
+			throw new IOException( "no handler" );
+		return h;
+	}
+
+	public MyStreamHandler newStreamHandler( SocketChannel channel,
+		boolean wantsConnect ) throws Exception
+	{
+		return new MyStreamHandler( channel, wantsConnect );
+	}
+
+	class MyStreamHandler extends StreamHandler
+	{
+		public MyStreamHandler( SocketChannel channel, boolean wantsConnect )
+			throws IOException
+		{
+			super( channel, wantsConnect );
+		}
+
+		@Override
+		protected void connected() throws IOException
+		{
+			super.connected();
+			
+			Socket s = channel().socket();
+
+			s.setKeepAlive( options.keepAlive );
+			s.setSoLinger( options.lingerTime >= 0,
+				options.lingerTime >= 0 ? options.lingerTime : 0 );
+			s.setTcpNoDelay( options.noDelay );
+			s.setTrafficClass( options.trafficClass );
+
+			fireUp( this );
+		}
+
+		public void setLinger( boolean on, int linger ) throws IOException
+		{
+			Socket s = channel().socket();
+			s.setSoLinger( on, linger );
+		}
+
+		public void writeBuf( ByteBuffer bb ) throws IOException
+		{
+			synchronized (wlist)
+			{
+				if (!bb.hasRemaining())
+					return;
+
+				if (!wlist.isEmpty())
+				{
+					wlist.add( bb );
+					return;
+				}
+
+				channel().write( bb );
+				if (!bb.hasRemaining())
+					return;
+
+				// there's some leftovers...
+
+				wlist.add( bb );
+				updateInterestOps();
+			}
+		}
+		
+		@Override
+		protected boolean canRead() throws Exception
+		{
+			return true;
+		}
+		
+		@Override
+		protected void doRead() throws Exception
+		{
+			ByteBuffer buf = bufferPool.alloc( null );
+			try
+			{
+				int n = read( buf );
+				if (n <= 0)
+					throw new EOFException( "n <= 0" );
+				
+				buf.flip();
+				byte[] bbuf = new byte[buf.remaining()];
+				buf.get( bbuf );
+				
+				FlexBuffer fbuf = new FlexBuffer( bbuf );
+				session.sessionData( null, fbuf );
+			}
+			finally
+			{
+				if (buf != null)
+					bufferPool.release( buf );
+			}
+			
+		}
+
+		@Override
+		protected boolean canWrite() throws Exception
+		{
+			return !wlist.isEmpty();
+		}
+
+		private final LinkedList<ByteBuffer> wlist = new LinkedList<ByteBuffer>();
+
+		@Override
+		protected void doWrite() throws Exception
+		{
+			synchronized (wlist)
+			{
+				ByteBuffer buf = wlist.getFirst();
+				write( buf );
+				if (!buf.hasRemaining())
+					wlist.removeFirst();
+			}
+		}
+
+		@Override
+		public int write( ByteBuffer wbuf ) throws IOException
+		{
+			throw new IOException( "don't use this!" );
+		}
+
+		@Override
+		public void canceled( Exception e )
+		{
+			super.canceled( e );
+			fireDown();
+		}
+	}
+
+	boolean isStarted()
+	{
+		return started;
+	}
+
+	void close()
+	{
+		close( false );
+	}
+
+	/**
+	 * @throws IOException
+	 */
+	public void shutdownOutput() throws IOException
+	{
+		StreamHandler h = handler;
+		if (h != null)
+			h.shutdownOutput();
+	}
+
+	public int wakeup( AlarmManager manager, Object state, long due )
+	{
+		try
+		{
+			restart();
+			return 0;
+		}
+		catch ( Exception e )
+		{
+			fireException( "reconnect", e );
+			return started ? options.reconnectDelay : 0;
+		}
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/nio/Tcp2Listener.java b/util/src/main/java/org/apache/etch/util/core/nio/Tcp2Listener.java
new file mode 100644
index 0000000..c53f010
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/nio/Tcp2Listener.java
@@ -0,0 +1,427 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+import org.apache.etch.util.Monitor;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.Todo;
+import org.apache.etch.util.TodoManager;
+import org.apache.etch.util.URL;
+import org.apache.etch.util.core.io.Session;
+import org.apache.etch.util.core.io.SessionListener;
+import org.apache.etch.util.core.io.TcpConnection;
+import org.apache.etch.util.core.io.Transport;
+
+
+/**
+ * Selector based TCP listener.
+ * 
+ */
+public class Tcp2Listener implements Transport<SessionListener<SocketChannel>>,
+	AcceptHandlerFactory
+{
+	/**
+	 * @param uri
+	 * @param resources
+	 */
+	public Tcp2Listener( String uri, Resources resources )
+	{
+		this( new URL( uri ), resources );
+	}
+
+	/**
+	 * @param uri
+	 * @param resources
+	 */
+	public Tcp2Listener( URL uri, Resources resources )
+	{
+		this( uri.getHost(), uri.getPort(), uri
+			.getIntegerTerm( "backlog", 0 ), resources );
+	}
+
+	private Tcp2Listener( String host, Integer port, int backlog,
+		Resources resources )
+	{
+		if (port == null)
+			throw new IllegalArgumentException( "port not specified" );
+		
+		if (port < 0 || port > 65535)
+			throw new IllegalArgumentException( "port < 0 || port > 65535" );
+		
+		if (backlog < 0)
+			throw new IllegalArgumentException( "backlog < 0" );
+
+		selector = (SuperSelector) resources.get( "selector" );
+
+		this.host = host;
+		this.port = port;
+		this.backlog = backlog;
+	}
+
+	private final SuperSelector selector;
+
+	private final String host;
+
+	private final int port;
+
+	private final int backlog;
+
+	/**
+	 * Host name to specify to select listening on all interfaces. The value is
+	 * "0.0.0.0".
+	 */
+	public static final String ALL_INTFS = "0.0.0.0";
+
+	/**
+	 * @param s
+	 * @return null if s is null or ALL_INTFS ("0.0.0.0").
+	 */
+	protected static String translateHost( String s )
+	{
+		if (s != null && s.equals( ALL_INTFS ))
+			return null;
+		return s;
+	}
+
+	@Override
+	public String toString()
+	{
+		ServerSocket s = null;
+
+		if (s != null)
+			return String.format( "Tcp2Listener(up, %s, %d)", s
+				.getInetAddress(), s.getLocalPort() );
+
+		return String.format( "Tcp2Listener(down, %s, %d)", host, port );
+	}
+
+	// ///////////
+	// SESSION //
+	// ///////////
+
+	public SessionListener<SocketChannel> getSession()
+	{
+		return session;
+	}
+
+	public void setSession( SessionListener<SocketChannel> session )
+	{
+		this.session = session;
+	}
+
+	private SessionListener<SocketChannel> session;
+
+	// /////////////
+	// TRANSPORT //
+	// /////////////
+
+	public Object transportQuery( Object query ) throws Exception
+	{
+		if (query == TcpConnection.LOCAL_ADDRESS)
+			return localAddress();
+
+		if (query instanceof WaitUp)
+		{
+			waitUp( ((WaitUp) query).maxDelay );
+			return null;
+		}
+
+		if (query instanceof WaitDown)
+		{
+			waitDown( ((WaitDown) query).maxDelay );
+			return null;
+		}
+
+		throw new UnsupportedOperationException( "unknown query: " + query );
+	}
+
+	public void transportControl( Object control, Object value )
+		throws Exception
+	{
+		if (control == START)
+		{
+			start();
+			return;
+		}
+
+		if (control == START_AND_WAIT_UP)
+		{
+			start();
+			waitUp( (Integer) value );
+			return;
+		}
+
+		if (control == STOP)
+		{
+			stop();
+			return;
+		}
+
+		if (control == STOP_AND_WAIT_DOWN)
+		{
+			stop();
+			waitDown( (Integer) value );
+			return;
+		}
+
+		throw new UnsupportedOperationException( "unknown control: " + control );
+	}
+
+	public void transportNotify( Object event ) throws Exception
+	{
+		// nothing to do.
+	}
+
+	// //////////////////
+	// IMPLEMENTATION //
+	// //////////////////
+
+	void start() throws Exception
+	{
+		synchronized (startedSync)
+		{
+			if (started)
+				throw new IllegalStateException( "started" );
+			
+			started = true;
+			restart();
+		}
+	}
+	
+	private void restart() throws Exception
+	{
+		// fireUp will save the handler.
+		try
+		{
+			selector.newAcceptHandler(
+				new InetSocketAddress( host, port ), backlog, this );
+		}
+		catch ( Error e )
+		{
+			// This is a hack work around for jdk_1.5.0_15, which has no
+			// translation for the error message and turns it into an
+			// Error.
+			
+			String msg = e.getMessage();
+			if (msg == null || !msg.equals( "Untranslated exception" ))
+				throw e;
+			
+			Throwable x = e.getCause();
+			if (x == null || !(x instanceof SocketException))
+				throw e;
+			
+			throw (SocketException) x;
+		}
+	}
+
+	private boolean started;
+	
+	private final Object startedSync = new Object();
+	
+	private MyAcceptHandler handler;
+	
+	private final Object handlerSync = new Object();
+
+	void stop() throws IOException
+	{
+		started = false;
+		
+		MyAcceptHandler h = setHandler( null );
+		if (h != null)
+		{
+			h.cancel();
+		}
+	}
+
+	private MyAcceptHandler setHandler( MyAcceptHandler newHandler )
+	{
+		synchronized (handlerSync)
+		{
+			if (newHandler == handler)
+				return null;
+			
+			if (newHandler != null && handler != null)
+				throw new IllegalStateException(
+					"newHandler != null && handler != null && newHandler != handler" );
+			
+			MyAcceptHandler oldHandler = handler;
+			handler = newHandler;
+			return oldHandler;
+		}
+	}
+
+	private void fireUp( MyAcceptHandler h )
+	{
+		setHandler( h );
+		status.set( Session.UP );
+		
+		TodoManager.addTodo( new Todo()
+		{
+			public void doit( TodoManager m ) throws Exception
+			{
+				session.sessionNotify( Session.UP );
+			}
+
+			public void exception( TodoManager m, Exception e )
+			{
+				e.printStackTrace();
+			}
+		} );
+	}
+
+	private void fireDown()
+	{
+		setHandler( null );
+		status.set( Session.DOWN );
+		
+		TodoManager.addTodo( new Todo()
+		{
+			public void doit( TodoManager m ) throws Exception
+			{
+				session.sessionNotify( Session.DOWN );
+			}
+
+			public void exception( TodoManager m, Exception e )
+			{
+				e.printStackTrace();
+			}
+		} );
+	}
+
+	void waitUp( int maxDelay ) throws Exception
+	{
+		status.waitUntilEq( Session.UP, maxDelay );
+	}
+
+	void waitDown( int maxDelay ) throws Exception
+	{
+		status.waitUntilEq( Session.DOWN, maxDelay );
+	}
+
+	private final Monitor<String> status = new Monitor<String>( "status",
+		Session.DOWN );
+
+	SocketAddress localAddress() throws IOException
+	{
+		return checkSocket().getLocalSocketAddress();
+	}
+
+	private ServerSocket checkSocket() throws IOException
+	{
+		ServerSocket s = checkChannel().socket();
+		if (s == null)
+			throw new IOException( "no socket" );
+		return s;
+	}
+
+	private ServerSocketChannel checkChannel() throws IOException
+	{
+		ServerSocketChannel c = checkHandler().channel();
+		if (c == null)
+			throw new IOException( "c == null" );
+		return c;
+	}
+
+	private AcceptHandler checkHandler() throws IOException
+	{
+		AcceptHandler h = handler;
+		if (h == null)
+			throw new IOException( "h == null" );
+		return h;
+	}
+
+	public AcceptHandler newAcceptHandler( ServerSocketChannel channel )
+		throws Exception
+	{
+		return new MyAcceptHandler( channel, null );
+	}
+	
+	/** */
+	public class MyAcceptHandler extends AcceptHandler
+	{
+		/**
+		 * @param channel
+		 * @param factory
+		 */
+		public MyAcceptHandler( ServerSocketChannel channel,
+			StreamHandlerFactory factory )
+		{
+			super( channel, factory );
+		}
+		
+		@Override
+		protected void registered()
+		{
+			super.registered();
+			fireUp( this );
+		}
+		
+		@Override
+		protected void acceptedChannel( SocketChannel sc ) throws Exception
+		{
+			session.sessionAccepted( sc );
+		}
+		
+		@Override
+		public void canceled( Exception e )
+		{
+			super.canceled( e );
+			fireDown();
+		}
+	}
+
+	boolean isStarted()
+	{
+		return started;
+	}
+
+	/**
+	 * @return the host interface to listen on.
+	 */
+	public String getHost()
+	{
+		return host;
+	}
+
+	/**
+	 * @return the port to listen on.
+	 */
+	public int getPort()
+	{
+		return port;
+	}
+
+	/**
+	 * @return the backlog (the number of unaccepted connections to allow).
+	 */
+	public int getBacklog()
+	{
+		return backlog;
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/xml/CircularStringBuf.java b/util/src/main/java/org/apache/etch/util/core/xml/CircularStringBuf.java
new file mode 100644
index 0000000..a483e75
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/xml/CircularStringBuf.java
@@ -0,0 +1,179 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.xml;
+
+import org.apache.etch.util.Assertion;
+
+/**
+ * A StringBuf implemented as a circular fixed-size list of characters.
+ */
+final public class CircularStringBuf implements StringBuf
+{
+	/**
+	 * Constructs the CircularStringBuf.
+	 * @param descr a description of this buffer
+	 *
+	 * @param maxLen the maximum number of characters to keep
+	 * in the buf.
+	 */
+	public CircularStringBuf( String descr, int maxLen )
+	{
+		this.descr = descr;
+		this.maxLen = maxLen;
+		chars = new char[maxLen];
+	}
+	
+	private final String descr;
+	
+	private final int maxLen;
+	
+	private final char[] chars;
+	
+	private int index;
+	
+	private int length;
+
+	public void append( char c )
+	{
+		fixupIndex();
+		
+		chars[index++] = c;
+		
+		if (length < maxLen)
+			length++;
+	}
+	
+	private void fixupIndex()
+	{
+		while (index >= maxLen)
+			index -= maxLen;
+	}
+
+	public void append( String s )
+	{
+		// if the length of s is larger than or equal to maxLen,
+		// then we only need consider the last maxLen characters
+		// and put them directly into the buffer. otherwise, we
+		// must deposit the characters in two segments:
+		// [index..maxLen) and [0..index).
+		
+		int n = s.length();
+		if (n == 0)
+			return;
+
+		// offset in s (if negative, then n < maxLen)
+		int i = n - maxLen;
+		if (i < 0)
+			i = 0;
+		
+		// how many characters from s we actually want.
+		n = n - i;
+		
+		Assertion.check( i >= 0 && i < s.length(), "i >= 0 && i < s.length()" );
+		Assertion.check( n > 0 && n <= maxLen, "n > 0 && n <= maxLen" );
+		Assertion.check( i+n == s.length(), "i+n == s.length()" );
+		
+		// here is an optimization: if we're getting maxLen chars
+		// from s, just get the chars directly into the buffer in
+		// one try and reset index and length.
+		
+		if (n == maxLen)
+		{
+			s.getChars( i, i+n, chars, 0 );
+			index = n;
+			length = n;
+			return;
+		}
+
+		Assertion.check( n < maxLen, "n < maxLen" );
+
+		fixupIndex();
+		
+		int seg1len = maxLen - index;
+		if (seg1len > n)
+			seg1len = n;
+		n -= seg1len;
+		
+		int seg2len = index;
+		if (seg2len > n)
+			seg2len = n;
+		n -= seg2len;
+		
+		Assertion.check( n == 0, "n == 0" );
+		Assertion.check( seg1len > 0, "seg1len > 0" );
+		Assertion.check( seg2len >= 0, "seg2len >= 0" );
+		Assertion.check( seg1len + seg2len < maxLen, "(seg1len + seg2len) < maxLen" );
+		
+		// handle segment 1:
+		
+		s.getChars( i, i+seg1len, chars, index );
+		i += seg1len;
+		index += seg1len;
+		length += seg1len;
+		
+		// handle segment 2:
+		
+		if (seg2len > 0)
+		{
+			s.getChars( i, i+seg2len, chars, 0 );
+			index = seg2len;
+			length += seg2len;
+		}
+		
+		if (length > maxLen)
+			length = maxLen;
+	}
+
+	public int length()
+	{
+		return length;
+	}
+
+	@Override
+	public String toString()
+	{
+		fixupIndex();
+		
+		if (index == length)
+		{
+			// chars are in one segment: [0..index)
+			return new String( chars, 0, index );
+		}
+		
+		// chars are in two segments: [index..maxLen) and [0..index)
+		
+		StringBuffer sb = new StringBuffer( maxLen );
+		sb.append( chars, index, maxLen - index );
+		sb.append( chars, 0, index );
+		return sb.toString();
+	}
+	
+	public void clear()
+	{
+		index = 0;
+		length = 0;
+	}
+
+	public String getDescr()
+	{
+		return descr;
+	}
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/xml/ParseException.java b/util/src/main/java/org/apache/etch/util/core/xml/ParseException.java
new file mode 100644
index 0000000..b4b279b
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/xml/ParseException.java
@@ -0,0 +1,88 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.xml;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.etch.util.core.xml.XmlParser.TagElement;
+
+
+
+/**
+ * Description of SyntaxException
+ */
+public class ParseException extends IOException
+{
+	private static final long serialVersionUID = -4649152474648809695L;
+
+	/**
+	 * @param msg
+	 */
+	public ParseException( String msg )
+	{
+		super( msg );
+	}
+	
+	/**
+	 * @param msg
+	 * @param cause
+	 */
+	public ParseException( String msg, Throwable cause )
+	{
+		super( msg );
+		initCause( cause );
+	}
+
+	/**
+	 * @return the context of the error
+	 */
+	public String getContext()
+	{
+		return context;
+	}
+	
+	/**
+	 * @param context
+	 */
+	public void setContext( String context )
+	{
+		this.context = context;
+	}
+
+	@Override
+	public String toString()
+	{
+		return super.toString()+" in '"+context+"' at "+tagElementStack;
+	}
+	
+	private String context;
+
+	/**
+	 * @param tagElementStack
+	 */
+	public void setTagElementStack( List<TagElement> tagElementStack )
+	{
+		this.tagElementStack = tagElementStack;
+	}
+	
+	private List<TagElement> tagElementStack;
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/xml/PlainStringBuf.java b/util/src/main/java/org/apache/etch/util/core/xml/PlainStringBuf.java
new file mode 100644
index 0000000..824625a
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/xml/PlainStringBuf.java
@@ -0,0 +1,87 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.xml;
+
+/**
+ * Description of PlainStringBuf.
+ */
+public class PlainStringBuf implements StringBuf
+{
+	/**
+	 * Constructs the PlainStringBuf.
+	 *
+	 * @param descr
+	 * @param maxLen
+	 */
+	public PlainStringBuf( String descr, int maxLen )
+	{
+		this.descr = descr;
+		this.maxLen = maxLen;
+	}
+	
+	private final String descr;
+	
+	private final int maxLen;
+
+	/**
+	 * @return the descr of this string buf.
+	 */
+	public String getDescr()
+	{
+		return descr;
+	}
+
+	public void append( char c )
+	{
+		if (sb.length() >= maxLen)
+			throw new UnsupportedOperationException(
+				"maximum length of "+descr+" exceeded: "+maxLen );
+
+		sb.append( c );
+	}
+
+	public void append( String s )
+	{
+		// this must process a character at a time so that subclassers
+		// will work properly.
+		int n = s.length();
+		for (int i = 0; i < n; i++)
+			append( s.charAt( i )  );
+	}
+
+	public int length()
+	{
+		return sb.length();
+	}
+
+	@Override
+	public String toString()
+	{
+		return sb.toString();
+	}
+	
+	public void clear()
+	{
+		sb.setLength( 0 );
+	}
+	
+	private final StringBuffer sb = new StringBuffer();
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/xml/StringBuf.java b/util/src/main/java/org/apache/etch/util/core/xml/StringBuf.java
new file mode 100644
index 0000000..18f6442
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/xml/StringBuf.java
@@ -0,0 +1,59 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.xml;
+
+/**
+ * A simple interface to a string buffer.
+ */
+public interface StringBuf
+{
+	/**
+	 * Append a character to the string buffer.
+	 * @param c the character to append.
+	 */
+	public void append( char c );
+	
+	/**
+	 * Append a string to the string buffer.
+	 * @param s the string of chars to append.
+	 */
+	public void append( String s );
+
+	/**
+	 * @return the number of characters in the string buffer.
+	 */
+	public int length();
+
+	/**
+	 * @return the current contents as a string.
+	 */
+	public String toString();
+
+	/**
+	 * Reset the string buffer to having no content.
+	 */
+	public void clear();
+
+	/**
+	 * @return a description of the string buffer.
+	 */
+	public String getDescr();
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/xml/StringBufWithEscape.java b/util/src/main/java/org/apache/etch/util/core/xml/StringBufWithEscape.java
new file mode 100644
index 0000000..8bfd8eb
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/xml/StringBufWithEscape.java
@@ -0,0 +1,132 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.xml;
+
+import java.util.Map;
+
+/**
+ * Description of StringBufWithEscape.
+ */
+public class StringBufWithEscape extends PlainStringBuf
+{
+	/**
+	 * Constructs the StringBufWithEscape.
+	 *
+	 * @param descr
+	 * @param maxLen
+	 * @param maxEscapeLen
+	 * @param escapes
+	 */
+	public StringBufWithEscape( String descr, int maxLen,
+		int maxEscapeLen, Map<String,Character> escapes )
+	{
+		super( descr, maxLen );
+		this.maxEscapeLen = maxEscapeLen;
+		this.escapes = escapes;
+	}
+	
+	private final int maxEscapeLen;
+	
+	private final Map<String,Character> escapes;
+	
+	@Override
+	public void append( char c )
+	{
+		if (c == '&')
+		{
+			if (escapeBuffer != null)
+				throw new UnsupportedOperationException( "bad char '"+c+"' in escape" );
+			escapeBuffer = new PlainStringBuf( "escape", maxEscapeLen );
+		}
+		else if (escapeBuffer != null)
+		{
+			if (c == ';')
+			{
+				String s = escapeBuffer.toString();
+				escapeBuffer = null;
+				super.append( parseEscape( s ) );
+			}
+			else
+			{
+				escapeBuffer.append( c );
+			}
+		}
+		else
+		{
+			super.append( c );
+		}
+	}
+	
+	private char parseEscape( String s )
+	{
+		if (s.length() == 0)
+			throw new UnsupportedOperationException( "empty escape" );
+		
+		if (s.startsWith( "#" ))
+		{
+			try
+			{
+				int k = Integer.parseInt( s.substring( 1 ) );
+				
+				if (k < 0 || k > 65535)
+					throw new UnsupportedOperationException( "numeric escape out of range '"+s+"'" );
+				
+				return (char) k;
+			}
+			catch ( NumberFormatException e )
+			{
+				throw new UnsupportedOperationException( "bad numeric escape '"+s+"'" );
+			}
+		}
+		
+		Character c = escapes.get( s );
+		if (c != null)
+			return c.charValue();
+		
+		c = escapes.get( s.toLowerCase() );
+		if (c != null)
+			return c.charValue();
+		
+		throw new UnsupportedOperationException( "unknown entity escape '"+s+"'" );
+	}
+	
+	@Override
+	public int length()
+	{
+		int n = super.length();
+		
+		if (escapeBuffer != null)
+			return n+1;
+		
+		return n;
+	}
+
+	@Override
+	public String toString()
+	{
+		if (escapeBuffer != null)
+			throw new UnsupportedOperationException( "unfinished escape" );
+		
+		return super.toString();
+	}
+
+	private PlainStringBuf escapeBuffer;
+}
diff --git a/util/src/main/java/org/apache/etch/util/core/xml/XmlParser.java b/util/src/main/java/org/apache/etch/util/core/xml/XmlParser.java
new file mode 100644
index 0000000..b66d613
--- /dev/null
+++ b/util/src/main/java/org/apache/etch/util/core/xml/XmlParser.java
@@ -0,0 +1,2181 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.xml;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Stack;
+import java.util.StringTokenizer;
+
+import org.apache.etch.util.Assertion;
+import org.apache.etch.util.EmptyIterator;
+import org.apache.etch.util.SingleIterator;
+import org.apache.etch.util.StringUtil;
+
+
+
+/**
+ * Description of XmlParser.
+ */
+public class XmlParser
+{
+	/**
+	 * Constructs the xml parser.
+	 */
+	public XmlParser()
+	{
+		// nothing to do yet.
+	}
+	
+	/**
+	 * Line separator for XML files.
+	 */
+	public final static String CRLF = "\r\n";
+	
+	/**
+	 * @param file
+	 * @param qualifier
+	 * @param name
+	 * @return the top tag element
+	 * @throws IOException if there is a problem reading the file
+	 * or if the top tag element isn't as specified
+	 */
+	public TagElement parseOne( File file, String qualifier, String name )
+		throws IOException
+	{
+		Reader rdr = new BufferedReader( new FileReader( file ) );
+		try
+		{
+			return parseOne( rdr, qualifier, name );
+		}
+		finally
+		{
+			rdr.close();
+		}
+	}
+	
+	/**
+	 * @param is
+	 * @param qualifier
+	 * @param name
+	 * @return the tag element found by parsing the specified input stream
+	 * to the very end.
+	 * @throws ParseException
+	 * @throws IOException
+	 */
+	public TagElement parseOne( InputStream is, String qualifier, String name )
+		throws ParseException, IOException
+	{
+		return parseOne( new InputStreamReader( is ), qualifier, name );
+	}
+
+	/**
+	 * @param rdr
+	 * @param qualifier
+	 * @param name
+	 * @return the tag element found by parsing the specified reader
+	 * to the very end.
+	 * @throws IOException
+	 * @throws ParseException
+	 */
+	public TagElement parseOne( Reader rdr, String qualifier, String name )
+		throws ParseException, IOException
+	{
+		while (parse( rdr.read() ))
+		{
+			// nothing to do.
+		}
+		
+		TagElement te = finish();
+		
+		if (name != null && te != null && !te.matches( qualifier, name ))
+			throw new IOException(
+				"top tag "+te.getQName()+" does not match "+
+					new QName( qualifier, name ) );
+		
+		return te;
+	}
+	
+	/**
+	 * @param s
+	 * @return false if parsing is finished, true otherwise.
+	 * @throws ParseException
+	 */
+	public TagElement parseOne( String s ) throws ParseException
+	{
+		clear();
+		
+		if (parse( s ))
+			return finish();
+		
+		return null;
+	}
+	/**
+	 * @param s
+	 * @return false if parsing is finished, true otherwise.
+	 * @throws ParseException
+	 */
+	public boolean parse( String s ) throws ParseException
+	{
+		int n = s.length();
+		for (int i = 0; i < n; i++)
+			if (!parse( s.charAt( i ) ))
+				return false;
+		return true;
+	}
+	
+	/**
+	 * @return TagElement if the parse worked.
+	 * @throws ParseException
+	 */
+	public TagElement finish() throws ParseException
+	{
+		if (parse( -1 ))
+			return null;
+		
+		return rootTagElement;
+	}
+	
+	/**
+	 * @param c the next character to parse, or -1 to indicate
+	 * there are no more characters.
+	 * @return false if parsing is finished, true otherwise.
+	 * @throws ParseException
+	 */
+	public boolean parse( int c ) throws ParseException
+	{
+		try
+		{
+			if (c >= 0)
+				context.append( (char) c );
+			return parse0( c );
+		}
+		catch ( ParseException e )
+		{
+			e.setContext( context.toString() );
+			e.setTagElementStack( getTagElements() );
+			throw e;
+		}
+		catch ( RuntimeException e )
+		{
+			ParseException pe = new ParseException( "caught exception", e );
+			pe.setContext( context.toString() );
+			pe.setTagElementStack( getTagElements() );
+			throw e;
+		}
+	}
+	
+	private StringBuf context = new CircularStringBuf( null, 100 );
+	
+	private boolean parse0( int c ) throws ParseException
+	{
+		if (state < 0 || state >= NSTATES)
+			throw new IllegalStateException( "the parser is in an illegal state: "+state );
+		
+		int cc = getCharClass( c );
+		int stateAction = transitions[state][cc];
+		int newState = stateAction & STATE_MASK;
+		int action = stateAction >>> ACTION_SHIFT & ACTION_MASK;
+		switch (action)
+		{
+			case A_ERROR:
+			{
+				int s = state;
+				state = -1;
+				
+				if (c == -1)
+					throw new ParseException( "unexpected EOF while "+
+						describeState( s )+
+						": expected one of "+expectedChars( s ) );
+				
+				throw new ParseException( "unexpected character "+
+					describeChar( c )+" while "+describeState( s )+
+					": expected one of "+expectedChars( s ) );
+			}
+			
+			case A_IGNORE:
+				break;
+			
+			case A_STOP:
+				finishCdata();
+				return false;
+			
+			case A_ADD_CHAR_TO_CDATA:
+				addToCdata( c );
+				break;
+			
+			case A_ADD_LT_CHAR_TO_CDATA:
+				addToCdata( '<' );
+				addToCdata( c );
+				break;
+			
+			case A_ADD_LT_SLASH_CHAR_TO_CDATA:
+				addToCdata( '<' );
+				addToCdata( '/' );
+				addToCdata( c );
+				break;
+			
+			case A_ADD_LT_BANG_CHAR_TO_CDATA:
+				addToCdata( '<' );
+				addToCdata( '!' );
+				addToCdata( c );
+				break;
+			
+			case A_ADD_LT_QUESTION_CHAR_TO_CDATA:
+				addToCdata( '<' );
+				addToCdata( '?' );
+				addToCdata( c );
+				break;
+			
+			case A_ADD_CHAR_TO_TAG_NAME:
+				finishCdata();
+				addToTagName( (char) c );
+				break;
+			
+			case A_SET_TAG_NAME_QUALIFIER:
+				setTagNameQualifier();
+				break;
+			
+			case A_START_TAG:
+				startTag();
+				break;
+			
+			case A_EMPTY_TAG:
+				emptyTag();
+				break;
+			
+			case A_END_TAG:
+				endTag();
+				break;
+			
+			case A_ADD_CHAR_TO_ATTR_NAME:
+				addToAttrName( (char) c );
+				break;
+			
+			case A_SET_ATTR_NAME_QUALIFIER:
+				setAttrNameQualifier();
+				break;
+			
+			case A_ADD_TO_ATTR_VALUE:
+				addToAttrValue( (char) c );
+				break;
+			
+			case A_FINISH_ATTR:
+				finishAttr();
+				break;
+
+			default:
+				throw new UnsupportedOperationException( "unknown action "+action );
+		}
+		state = newState;
+		return true;
+	}
+
+	private int state = 0;
+
+	////////////////////
+	// ACTION METHODS //
+	////////////////////
+
+	private static final int MAX_CDATA_LEN = 1024*1024;
+
+	private static final int MAX_TAG_NAME_LEN = 255;
+
+	private static final int MAX_ATTR_NAME_LEN = 255;
+
+	private static final int MAX_ATTR_VALUE_LEN = 10*1024;
+
+	private static final int MAX_ESCAPE_LEN = 31;
+	
+	private void addToCdata( int c )
+	{
+		if (c >= 0)
+			cdataBuf.append( (char) c );
+	}
+
+	private final PlainStringBuf cdataBuf =
+		new StringBufWithEscape( "cdata", MAX_CDATA_LEN,
+			MAX_ESCAPE_LEN, escapes );
+	
+	private void finishCdata() throws ParseException
+	{
+		String cdata = finishStringBuf( cdataBuf, true );
+		if (cdata.length() > 0)
+			deliverCdata( cdata );
+	}
+
+	private void addToTagName( char c )
+	{
+		tagNameBuf.append( c );
+	}
+	
+	private final StringBuf tagNameBuf =
+		new PlainStringBuf( "tag name", MAX_TAG_NAME_LEN );
+
+	private void setTagNameQualifier() throws ParseException
+	{
+		tagNameQualifier = finishStringBuf( tagNameBuf, false );
+	}
+	
+	private String tagNameQualifier;
+
+	private void emptyTag() throws ParseException
+	{
+		String tagName = finishStringBuf( tagNameBuf, false );
+		deliverStartTag( tagNameQualifier, tagName, true );
+		tagNameQualifier = null;
+	}
+
+	private void startTag() throws ParseException
+	{
+		String tagName = finishStringBuf( tagNameBuf, false );
+		deliverStartTag( tagNameQualifier, tagName, false );
+		tagNameQualifier = null;
+	}
+
+	private void endTag() throws ParseException
+	{
+		String tagName = finishStringBuf( tagNameBuf, false );
+		deliverEndTag( tagNameQualifier, tagName );
+		tagNameQualifier = null;
+	}
+
+	private void addToAttrName( char c )
+	{
+		attrNameBuf.append( c );
+	}
+	
+	private final PlainStringBuf attrNameBuf =
+		new PlainStringBuf( "attr name", MAX_ATTR_NAME_LEN );
+
+	private void setAttrNameQualifier() throws ParseException
+	{
+		attrNameQualifier = finishStringBuf( attrNameBuf, false );
+	}
+	
+	private String attrNameQualifier;
+
+	private void addToAttrValue( char c )
+	{
+		attrValueBuf.append( c );
+	}
+	
+	private final PlainStringBuf attrValueBuf =
+		new StringBufWithEscape( "attr value", MAX_ATTR_VALUE_LEN,
+			MAX_ESCAPE_LEN, escapes );
+
+	private void finishAttr() throws ParseException
+	{
+		String attrName = finishStringBuf( attrNameBuf, false );
+		String attrValue = finishStringBuf( attrValueBuf, true );
+		deliverAttr( attrNameQualifier, attrName, attrValue );
+		attrNameQualifier = null;
+	}
+	
+	/**
+	 * Clears the state of the xml parser.
+	 */
+	public void clear()
+	{
+		attrNameBuf.clear();
+		attrNameQualifier = null;
+		attrValueBuf.clear();
+		cdataBuf.clear();
+		context.clear();
+		state = 0;
+		tagAttrs = null;
+		clearTagElements();
+		tagNameBuf.clear();
+		tagNameQualifier = null;
+	}
+
+	//////////////////////
+	// DELIVERY METHODS //
+	//////////////////////
+
+	/**
+	 * Delivers the characters between tags if any.
+	 * 
+	 * @param cdata (escape sequences have been expanded).
+	 * @throws ParseException
+	 */
+	protected void deliverCdata( String cdata )
+		throws ParseException
+	{
+		TagElement top = peekTagElement();
+		
+		if (top != null)
+			top.addCdata( cdata );
+		else
+			addRootCdata( cdata );
+	}
+
+	/**
+	 * Delivers an open tag.
+	 * 
+	 * @param qualifier any qualifier prepended to the name.
+	 * 
+	 * @param name the tag name (minus any qualifier).
+	 * 
+	 * @param empty true if the tag was opened and closed all in one step.
+	 */
+	protected void deliverStartTag( String qualifier, String name, boolean empty )
+	{
+		TagElement top = peekTagElement();
+
+		QName qName = new QName( qualifier, name );
+		
+		TagElement tagElement;
+		if (top != null)
+			tagElement = top.addTag( qName, tagAttrs );
+		else
+			rootTagElement = tagElement = addRootTag( qName, tagAttrs );
+		tagAttrs = null;
+		
+		if (empty)
+			tagElement.finish();
+		else
+			pushTagElement( tagElement );
+	}
+
+	/**
+	 * Delivers a close tag. A close tag will not be delivered for a
+	 * tag which was opened and closed all in one step.
+	 * 
+	 * @param qualifier any qualifier prepended to the name.
+	 * 
+	 * @param name the tag name (minus any qualifier).
+	 * @throws ParseException
+	 */
+	protected void deliverEndTag( String qualifier, String name )
+		throws ParseException
+	{
+		TagElement top = peekTagElement();
+		if (top == null)
+			throw new ParseException( "end tag with empty stack: "+
+				QName.toString( qualifier, name ) );
+		
+		if (!top.matches( qualifier, name ))
+			throw new ParseException( "end tag "+
+				QName.toString( qualifier, name )+
+				" does not match current top of stack" );
+		
+		popTagElement().finish();
+	}
+
+	/**
+	 * Delivers an attribute of a tag which is being parsed. The tag
+	 * will be delivered with deliverOpenTag when it is done, after
+	 * any and all attributes have been delivered.
+	 * 
+	 * @param qualifier any qualifier prepended to the name.
+	 * 
+	 * @param name the attribute name (minus any qualifier).
+	 * 
+	 * @param value the attribute value (escape sequences have been expanded).
+	 */
+	protected void deliverAttr( String qualifier, String name, String value )
+	{
+		if (tagAttrs == null)
+			tagAttrs = new HashMap<QName, String>();
+		
+		QName qName = new QName( qualifier, name );
+		tagAttrs.put( qName, value );
+	}
+
+	///////////////////////
+	// TAG ELEMENT STACK //
+	///////////////////////
+	
+	private TagElement peekTagElement()
+	{
+		if (tagElementStack.isEmpty())
+			return null;
+		
+		return tagElementStack.peek();
+	}
+	
+	/**
+	 * @param tagElement
+	 */
+	protected void pushTagElement( TagElement tagElement )
+	{
+		tagElementStack.push( tagElement );
+	}
+	
+	private TagElement popTagElement()
+	{
+		return tagElementStack.pop();
+	}
+	
+	private void clearTagElements()
+	{
+		tagElementStack.clear();
+		rootTagElement = null;
+	}
+	
+	/**
+	 * Dumps the tag stack of the xml parser.
+	 */
+	public void dump()
+	{
+		System.out.println( "tag stack: "+tagElementStack );
+		System.out.flush();
+	}
+	
+	/**
+	 * @return a list of the current tag element stack.
+	 */
+	public List<TagElement> getTagElements()
+	{
+		return new ArrayList<TagElement>( tagElementStack );
+	}
+	
+	private Stack<TagElement> tagElementStack = new Stack<TagElement>();
+	
+	private Map<QName, String> tagAttrs;
+	
+	private TagElement rootTagElement;
+
+	/////////////////////////////
+	// SUBCLASS RESPONSIBILITY //
+	/////////////////////////////
+	
+	/**
+	 * @param cdata
+	 * @throws ParseException
+	 */
+	public void addRootCdata( String cdata ) throws ParseException
+	{
+		if (cdata.trim().length() > 0)
+			throw new ParseException( "cannot add root cdata" );
+	}
+	
+	/**
+	 * @param qName
+	 * @param attrs
+	 * @return a new tag element suitable to be a root tag element.
+	 */
+	public TagElement addRootTag( QName qName, Map<QName, String> attrs )
+	{
+		return new RootTagElement( qName, attrs );
+	}
+
+	//////////////////////////
+	// misc support methods //
+	//////////////////////////
+	
+	private final static Map<String,Character> escapes = new HashMap<String,Character>();
+	static
+	{
+		escapes.put( "amp", new Character( '&' ) );
+		escapes.put( "apos", new Character( '\'' ) );
+		escapes.put( "gt", new Character( '>' ) );
+		escapes.put( "lt", new Character( '<' ) );
+		escapes.put( "quot", new Character( '"' ) );
+	}
+
+	private static String finishStringBuf( StringBuf sb,
+		boolean emptyOk ) throws ParseException
+	{
+		if (sb.length() == 0)
+		{
+			if (!emptyOk)
+				throw new ParseException( "empty '"+sb.getDescr()+"' not allowed" );
+			
+			return "";
+		}
+		
+		String s = sb.toString();
+		sb.clear();
+		return s;
+	}
+	
+	private static String describeChar( int c )
+	{
+		if (c < 32 || c > 126)
+			return "&#"+c+';';
+		
+		if (c == '\'')
+			return "'\\''";
+		
+		if (c == '\\')
+			return "'\\\\'";
+		
+		return "'"+(char) c+'\'';
+	}
+
+	private static String expectedChars( int state )
+	{
+		StringBuffer sb = new StringBuffer();
+		for (int i = 0; i < NCC; i++)
+		{
+			if (transitions[state][i]>>>ACTION_SHIFT != A_ERROR)
+			{
+				if (sb.length() > 0)
+					sb.append( '|' );
+				sb.append( describeCharClass( i ) );
+			}
+		}
+		return sb.toString();
+	}
+	
+	private final static int STATE_MASK = 255;
+	
+	private final static int ACTION_SHIFT = 8;
+	
+	private final static int ACTION_MASK = 255;
+
+	///////////////////////
+	// CHARACTER CLASSES //
+	///////////////////////
+
+	private final static int CC_OTHER = 0;
+	private final static int CC_EOF = 1;
+	private final static int CC_X = 2;
+	private final static int CC_M = 3;
+	private final static int CC_L = 4;
+	private final static int CC_OTHR_LTR = 5;
+	private final static int CC_DIGIT = 6;
+	private final static int CC_WS = 7;
+	private final static int CC_SLASH = 8;
+	private final static int CC_BANG = 9;
+	private final static int CC_EQ = 10;
+	private final static int CC_SQ = 11;
+	private final static int CC_DQ = 12;
+	private final static int CC_DASH = 13;
+	private final static int CC_COLON = 14;
+	private final static int CC_LT = 15;
+	private final static int CC_GT = 16;
+	private final static int CC_DOT = 17;
+	private final static int CC_UNDERSCORE = 18;
+	private final static int CC_QUESTION = 19;
+	private final static int NCC = 20;
+	
+	private final static String[] ccDescr = new String[NCC];
+	
+	private final static int NCHARS = 128;
+	private final static byte[] ccs = new byte[NCHARS];
+	static
+	{
+		addChar( CC_EOF, "EOF" );
+		addChar( CC_OTHER, "all others" );
+
+		addChar( CC_OTHR_LTR, 'a', 'k', "a-k" );
+		addChar( CC_L, 'l', "l" );
+		addChar( CC_M, 'm', "m" );
+		addChar( CC_OTHR_LTR, 'n', 'w', "n-w" );
+		addChar( CC_X, 'x', "x" );
+		addChar( CC_OTHR_LTR, 'y', 'z', "y-z" );
+
+		addChar( CC_OTHR_LTR, 'A', 'K', "A-K" );
+		addChar( CC_L, 'L', "L" );
+		addChar( CC_M, 'M', "M" );
+		addChar( CC_OTHR_LTR, 'N', 'W', "N-W" );
+		addChar( CC_X, 'X', "X" );
+		addChar( CC_OTHR_LTR, 'Y', 'Z', "Y-Z" );
+		
+		addChar( CC_DIGIT, '0', '9', "0-9" );
+		
+		addChar( CC_WS, ' ', "SP" );
+		addChar( CC_WS, '\t', "TAB" );
+		addChar( CC_WS, '\r', "CR" );
+		addChar( CC_WS, '\n', "LF" );
+		
+		addChar( CC_SLASH, '/', "/" );
+		addChar( CC_BANG, '!', "!" );
+		addChar( CC_EQ, '=', "=" );
+		addChar( CC_SQ, '\'', "'" );
+		addChar( CC_DQ, '"', "\"" );
+		addChar( CC_DASH, '-', "-" );
+		addChar( CC_COLON, ':', ":" );
+		addChar( CC_LT, '<', "<" );
+		addChar( CC_GT, '>', ">" );
+		addChar( CC_DOT, '.', "." );
+		addChar( CC_UNDERSCORE, '_', "_" );
+		addChar( CC_QUESTION, '?', "?" );
+	}
+	
+	private static int getCharClass( int c )
+	{
+		if (c < 0) return CC_EOF;
+		if (c >= NCHARS) return CC_OTHER;
+		return ccs[c];
+	}
+
+	private static void addChar( int cc, String descr )
+	{
+		addCCDescr( cc, descr );
+	}
+
+	private static void addChar( int cc, char c, String descr )
+	{
+		Assertion.check( ccs[c] == CC_OTHER, "ccs[c] == CC_OTHER" );
+		ccs[c] = (byte) cc;
+		addCCDescr( cc, descr );
+	}
+
+	private static void addChar( int cc, char start, char end, String descr )
+	{
+		while (start <= end)
+		{
+			Assertion.check( ccs[start] == CC_OTHER, "ccs[start] == CC_OTHER" );
+			ccs[start++] = (byte) cc;
+		}
+		addCCDescr( cc, descr );
+	}
+
+	private static void addCCDescr( int cc, String descr )
+	{
+		String s = ccDescr[cc];
+		if (s != null)
+			ccDescr[cc] = s+'|'+descr;
+		else
+			ccDescr[cc] = descr;
+	}
+
+	private static String describeCharClass( int cc )
+	{
+		return ccDescr[cc];
+	}
+
+	/////////////
+	// ACTIONS //
+	/////////////
+	
+	private final static int A_ERROR = 0;
+	private final static int A_IGNORE = 1;
+	private final static int A_STOP = 2;
+	private final static int A_ADD_CHAR_TO_CDATA = 3;
+	private final static int A_ADD_LT_CHAR_TO_CDATA = 4;
+	private final static int A_ADD_LT_SLASH_CHAR_TO_CDATA = 5;
+	private final static int A_ADD_LT_BANG_CHAR_TO_CDATA = 15;
+	private final static int A_ADD_LT_QUESTION_CHAR_TO_CDATA = 16;
+	private final static int A_ADD_CHAR_TO_TAG_NAME = 6;
+	private final static int A_SET_TAG_NAME_QUALIFIER = 7;
+	private final static int A_START_TAG = 8;
+	private final static int A_EMPTY_TAG = 9;
+	private final static int A_END_TAG = 10;
+	private final static int A_ADD_CHAR_TO_ATTR_NAME = 11;
+	private final static int A_SET_ATTR_NAME_QUALIFIER = 12;
+	private final static int A_ADD_TO_ATTR_VALUE = 13;
+	private final static int A_FINISH_ATTR = 14;
+
+	////////////
+	// STATES //
+	////////////
+
+	private final static int S_CDATA = 0;
+	private final static int S_GOT_LT = 1;
+	private final static int S_GET_STAG_NM = 2;
+	private final static int S_SKNG_GT = 3;
+	private final static int S_SKNG_ATTR_NM = 4;
+	private final static int S_GET_ATTR_NM = 5;
+	private final static int S_SKNG_ATTR_VAL = 6;
+	private final static int S_GET_DQ_VALUE = 7;
+	private final static int S_GET_SQ_VALUE = 8;
+	private final static int S_GOT_LT_SLASH = 9;
+	private final static int S_GET_ETAG_NM = 10;
+	private final static int S_SKNG_WS_STAR_GT = 11;
+	private final static int S_GOT_LT_BANG = 12;
+	private final static int S_SKNG_DASH2 = 13;
+	private final static int S_GET_CMMNT = 14;
+	private final static int S_SKNG_DASH4 = 15;
+	private final static int S_SKNG_EQ = 16;
+	private final static int S_GOT_LT_QUESTION = 17;
+	private final static int S_GET_DIR_NM = 18;
+	private final static int S_1 = 19;
+	private final static int S_2 = 20;
+	private final static int NSTATES = 22;
+
+	private static String describeState( int state )
+	{
+		return stateDescr[state];
+	}
+	
+	private static String[] stateDescr = new String[NSTATES];
+
+	//////////////////////
+	// TRANSITION TABLE //
+	//////////////////////
+	
+	private final static short[][] transitions = new short[NSTATES][NCC];
+	static
+	{
+		addState( S_CDATA, "gathering CDATA, looking for tag start or EOF" );
+		addTransition( CC_LT, S_GOT_LT, A_IGNORE );
+		addTransition( CC_EOF, S_CDATA, A_STOP );
+		addBackstop( S_CDATA, A_ADD_CHAR_TO_CDATA );
+
+		// pending CDATA: LT
+		addState( S_GOT_LT, "looking for stag name, slash, bang, or question" );
+		addTransition( CC_X, S_GET_STAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_M, S_GET_STAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_L, S_GET_STAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_OTHR_LTR, S_GET_STAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_UNDERSCORE, S_GET_STAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_SLASH, S_GOT_LT_SLASH, A_IGNORE );
+		addTransition( CC_BANG, S_GOT_LT_BANG, A_IGNORE );
+		addTransition( CC_QUESTION, S_GOT_LT_QUESTION, A_IGNORE );
+		addBackstop( S_CDATA, A_ADD_LT_CHAR_TO_CDATA );
+
+		// pending CDATA: LT SLASH
+		addState( S_GOT_LT_SLASH, "looking for etag name" );
+		addTransition( CC_X, S_GET_ETAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_M, S_GET_ETAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_L, S_GET_ETAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_OTHR_LTR, S_GET_ETAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_UNDERSCORE, S_GET_ETAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addBackstop( S_CDATA, A_ADD_LT_SLASH_CHAR_TO_CDATA );
+
+		// pending CDATA: LT BANG
+		addState( S_GOT_LT_BANG, "looking for directive name or first dash of comment" );
+		addTransition( CC_X, S_GET_DIR_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_M, S_GET_DIR_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_L, S_GET_DIR_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_OTHR_LTR, S_GET_DIR_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_UNDERSCORE, S_GET_DIR_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_DASH, S_SKNG_DASH2, A_IGNORE );
+		addBackstop( S_CDATA, A_ADD_LT_BANG_CHAR_TO_CDATA );
+		
+		// pending CDATA: LT QUESTION
+		addState( S_GOT_LT_QUESTION, "looking for processing instruction" );
+		addTransition( CC_X, S_1, A_IGNORE );
+		addTransition( CC_M, S_1, A_IGNORE );
+		addTransition( CC_L, S_1, A_IGNORE );
+		addTransition( CC_OTHR_LTR, S_1, A_IGNORE );
+		addTransition( CC_UNDERSCORE, S_1, A_IGNORE );
+		addBackstop( S_CDATA, A_ADD_LT_QUESTION_CHAR_TO_CDATA );
+		
+		addState( S_1, "gather processing instruction" );
+		addTransition( CC_QUESTION, S_2, A_IGNORE );
+		addBackstop( S_1, A_IGNORE );
+		
+		addState( S_2, "ending processing instruction" );
+		addTransition( CC_GT, S_CDATA, A_IGNORE );
+		addTransition( CC_QUESTION, S_2, A_IGNORE );
+		addBackstop( S_1, A_IGNORE );
+		
+		addState( S_GET_STAG_NM, "gathering stag name" );
+		addTransition( CC_X, S_GET_STAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_M, S_GET_STAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_L, S_GET_STAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_OTHR_LTR, S_GET_STAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_UNDERSCORE, S_GET_STAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_DIGIT, S_GET_STAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_DASH, S_GET_STAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_DOT, S_GET_STAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_COLON, S_GET_STAG_NM, A_SET_TAG_NAME_QUALIFIER );
+		addTransition( CC_WS, S_SKNG_ATTR_NM, A_IGNORE );
+		addTransition( CC_SLASH, S_SKNG_GT, A_IGNORE );
+		addTransition( CC_GT, S_CDATA, A_START_TAG );
+
+		addState( S_SKNG_GT, "looking for GT to close empty tag" );
+		addTransition( CC_GT, S_CDATA, A_EMPTY_TAG );
+
+		addState( S_SKNG_ATTR_NM, "looking for attribute name, or tag close or tag end" );
+		addTransition( CC_X, S_GET_ATTR_NM, A_ADD_CHAR_TO_ATTR_NAME );
+		addTransition( CC_M, S_GET_ATTR_NM, A_ADD_CHAR_TO_ATTR_NAME );
+		addTransition( CC_L, S_GET_ATTR_NM, A_ADD_CHAR_TO_ATTR_NAME );
+		addTransition( CC_OTHR_LTR, S_GET_ATTR_NM, A_ADD_CHAR_TO_ATTR_NAME );
+		addTransition( CC_UNDERSCORE, S_GET_ATTR_NM, A_ADD_CHAR_TO_ATTR_NAME );
+		addTransition( CC_WS, S_SKNG_ATTR_NM, A_IGNORE );
+		addTransition( CC_SLASH, S_SKNG_GT, A_IGNORE );
+		addTransition( CC_GT, S_CDATA, A_START_TAG );
+
+		addState( S_GET_ATTR_NM, "collect attribute name" );
+		addTransition( CC_X, S_GET_ATTR_NM, A_ADD_CHAR_TO_ATTR_NAME );
+		addTransition( CC_M, S_GET_ATTR_NM, A_ADD_CHAR_TO_ATTR_NAME );
+		addTransition( CC_L, S_GET_ATTR_NM, A_ADD_CHAR_TO_ATTR_NAME );
+		addTransition( CC_OTHR_LTR, S_GET_ATTR_NM, A_ADD_CHAR_TO_ATTR_NAME );
+		addTransition( CC_UNDERSCORE, S_GET_ATTR_NM, A_ADD_CHAR_TO_ATTR_NAME );
+		addTransition( CC_DIGIT, S_GET_ATTR_NM, A_ADD_CHAR_TO_ATTR_NAME );
+		addTransition( CC_DASH, S_GET_ATTR_NM, A_ADD_CHAR_TO_ATTR_NAME );
+		addTransition( CC_DOT, S_GET_ATTR_NM, A_ADD_CHAR_TO_ATTR_NAME );
+		addTransition( CC_COLON, S_GET_ATTR_NM, A_SET_ATTR_NAME_QUALIFIER );
+		addTransition( CC_WS, S_SKNG_EQ, A_IGNORE );
+		addTransition( CC_EQ, S_SKNG_ATTR_VAL, A_IGNORE );
+
+		addState( S_SKNG_EQ, "seeking the EQ of an attribute spec" );
+		addTransition( CC_WS, S_SKNG_EQ, A_IGNORE );
+		addTransition( CC_EQ, S_SKNG_ATTR_VAL, A_IGNORE );
+		
+		addState( S_SKNG_ATTR_VAL, "looking for attribute value" );
+		addTransition( CC_WS, S_SKNG_ATTR_VAL, A_IGNORE );
+		addTransition( CC_SQ, S_GET_SQ_VALUE, A_IGNORE );
+		addTransition( CC_DQ, S_GET_DQ_VALUE, A_IGNORE );
+
+		addState( S_GET_DQ_VALUE, "collecting DQ attribute value" );
+		addTransition( CC_DQ, S_SKNG_ATTR_NM, A_FINISH_ATTR );
+		addBackstop( S_GET_DQ_VALUE, A_ADD_TO_ATTR_VALUE );
+
+		addState( S_GET_SQ_VALUE, "collecting SQ attribute value" );
+		addTransition( CC_SQ, S_SKNG_ATTR_NM, A_FINISH_ATTR );
+		addBackstop( S_GET_SQ_VALUE, A_ADD_TO_ATTR_VALUE );
+
+		addState( S_GET_ETAG_NM, "collecting etag name" );
+		addTransition( CC_X, S_GET_ETAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_M, S_GET_ETAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_L, S_GET_ETAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_OTHR_LTR, S_GET_ETAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_UNDERSCORE, S_GET_ETAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_DIGIT, S_GET_ETAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_DASH, S_GET_ETAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_DOT, S_GET_ETAG_NM, A_ADD_CHAR_TO_TAG_NAME );
+		addTransition( CC_COLON, S_GET_ETAG_NM, A_SET_TAG_NAME_QUALIFIER );
+		addTransition( CC_WS, S_SKNG_WS_STAR_GT, A_IGNORE );
+		addTransition( CC_GT, S_CDATA, A_END_TAG );
+
+		addState( S_SKNG_WS_STAR_GT, "looking for end of closing tag" );
+		addTransition( CC_WS, S_SKNG_WS_STAR_GT, A_IGNORE );
+		addTransition( CC_GT, S_CDATA, A_END_TAG );
+		
+		addState( S_SKNG_DASH2, "looking for second dash of comment" );
+		addTransition( CC_DASH, S_GET_CMMNT, A_IGNORE );
+
+		addState( S_GET_CMMNT, "collecting comment" );
+		addTransition( CC_DASH, S_SKNG_DASH4, A_IGNORE );
+		addBackstop( S_GET_CMMNT, A_IGNORE );
+
+		addState( S_SKNG_DASH4, "looking for second dash of comment end" );
+		addTransition( CC_DASH, S_GOT_LT_BANG, A_IGNORE );
+		addBackstop( S_GET_CMMNT, A_IGNORE );
+	}
+	
+	private static void addState( int state, String descr )
+	{
+		Assertion.check( stateDescr[state] == null, "states[state] == null" );
+		staticNextState = state;
+		stateDescr[state] = descr;
+	}
+	
+	private static int staticNextState = -1;
+	
+	private static void addTransition( int cc, int newState, int action )
+	{
+		Assertion.check( transitions[staticNextState][cc] == 0, "stateActions[staticNextState][cc] == 0" );
+		Assertion.check( (newState & ~STATE_MASK) == 0, "(newState & ~STATE_MASK) == 0" );
+		Assertion.check( (action & ~ACTION_MASK) == 0, "(action & ~ACTION_MASK) == 0" );
+		int sa = newState | action << ACTION_SHIFT;
+		transitions[staticNextState][cc] = (short) sa;
+	}
+	
+	private static void addBackstop( int newState, int action )
+	{
+		Assertion.check( (newState & ~STATE_MASK) == 0, "(newState & ~STATE_MASK) == 0" );
+		Assertion.check( (action & ~ACTION_MASK) == 0, "(action & ~ACTION_MASK) == 0" );
+		int sa = newState | action << ACTION_SHIFT;
+		for (int i = 0; i < NCC; i++)
+		{
+			if (i == CC_EOF)
+				continue;
+			
+			if (transitions[staticNextState][i] == 0)
+				transitions[staticNextState][i] = (short) sa;
+		}
+	}
+	
+	/**
+	 * Description of Element
+	 */
+	public interface Element
+	{
+		/**
+		 * @return the element dumped in appropriate format.
+		 */
+		public String toString();
+		
+		/**
+		 * @param newlineBetweenTags
+		 * @param collapseEmptyTags
+		 * @return the element dumped in appropriate format.
+		 */
+		public String toString( boolean newlineBetweenTags,
+			boolean collapseEmptyTags );
+		
+		/**
+		 * the element dumped in appropriate format to the string buffer.
+		 * @param wtr
+		 * @throws IOException
+		 */
+		public void toString( Writer wtr ) throws IOException;
+		
+		/**
+		 * the element dumped in appropriate format to the string buffer.
+		 * @param wtr
+		 * @param newlineBetweenTags
+		 * @param collapseEmptyTags if true allows <foo></foo> to be
+		 * collapsed into <foo/>
+		 * @throws IOException
+		 */
+		public void toString( Writer wtr, boolean newlineBetweenTags,
+			boolean collapseEmptyTags ) throws IOException;
+	}
+	
+	/**
+	 * Description of AbstractElement.
+	 */
+	abstract public static class AbstractElement implements Element
+	{
+		@Override
+		final public String toString()
+		{
+			try
+			{
+				StringWriter sw = new StringWriter();
+				toString( sw );
+				return sw.toString();
+			}
+			catch ( IOException e )
+			{
+				throw new RuntimeException( "caught exception", e );
+			}
+		}
+		
+		final public String toString( boolean newlineBetweenTags, boolean collapseEmptyTags )
+		{
+			try
+			{
+				StringWriter sw = new StringWriter();
+				toString( sw, newlineBetweenTags, collapseEmptyTags );
+				return sw.toString();
+			}
+			catch ( IOException e )
+			{
+				throw new RuntimeException( "caught exception", e );
+			}
+		}
+
+		final public void toString( Writer wtr ) throws IOException
+		{
+			toString( wtr, true, false );
+		}
+	}
+	
+	/**
+	 * Description of CdataElement.
+	 */
+	public interface CdataElement extends Element
+	{
+		/**
+		 * @return the cdata of this element.
+		 */
+		public String getCdata();
+	}
+	
+	/**
+	 * Description of DefaultCdataElement.
+	 */
+	public static class DefaultCdataElement extends AbstractElement
+		implements CdataElement
+	{
+		/**
+		 * Constructs the DefaultCdataElement.
+		 *
+		 * @param cdata
+		 */
+		public DefaultCdataElement( String cdata )
+		{
+			this.cdata = cdata;
+		}
+		
+		public String getCdata()
+		{
+			return cdata;
+		}
+		
+		private final String cdata;
+		
+		public void toString( Writer wtr, boolean newlineBetweenTags,
+			boolean collapseEmptyTags ) throws IOException
+		{
+			ProtectCData.write( wtr, cdata );
+		}
+	}
+	
+	/**
+	 * Description of TagElement.
+	 */
+	public interface TagElement extends Element, Iterable<Element>
+	{
+		/**
+		 * @return the qualified name of this tag element.
+		 */
+		public QName getQName();
+		
+		/**
+		 * @param qualifier
+		 * @param name
+		 * @return true if this tag element matches qualifier and name.
+		 */
+		public boolean matches( String qualifier, String name );
+
+		/**
+		 * @param qName
+		 * @return true if the specified qName matches this tag element.
+		 */
+		public boolean matches( QName qName );
+
+		/**
+		 * @param cdata adds some cdata to this tag element.
+		 */
+		public void addCdata( String cdata );
+
+		/**
+		 * @param childQName
+		 * @param childAttrs
+		 * @return a new tag element suitable to be a child of this element.
+		 */
+		public TagElement addTag( QName childQName, Map<QName, String> childAttrs );
+
+		/**
+		 * @param childQName
+		 * @return a new tag element suitable to be a child of this element.
+		 */
+		public TagElement addTag( QName childQName );
+
+		/**
+		 * @param childName
+		 * @param childAttrs
+		 * @return the new tag that was added.
+		 */
+		public TagElement addTag( String childName, Map<QName, String> childAttrs );
+
+		/**
+		 * @param childName
+		 * @return the new tag that was added.
+		 */
+		public TagElement addTag( String childName );
+		
+		/**
+		 * Removes the specified child element.
+		 * @param e
+		 * @return true if the element was removed.
+		 */
+		public boolean remove( Element e );
+		
+		/**
+		 * Removes all the child elements.
+		 */
+		public void clear();
+		
+		/**
+		 * @return the count of children.
+		 */
+		public int countChildren();
+		
+		/**
+		 * @param index
+		 * @return the specified child.
+		 */
+		public Element getChild( int index );
+
+		/**
+		 * Called as this tag element is popped off the tag element stack.
+		 * This means processing of this tag element is now finished.
+		 */
+		public void finish();
+
+		/**
+		 * @return true if there are children.
+		 */
+		public boolean hasChildren();
+		
+		/**
+		 * @return an iterator over the children of this tag element.
+		 */
+		public Iterator<Element> getChildren();
+
+		/**
+		 * @return returns true if getCdataValue() would return ok.
+		 * @see #getCdataValue()
+		 */
+		public boolean hasCdataValue();
+
+		/**
+		 * @return the string value of the child cdata element.
+		 * 
+		 * @throws NoSuchElementException if there is more than
+		 * one child or if there is one child and it is not a
+		 * cdata element.
+		 */
+		public String getCdataValue();
+		
+		/**
+		 * @return true if there are any attributes.
+		 */
+		public boolean hasAttrs();
+		
+		/**
+		 * @return the set of attr names for this tag
+		 */
+		public Iterator<QName> getAttrNames();
+		
+		/**
+		 * @param qualifier
+		 * @param name
+		 * @return attr matching specified parameters, else null.
+		 */
+		public String getAttr( String qualifier, String name );
+
+		/**
+		 * @param qualifier
+		 * @param name
+		 * @param value
+		 * @return this tag element.
+		 */
+		public TagElement setAttr( String qualifier, String name, String value );
+		
+		/**
+		 * @param qualifier
+		 * @param name
+		 * @return attr matching the specified parameters, else null.
+		 */
+		public Integer getIntAttr( String qualifier, String name );
+
+		/**
+		 * @param qualifier
+		 * @param name
+		 * @param value
+		 * @return this tag element.
+		 */
+		public TagElement setAttr( String qualifier, String name, int value );
+		
+		/**
+		 * @param qualifier
+		 * @param name
+		 * @return attr matching the specified parameters, else null.
+		 */
+		public Long getLongAttr( String qualifier, String name );
+
+		/**
+		 * @param qualifier
+		 * @param name
+		 * @param value
+		 * @return this tag element.
+		 */
+		public TagElement setAttr( String qualifier, String name, long value );
+
+		/**
+		 * Finds the tag element given the specified path. Note that it
+		 * will only match the first named element at every step.
+		 * @param path a qName path specified as qName!qName!qName...
+		 * @return the terminal element of the specified path, else null.
+		 */
+		public TagElement find( String path );
+
+		/**
+		 * Finds the tag element under this one with the specified name.
+		 * Note that it will only match the first named element.
+		 * @param oqualifier
+		 * @param oname
+		 * @return the named element, else null.
+		 */
+		public TagElement find( String oqualifier, String oname );
+
+		/**
+		 * Finds the tag element under this one with the specified name.
+		 * Note that it will only match the first named element.
+		 * @param subQName
+		 * @return the named element, else null.
+		 */
+		public TagElement find( QName subQName );
+	}
+	
+	/**
+	 * Default implementation of TagElement.
+	 */
+	public static class DefaultTagElement extends AbstractElement
+		implements TagElement
+	{
+		/**
+		 * Constructs the DefaultTagElement.
+		 *
+		 * @param qName
+		 * @param attrs
+		 */
+		public DefaultTagElement( QName qName, Map<QName, String> attrs )
+		{
+			this.qName = qName;
+			this.attrs = attrs;
+			//System.out.println( "constructed DefaultTagElement( "+qName+" )" );
+		}
+		
+		/**
+		 * Constructs the DefaultTagElement.
+		 *
+		 * @param qName
+		 */
+		public DefaultTagElement( QName qName )
+		{
+			this( qName, null );
+		}
+		
+		/**
+		 * Constructs the DefaultTagElement.
+		 *
+		 * @param name
+		 * @param attrs
+		 */
+		public DefaultTagElement( String name, Map<QName, String> attrs )
+		{
+			this( new QName( name ), attrs );
+		}
+		
+		/**
+		 * Constructs the DefaultTagElement.
+		 *
+		 * @param name
+		 */
+		public DefaultTagElement( String name )
+		{
+			this( new QName( name ), null );
+		}
+
+		private final QName qName;
+		
+		private Map<QName, String> attrs;
+
+		///////////////////////////////
+		// TagElement Implementation //
+		///////////////////////////////
+		
+		public QName getQName()
+		{
+			return qName;
+		}
+		
+		public void addCdata( String cdata )
+		{
+			add( new DefaultCdataElement( cdata ) );
+		}
+
+		public TagElement addTag( QName childQName, Map<QName, String> childAttrs )
+		{
+			DefaultTagElement tagElement = new DefaultTagElement( childQName, childAttrs );
+			add( tagElement );
+			return tagElement;
+		}
+
+		public TagElement addTag( QName childQName )
+		{
+			return addTag( childQName, null );
+		}
+
+		public TagElement addTag( String childName, Map<QName, String> childAttrs )
+		{
+			return addTag( new QName( childName ), null );
+		}
+
+		public TagElement addTag( String childName )
+		{
+			return addTag( new QName( childName ), null );
+		}
+
+		public boolean remove( Element e )
+		{
+			Iterator<Element> i = getChildren();
+			while (i.hasNext())
+			{
+				if (i.next() == e)
+				{
+					i.remove();
+					return true;
+				}
+			}
+			return false;
+		}
+
+		public void clear()
+		{
+			if (firstElement != null)
+				firstElement = null;
+			
+			if (elements != null)
+			{
+				elements.clear();
+				elements = null;
+			}
+		}
+
+		public boolean hasAttrs()
+		{
+			return attrs != null && !attrs.isEmpty();
+		}
+		
+		public Iterator<QName> getAttrNames()
+		{
+			if (attrs == null)
+				return new EmptyIterator<QName>();
+			
+			return attrs.keySet().iterator();
+		}
+		
+		public String getAttr( String qualifier, String name )
+		{
+			if (attrs == null)
+				return null;
+			
+			return attrs.get( new QName( qualifier, name ) );
+		}
+		
+		public TagElement setAttr( String qualifier, String name, String value )
+		{
+			if (attrs == null)
+				attrs = new HashMap<QName, String>();
+			
+			attrs.put( new QName( qualifier, name ), value );
+			
+			return this;
+		}
+
+		public boolean matches( String qualifier, String name )
+		{
+			return qName.matches( qualifier, name );
+		}
+
+		public boolean matches( QName otherQName )
+		{
+			return qName.matches( otherQName );
+		}
+
+		public boolean hasChildren()
+		{
+			if (firstElement != null)
+				return true;
+			
+			return elements != null && !elements.isEmpty();
+		}
+		
+		public Iterator<Element> getChildren()
+		{
+			if (firstElement != null)
+				return new SingleIterator<Element>( firstElement );
+			
+			if (elements == null)
+				return new EmptyIterator<Element>();
+			
+			return elements.iterator();
+		}
+
+		public Iterator<Element> iterator()
+		{
+			return getChildren();
+		}
+
+		public int countChildren()
+		{
+			if (firstElement != null)
+				return 1;
+			
+			return elements != null ? elements.size() : 0;
+		}
+
+		public Element getChild( int index )
+		{
+			if (firstElement != null && index == 0)
+				return firstElement;
+			
+			if (elements == null)
+				throw new NoSuchElementException();
+			
+			return elements.get( index );
+		}
+		
+		public void finish()
+		{
+			// nothing to do.
+		}
+		
+		public boolean hasCdataValue()
+		{
+			int n = countChildren();
+			if (n == 0)
+				return true;
+			
+			if (n > 1)
+				return false;
+			
+			Element e = getChild( 0 );
+			
+			return e instanceof CdataElement;
+		}
+
+		public String getCdataValue()
+		{
+			int n = countChildren();
+			
+			if (n == 0)
+				return "";
+			
+			if (n > 1)
+				throw new NoSuchElementException( "not just one child" );
+			
+			Element e = getChild( 0 );
+			
+			if (!(e instanceof CdataElement))
+				throw new NoSuchElementException( "child not cdata element" );
+			
+			return ((CdataElement) e).getCdata();
+		}
+
+		/**
+		 * @param element
+		 * @return the element added
+		 */
+		public Element add( Element element )
+		{
+			if (elements == null)
+			{
+				if (firstElement == null)
+				{
+					firstElement = element;
+				}
+				else
+				{
+					elements = new ArrayList<Element>( 4 );
+					elements.add( firstElement );
+					firstElement = null;
+					elements.add( element );
+				}
+			}
+			else
+			{
+				elements.add( element );
+			}
+			return element;
+		}
+		
+		private List<Element> elements;
+		
+		private Element firstElement;
+		
+		public void toString( Writer wtr, boolean newlineBetweenTags,
+			boolean collapseEmptyTags ) throws IOException
+		{
+			if (hasChildren() || !collapseEmptyTags)
+			{
+				// <tagname attrs>children</tagname>
+				wtr.write( '<' );
+				qName.toString( wtr );
+				if (hasAttrs())
+					dumpAttrs( wtr );
+				wtr.write( '>' );
+				if (newlineBetweenTags && wantNewlineBeforeChildren())
+					wtr.write( CRLF );
+				
+				dumpChildren( wtr, newlineBetweenTags, collapseEmptyTags );
+				
+				wtr.write( "</" );
+				qName.toString( wtr );
+				wtr.write( '>' );
+			}
+			else
+			{
+				// <tagname attrs/>
+				wtr.write( '<' );
+				qName.toString( wtr );
+				if (hasAttrs())
+					dumpAttrs( wtr );
+				wtr.write( "/>" );
+			}
+			
+			if (newlineBetweenTags)
+				wtr.write( CRLF );
+		}
+		
+		private boolean wantNewlineBeforeChildren()
+		{
+			// we want newline unless there are no children
+			// or only a single child and the child is a
+			// cdata.
+			
+			int n = countChildren();
+			
+			if (n > 1)
+				return true;
+			
+			if (n == 0)
+				return false;
+			
+			return !(getChild( 0 ) instanceof CdataElement);
+		}
+		
+		private void dumpAttrs( Writer wtr ) throws IOException
+		{
+			for (Map.Entry<QName, String> me : attrs.entrySet())
+			{
+				QName qn = me.getKey();
+				String value = me.getValue();
+				
+				wtr.write( ' ' );
+				qn.toString( wtr );
+				wtr.write( "=\"" );
+				ProtectAttrValue.write( wtr, value );
+				wtr.write( '"' );
+			}
+		}
+
+		private void dumpChildren( Writer wtr, boolean newlineBetweenTags,
+			boolean collapseEmptyTags ) throws IOException
+		{
+			for (Element e : this)
+				e.toString( wtr, newlineBetweenTags, collapseEmptyTags );
+		}
+
+		public TagElement find( String path )
+		{
+			StringTokenizer st = new StringTokenizer( path, "!" );
+			TagElement e = this;
+			while (e != null && st.hasMoreTokens())
+			{
+				String token = st.nextToken();
+				QName subQName = new QName( token );
+				e = e.find( subQName );
+			}
+			return e;
+		}
+
+		public TagElement find( String oqualifier, String oname )
+		{
+			for (Element e: this)
+			{
+				if (e instanceof TagElement)
+				{
+					TagElement te = (TagElement) e;
+					if (te.matches( oqualifier, oname ))
+						return te;
+				}
+			}
+			return null;
+		}
+
+		public TagElement find( QName subQName )
+		{
+			for (Element e: this)
+			{
+				if (e instanceof TagElement)
+				{
+					TagElement te = (TagElement) e;
+					if (te.matches( subQName ))
+						return te;
+				}
+			}
+			return null;
+		}
+
+		public Integer getIntAttr( String qualifier, String name )
+		{
+			String s = getAttr( qualifier, name );
+			
+			if (s == null)
+				return null;
+			
+			return new Integer( s );
+		}
+		
+		public TagElement setAttr( String qualifier, String name, int value )
+		{
+			return setAttr( qualifier, name, Integer.toString( value ) );
+		}
+
+		public Long getLongAttr( String qualifier, String name )
+		{
+			String s = getAttr( qualifier, name );
+			
+			if (s == null)
+				return null;
+			
+			return new Long( s );
+		}
+		
+		public TagElement setAttr( String qualifier, String name, long value )
+		{
+			return setAttr( qualifier, name, Long.toString( value ) );
+		}
+	}
+	
+	/**
+	 * Subclass of DefaultTagElement for root tags. Needed to put
+	 * out xml version tag prefix on toString, etc.
+	 */
+	public static class RootTagElement extends DefaultTagElement
+	{
+		/**
+		 * @param qName
+		 * @param attrs
+		 */
+		public RootTagElement( QName qName, Map<QName, String> attrs )
+		{
+			super( qName, attrs );
+		}
+
+		/**
+		 * @param qName
+		 */
+		public RootTagElement( QName qName )
+		{
+			super( qName );
+		}
+
+		/**
+		 * @param name
+		 * @param attrs
+		 */
+		public RootTagElement( String name, Map<QName, String> attrs )
+		{
+			super( name, attrs );
+		}
+
+		/**
+		 * @param name
+		 */
+		public RootTagElement( String name )
+		{
+			super( name );
+		}
+		
+		public void toString( Writer wtr, boolean newlineBetweenTags,
+			boolean collapseEmptyTags ) throws IOException
+		{
+			// TODO get proper encoding from somewhere
+			wtr.write( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" );
+			wtr.write( CRLF );
+			super.toString( wtr, newlineBetweenTags, collapseEmptyTags );
+		}
+	}
+	
+	/**
+	 * Description of QName
+	 */
+	public static class QName
+	{
+		/**
+		 * @param qualifier
+		 * @param name
+		 */
+		public QName( String qualifier, String name )
+		{
+			this.qualifier = qualifier;
+			this.name = name;
+			//System.out.println( "constructed QName( "+this+" )" );
+		}
+
+		/**
+		 * @param qName
+		 */
+		public QName( String qName )
+		{
+			String[] x = StringUtil.leftSplit( qName, ':' );
+			if (x != null)
+			{
+				qualifier = x[0];
+				name = x[1];
+			}
+			else
+			{
+				qualifier = null;
+				name = qName;
+			}
+		}
+
+		/**
+		 * Description of qualifier
+		 */
+		public final String qualifier;
+		
+		/**
+		 * Description of name
+		 */
+		public final String name;
+		
+		/**
+		 * @param oqualifier
+		 * @param oname
+		 * @return true if oqualifier and oname match us
+		 */
+		public boolean matches( String oqualifier, String oname )
+		{
+			return matches( oqualifier, qualifier, oname, name );
+		}
+		
+		/**
+		 * @param other
+		 * @return true if other matches us.
+		 */
+		public boolean matches( QName other )
+		{
+			return matches( other.qualifier, qualifier, other.name, name );
+		}
+		
+		/**
+		 * @param qualifier1
+		 * @param qualifier2
+		 * @param name1
+		 * @param name2
+		 * @return true if the qualifiers match each other and the names match
+		 * each other.
+		 */
+		public static boolean matches( String qualifier1, String qualifier2,
+			String name1, String name2 )
+		{
+			return StringUtil.equals( qualifier1, qualifier2) &&
+				StringUtil.equals( name1, name2 );
+		}
+
+		@Override
+		public int hashCode()
+		{
+			// must match the usage of StringUtil.equals above.
+			return StringUtil.hashCode( qualifier ) ^ StringUtil.hashCode( name );
+		}
+
+		@Override
+		public boolean equals( Object obj )
+		{
+			if (obj == this)
+				return true;
+			
+			if (obj == null)
+				return false;
+			
+			if (obj.getClass() != QName.class)
+				return false;
+			
+			QName other = (QName) obj;
+			
+			return matches( qualifier, other.qualifier, name, other.name );
+		}
+
+		@Override
+		public String toString()
+		{
+			try
+			{
+				StringWriter wtr = new StringWriter();
+				toString( wtr );
+				return wtr.toString();
+			}
+			catch ( IOException e )
+			{
+				throw new RuntimeException( "caught exception", e );
+			}
+		}
+		
+		/**
+		 * @param wtr
+		 * @throws IOException
+		 */
+		public void toString( Writer wtr ) throws IOException
+		{
+			if (qualifier != null)
+			{
+				wtr.write( qualifier );
+				wtr.write( ':' );
+			}
+			wtr.write( name );
+		}
+		
+		/**
+		 * @param qualifier
+		 * @param name
+		 * @return printable form of a qualified name
+		 */
+		public static String toString( String qualifier, String name )
+		{
+			if (qualifier != null)
+				return qualifier+':'+name;
+			return name;
+		}
+	}
+	
+	/**
+	 * 
+	 */
+	abstract public static class ProtectBase extends Writer
+	{
+		/**
+		 * @param wtr
+		 */
+		public ProtectBase( Writer wtr )
+		{
+			this.wtr = wtr;
+		}
+		
+		/**
+		 * Description of wtr
+		 */
+		protected final Writer wtr;
+		
+		/**
+		 * 
+		 */
+		public static final String LT = "&lt;";
+		
+		/**
+		 * 
+		 */
+		public static final String GT = "&gt;";
+		
+		/**
+		 * 
+		 */
+		public static final String AMP = "&amp;";
+		
+		/**
+		 * 
+		 */
+		public static final String QUOT = "&quot;";
+		
+		/**
+		 * 
+		 */
+		public static final String TAB = "&#9;";
+		
+		/**
+		 * 
+		 */
+		public static final String CR = "&#13;";
+		
+		/**
+		 * 
+		 */
+		public static final String LF = "&#10;";
+
+		@Override
+		public void close()
+		{
+			// ignore.
+		}
+
+		@Override
+		public void flush()
+		{
+			// ignore.
+		}
+
+		@Override
+		public void write( char[] cbuf, int off, int len ) throws IOException
+		{
+			for (int i = 0; i < len; i++)
+				write( cbuf[off+i] );
+		}
+
+		@Override
+		public void write( String str, int off, int len ) throws IOException
+		{
+			for (int i = 0; i < len; i++)
+				write( str.charAt( off+i ) );
+		}
+
+		@Override
+		abstract public void write( int c ) throws IOException;
+
+		/**
+		 * Writes a character the normal way: ascii character range
+		 * (9, 10, 13, 32-126) is put out as itself, while any other
+		 * characters are put out as &#nnnnn;
+		 * @param wtr
+		 * @param c
+		 * @throws IOException
+		 */
+		protected static void defaultWrite( Writer wtr, int c ) throws IOException
+		{
+			if (c >= 32 && c <= 126)
+			{
+				wtr.write( c ); // printable ascii is ok
+			}
+			else if (c == '\t' || c == '\n' || c == '\r')
+			{
+				wtr.write( c ); // tab, linefeed, and carriage return are ok.
+			}
+			else
+			{
+				wtr.write( "&#" );
+				wtr.write( Integer.toString( c ) );
+				wtr.write( ';' );
+			}
+		}
+	}
+	
+	/**
+	 * 
+	 */
+	final public static class ProtectAttrValue extends ProtectBase
+	{
+		/**
+		 * @param wtr
+		 */
+		public ProtectAttrValue( Writer wtr )
+		{
+			super( wtr );
+		}
+
+		@Override
+		public void write( int c ) throws IOException
+		{
+			write( wtr, c );
+		}
+
+		/**
+		 * @param wtr
+		 * @param s
+		 * @throws IOException
+		 */
+		public static void write( Writer wtr, String s ) throws IOException
+		{
+			int n = s.length();
+			for (int i = 0; i < n; i++)
+				write( wtr, s.charAt( i ) );
+		}
+		
+		/**
+		 * @param s an attribute name which might have special characters.
+		 * @return the string protected as appropriate for an
+		 * attribute.
+		 * @throws IOException
+		 */
+		public static String toString( String s ) throws IOException
+		{
+			StringWriter sw = new StringWriter();
+			write( sw, s );
+			return sw.toString();
+		}
+		
+		/**
+		 * @param wtr
+		 * @param c
+		 * @throws IOException
+		 */
+		public static void write( Writer wtr, int c ) throws IOException
+		{
+			switch (c)
+			{
+				case '<':
+					wtr.write( LT );
+					break;
+				case '>':
+					wtr.write( GT );
+					break;
+				case '&':
+					wtr.write( AMP );
+					break;
+				case '"':
+					wtr.write( QUOT );
+					break;
+				case '\t':
+					wtr.write( TAB );
+					break;
+				case '\r':
+					wtr.write( CR );
+					break;
+				case '\n':
+					wtr.write( LF );
+					break;
+				default:
+					defaultWrite( wtr, c );
+					break;
+			}
+		}
+	}
+	
+	/**
+	 * 
+	 */
+	final public static class ProtectCData extends ProtectBase
+	{
+		/**
+		 * @param wtr
+		 */
+		public ProtectCData( Writer wtr )
+		{
+			super( wtr );
+		}
+
+		@Override
+		public void write( int c ) throws IOException
+		{
+			write( wtr, c );
+		}
+
+		/**
+		 * @param wtr
+		 * @param s
+		 * @throws IOException
+		 */
+		public static void write( Writer wtr, String s ) throws IOException
+		{
+			int n = s.length();
+			for (int i = 0; i < n; i++)
+				write( wtr, s.charAt( i ) );
+		}
+		
+		/**
+		 * @param s an attribute name which might have special characters.
+		 * @return the string protected as appropriate for an
+		 * attribute.
+		 * @throws IOException
+		 */
+		public static String toString( String s ) throws IOException
+		{
+			StringWriter sw = new StringWriter();
+			write( sw, s );
+			return sw.toString();
+		}
+		
+		/**
+		 * @param wtr
+		 * @param c
+		 * @throws IOException
+		 */
+		public static void write( Writer wtr, int c ) throws IOException
+		{
+			switch (c)
+			{
+				case '<':
+					wtr.write( LT );
+					break;
+				case '>':
+					wtr.write( GT );
+					break;
+				case '&':
+					wtr.write( AMP );
+					break;
+				default:
+					defaultWrite( wtr, c );
+					break;
+			}
+		}
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/PerfBasics.java b/util/src/test/java/org/apache/etch/util/PerfBasics.java
new file mode 100644
index 0000000..02460f2
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/PerfBasics.java
@@ -0,0 +1,153 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Basic perf tests.
+ */
+public class PerfBasics
+{
+	/**
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		final int time = 15;
+		final int count = 1;
+		
+//		new PerfTest( "null", time, count )
+//		{
+//			@Override
+//			public void run( long n ) throws Exception
+//			{
+//				while (n-- > 0);
+//			}
+//		}.run();
+		
+//		new PerfTest( "add", time, count )
+//		{
+//			@Override
+//			public void run( long n ) throws Exception
+//			{
+//				int x = 0;
+//				while (n-- > 0)
+//					x += 1;
+//			}
+//		}.run();
+		
+//		new PerfTest( "func", time, count )
+//		{
+//			@Override
+//			public void run( long n ) throws Exception
+//			{
+//				while (n-- > 0)
+//					func();
+//			}
+//		}.run();
+		
+//		new PerfTest( "sfunc", time, count )
+//		{
+//			@Override
+//			public void run( long n ) throws Exception
+//			{
+//				while (n-- > 0)
+//					sfunc();
+//			}
+//		}.run();
+		
+//		new PerfTest( "addWithTry", time, count )
+//		{
+//			@Override
+//			public void run( long n ) throws Exception
+//			{
+//				int x = 0;
+//				while (n-- > 0)
+//				{
+//					try
+//					{
+//						x += 1;
+//					}
+//					catch ( Exception e )
+//					{
+//						// do nothing.
+//					}
+//				}
+//			}
+//		}.run();
+		
+		final String k1 = "a";
+		final String k2 = "b";
+		final String k3 = "c";
+		final String k4 = "d";
+		
+		final String v1 = "1";
+		final String v2 = "2";
+		final String v3 = "3";
+		
+		new PerfTest( "getHit", time, count )
+		{
+			@Override
+			public void run( long n ) throws Exception
+			{
+				Map<String, Object> d = new HashMap<String, Object>();
+				d.put( k1, v1 );
+				d.put( k2, v2 );
+				d.put( k3, v3 );
+				while (n-- > 0)
+					d.get( k1 );
+			}
+		}.run();
+		
+		new PerfTest( "getMiss", time, count )
+		{
+			@Override
+			public void run( long n ) throws Exception
+			{
+				Map<String, Object> d = new HashMap<String, Object>();
+				d.put( k1, v1 );
+				d.put( k2, v2 );
+				d.put( k3, v3 );
+				while (n-- > 0)
+					d.get( k4 );
+			}
+		}.run();
+	}
+	
+	/**
+	 * 
+	 */
+	public static void func()
+	{
+		// nothing to do.
+	}
+	
+	/**
+	 * 
+	 */
+	public synchronized static void sfunc()
+	{
+		// nothing to do.
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/TestAlarmManager.java b/util/src/test/java/org/apache/etch/util/TestAlarmManager.java
new file mode 100644
index 0000000..e0f1de2
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/TestAlarmManager.java
@@ -0,0 +1,426 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+/** Test of AlarmManager */
+public class TestAlarmManager
+{
+	private final static int Q1 = 50;
+
+	private final static int Q2 = 100;
+
+	private final static int Q3 = 150;
+	
+	private final Object s1 = new Object();
+	
+	private final Object s2 = new Object();
+	
+	private final MyAlarmListener listener = new MyAlarmListener( 0 );
+
+	/** @throws Exception */
+	@Test
+	public void start1() throws Exception
+	{
+		AlarmManager am = new AlarmManager();
+		assertFalse( am.isStarted() );
+		am.start();
+		assertTrue( am.isStarted() );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void start2() throws Exception
+	{
+		// already started
+		AlarmManager am = new AlarmManager();
+		assertFalse( am.isStarted() );
+		am.start();
+		assertTrue( am.isStarted() );
+		am.start();
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void stop1() throws Exception
+	{
+		// is not started
+		AlarmManager am = new AlarmManager();
+		assertFalse( am.isStarted() );
+		am.stop();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void stop2() throws Exception
+	{
+		AlarmManager am = new AlarmManager();
+		assertFalse( am.isStarted() );
+		am.start();
+		assertTrue( am.isStarted() );
+		am.stop();
+		assertFalse( am.isStarted() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void static1() throws Exception
+	{
+		AlarmManager.shutdown();
+		
+		assertNull( AlarmManager.getAlarmManager( false ) );
+		assertNull( AlarmManager.getAlarmManager( false ) );
+		
+		AlarmManager am1 = AlarmManager.getAlarmManager( true );
+		assertNotNull( am1 );
+		assertTrue( am1.isStarted() );
+		
+		AlarmManager am2 = AlarmManager.getAlarmManager( true );
+		assertSame( am2, am1 );
+		assertTrue( am1.isStarted() );
+		
+		AlarmManager.shutdown();
+		assertFalse( am1.isStarted() );
+		assertNull( AlarmManager.getAlarmManager( false ) );
+		
+		AlarmManager.shutdown();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void listener1() throws Exception
+	{
+		assertEquals( 0, listener.delay );
+		assertFalse( listener.wake.get() );
+		assertNull( listener.state );
+
+		listener.wakeup( null, null, 12345 );
+		assertEquals( 0, listener.delay );
+		assertTrue( listener.wake.get() );
+		assertNull( listener.state );
+		
+		listener.wakeup( null, s1, 23456 );
+		assertEquals( 0, listener.delay );
+		assertTrue( listener.wake.get() );
+		assertSame( s1, listener.state );
+
+		MyAlarmListener listener1 = new MyAlarmListener( 1 );
+		assertEquals( 1, listener1.delay );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void add1() throws Exception
+	{
+		// is not started
+		AlarmManager am = new AlarmManager();
+		
+		am.add( listener, null, Q1 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = NullPointerException.class )
+	public void add2() throws Exception
+	{
+		// listener == null
+		AlarmManager am = new AlarmManager();
+		am.start();
+		
+		am.add( null, null, Q1 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void add3() throws Exception
+	{
+		// delay <= 0
+		AlarmManager am = new AlarmManager();
+		am.start();
+		
+		am.add( listener, null, -1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void add4() throws Exception
+	{
+		AlarmManager am = new AlarmManager();
+		am.start();
+
+		am.add( listener, null, Q1 );
+		assertFalse( listener.wake.get() );
+		assertNull( listener.state );
+
+		Thread.sleep( Q2 );
+		assertTrue( listener.wake.get() );
+		assertNull( listener.state );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void add5() throws Exception
+	{
+		AlarmManager am = new AlarmManager();
+		am.start();
+
+		am.add( listener, s1, Q1 );
+		assertFalse( listener.wake.get() );
+		assertNull( listener.state );
+
+		Thread.sleep( Q2 );
+		assertTrue( listener.wake.get() );
+		assertSame( s1, listener.state );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void add6() throws Exception
+	{
+		AlarmManager am = new AlarmManager();
+		am.start();
+
+		am.add( listener, s1, Q3 );
+		assertFalse( listener.wake.get() );
+		assertNull( listener.state );
+
+		am.add( listener, s2, Q1 );
+		assertFalse( listener.wake.get() );
+		assertNull( listener.state );
+
+		Thread.sleep( Q2 );
+		assertTrue( listener.wake.get() );
+		assertSame( s2, listener.state );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void add7() throws Exception
+	{
+		AlarmManager am = new AlarmManager();
+		am.start();
+
+		listener.excp = true;
+		am.add( listener, s1, Q1 );
+		assertFalse( listener.wake.get() );
+		assertNull( listener.state );
+
+		Thread.sleep( Q2 );
+		assertTrue( listener.wake.get() );
+		assertSame( s1, listener.state );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void remove1() throws Exception
+	{
+		// is not started
+		AlarmManager am = new AlarmManager();
+		
+		am.remove( listener );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void remove2() throws Exception
+	{
+		AlarmManager am = new AlarmManager();
+		am.start();
+		
+		am.remove( listener );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void remove3() throws Exception
+	{
+		AlarmManager am = new AlarmManager();
+		am.start();
+
+		am.add( listener, null, Q1 );
+		assertFalse( listener.wake.get() );
+		assertNull( listener.state );
+		
+		am.remove( listener );
+		assertFalse( listener.wake.get() );
+		assertNull( listener.state );
+		
+		Thread.sleep( Q2 );
+		assertFalse( listener.wake.get() );
+		assertNull( listener.state );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void repeat1() throws Exception
+	{
+		AlarmManager am = new AlarmManager();
+		am.start();
+		
+		listener.delay = Q2;
+		am.add( listener, null, Q2 );
+		
+		listener.wake.waitUntilEqAndSet( true, Q3, false );
+		System.out.printf( "due0 = %d\n", listener.due );
+		long t0 = listener.due;
+		
+		listener.wake.waitUntilEqAndSet( true, Q3, false );
+		System.out.printf( "due1 = %d\n", listener.due );
+		long d1 = listener.due - t0;
+		
+		listener.wake.waitUntilEqAndSet( true, Q3, false );
+		System.out.printf( "due2 = %d\n", listener.due );
+		long d2 = listener.due - t0;
+		
+		listener.wake.waitUntilEqAndSet( true, Q3, false );
+		System.out.printf( "due3 = %d\n", listener.due );
+		long d3 = listener.due - t0;
+		
+		Thread.sleep( Q1 );
+		listener.delay = 0;
+		
+		listener.wake.waitUntilEqAndSet( true, Q3, false );
+		System.out.printf( "due4 = %d\n", listener.due );
+		long d4 = listener.due - t0;
+		
+		long m1 = Math.round( d1/(double) d1 );
+		long m2 = Math.round( d2/(double) d1 );
+		long m3 = Math.round( d3/(double) d1 );
+		long m4 = Math.round( d4/(double) d1 );
+		
+		System.out.printf( "times %d %d %d %d %d\n", t0, d1, d2, d3, d4 );
+		
+		assertEquals( 1, m1 );
+		assertEquals( 2, m2 );
+		assertEquals( 3, m3 );
+		assertEquals( 4, m4 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void repeat2() throws Exception
+	{
+		AlarmManager am = new AlarmManager();
+		am.start();
+		
+		listener.delay = -Q2;
+		am.add( listener, null, Q2 );
+		
+		listener.wake.waitUntilEqAndSet( true, Q3, false );
+		System.out.printf( "due0 = %d\n", listener.due );
+		long t0 = listener.due;
+		
+		listener.wake.waitUntilEqAndSet( true, Q3, false );
+		System.out.printf( "due1 = %d\n", listener.due );
+		long d1 = listener.due - t0;
+		
+		listener.wake.waitUntilEqAndSet( true, Q3, false );
+		System.out.printf( "due2 = %d\n", listener.due );
+		long d2 = listener.due - t0;
+		
+		listener.wake.waitUntilEqAndSet( true, Q3, false );
+		System.out.printf( "due3 = %d\n", listener.due );
+		long d3 = listener.due - t0;
+		
+		Thread.sleep( Q1 );
+		listener.delay = 0;
+		
+		listener.wake.waitUntilEqAndSet( true, Q3, false );
+		System.out.printf( "due4 = %d\n", listener.due );
+		long d4 = listener.due - t0;
+		
+		long m1 = Math.round( d1/(double) d1 );
+		long m2 = Math.round( d2/(double) d1 );
+		long m3 = Math.round( d3/(double) d1 );
+		long m4 = Math.round( d4/(double) d1 );
+		
+		System.out.printf( "times %d %d %d %d %d\n", t0, d1, d2, d3, d4 );
+		
+		assertEquals( 1, m1 );
+		assertEquals( 2, m2 );
+		assertEquals( 3, m3 );
+		assertEquals( 4, m4 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = TimeoutException.class )
+	public void repeat3() throws Exception
+	{
+		// timeout
+		AlarmManager am = new AlarmManager();
+		am.start();
+		
+		listener.delay = Q2;
+		am.add( listener, null, Q2 );
+		
+		listener.wake.waitUntilEqAndSet( true, Q3, false );
+		
+		listener.wake.waitUntilEqAndSet( true, Q3, false );
+		
+		listener.wake.waitUntilEqAndSet( true, Q3, false );
+		
+		Thread.sleep( Q1 );
+		listener.delay = 0;
+		
+		listener.wake.waitUntilEqAndSet( true, Q3, false );
+		// alarm is now canceled
+		
+		// this should timeout...
+		listener.wake.waitUntilEqAndSet( true, Q3, false );
+	}
+
+	private static class MyAlarmListener implements AlarmListener
+	{
+		public MyAlarmListener( int delay )
+		{
+			this.delay = delay;
+		}
+
+		private int delay;
+		
+		private boolean excp;
+
+		private Monitor<Boolean> wake = new Monitor<Boolean>( "wake", false );
+
+		private Object state;
+		
+		private long due;
+
+		public int wakeup( AlarmManager manager, Object state, long due )
+		{
+			this.state = state;
+			this.due = due;
+			wake.set( true );
+			
+			if (excp)
+				throw new RuntimeException();
+			
+			return delay;
+		}
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/TestCircularQueue.java b/util/src/test/java/org/apache/etch/util/TestCircularQueue.java
new file mode 100644
index 0000000..a4e56e3
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/TestCircularQueue.java
@@ -0,0 +1,687 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+/** Test of CircularQueue */
+public class TestCircularQueue
+{
+	// change this to a much smaller number (e.g., 0.1) to actually test the
+	// circular queue timeout accuracy.
+	private final static double REL_ERROR = 100000;
+	
+	/** @throws Exception */
+	@Test
+	public void testgettimes() throws Exception
+	{
+		@SuppressWarnings("unused")
+		double[] times;
+		
+		times = gettimes();
+//		System.out.printf( "times: hp %f / tod %f\n", times[0], times[1] );
+		
+		times = gettimes();
+//		System.out.printf( "times: hp %f / tod %f\n", times[0], times[1] );
+		
+		times = gettimes();
+//		System.out.printf( "times: hp %f / tod %f\n", times[0], times[1] );
+	}
+	
+	private double[] gettimes() throws InterruptedException
+	{
+		long t0 = Timer.getNanos();
+		long s0 = System.currentTimeMillis();
+		
+		Thread.sleep( 1000 );
+		
+		double t = Timer.getSecondsSince( t0 );
+		double s = (System.currentTimeMillis() - s0) / 1000.0;
+		
+		return new double[] { t, s };
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void construct1() throws Exception
+	{
+		new CircularQueue<Integer>( 0 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void construct2() throws Exception
+	{
+		new CircularQueue<Integer>( -1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construct3() throws Exception
+	{
+		CircularQueue<Integer> queue = new CircularQueue<Integer>( 1 );
+		assertEquals( 1, queue.size() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construct4() throws Exception
+	{
+		CircularQueue<Integer> queue = new CircularQueue<Integer>( 2 );
+		assertEquals( 2, queue.size() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void construct5() throws Exception
+	{
+		CircularQueue<Integer> queue = new CircularQueue<Integer>();
+		assertEquals( 10, queue.size() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void putget1() throws Exception
+	{
+		CircularQueue<Integer> queue = new CircularQueue<Integer>();
+		
+		assertEquals( 0, queue.count() );
+		assertTrue( queue.isEmpty() );
+		assertFalse( queue.isFull() );
+		
+		for (int i = 0; i < 10000; i++)
+		{
+			queue.put( i );
+			assertEquals( 1, queue.count() );
+			assertFalse( queue.isEmpty() );
+			
+			assertEquals( i, queue.get() );
+			assertEquals( 0, queue.count() );
+			assertTrue( queue.isEmpty() );
+		}
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void putget2() throws Exception
+	{
+		CircularQueue<Integer> queue = new CircularQueue<Integer>();
+		
+		assertNull( queue.get( 1 ) );
+		assertNull( queue.get( -1 ) );
+		assertNull( queue.get( 10 ) );
+		
+		queue.put( 9 );
+		assertEquals( 9, queue.get( 1 ) );
+		
+		queue.put( 9 );
+		assertEquals( 9, queue.get( -1 ) );
+		
+		queue.put( 9 );
+		assertEquals( 9, queue.get( 10 ) );
+		
+		assertNull( queue.get( 1 ) );
+		assertNull( queue.get( -1 ) );
+		assertNull( queue.get( 10 ) );
+		
+		long t0;
+		double t;
+		
+		t0 = System.nanoTime();
+		assertNull( queue.get( 10 ) );
+		t = (System.nanoTime() - t0) / 1000000.0;
+		// TODO is there a better way for choosing relative error?
+		TestHelp.assertRelError( 10, t, REL_ERROR );
+		
+		t0 = System.nanoTime();
+		assertNull( queue.get( 20 ) );
+		t = (System.nanoTime() - t0) / 1000000.0;
+		// TODO is there a better way for choosing relative error?
+		TestHelp.assertRelError( 20, t, REL_ERROR );
+		
+		t0 = System.nanoTime();
+		assertNull( queue.get( 30 ) );
+		t = (System.nanoTime() - t0) / 1000000.0;
+		// TODO is there a better way for choosing relative error?
+		TestHelp.assertRelError( 30, t, REL_ERROR );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void putget3() throws Exception
+	{
+		CircularQueue<Integer> queue = new CircularQueue<Integer>();
+		
+		assertTrue( queue.put( 1 ) );
+		assertTrue( queue.put( 2 ) );
+		assertTrue( queue.put( 3 ) );
+		assertEquals( 1, queue.get() );
+		assertEquals( 2, queue.get() );
+		assertEquals( 3, queue.get() );
+		
+		assertTrue( queue.put( 1, 0 ) );
+		assertTrue( queue.put( 2, 0 ) );
+		assertTrue( queue.put( 3, 0 ) );
+		assertEquals( 1, queue.get( 0 ) );
+		assertEquals( 2, queue.get( 0 ) );
+		assertEquals( 3, queue.get( 0 ) );
+		
+		assertTrue( queue.put( 1, -1 ) );
+		assertTrue( queue.put( 2, -1 ) );
+		assertTrue( queue.put( 3, -1 ) );
+		assertEquals( 1, queue.get( -1 ) );
+		assertEquals( 2, queue.get( -1 ) );
+		assertEquals( 3, queue.get( -1 ) );
+		
+		assertTrue( queue.put( 1, 1 ) );
+		assertTrue( queue.put( 2, 1 ) );
+		assertTrue( queue.put( 3, 1 ) );
+		assertEquals( 1, queue.get( 1 ) );
+		assertEquals( 2, queue.get( 1 ) );
+		assertEquals( 3, queue.get( 1 ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void get() throws Exception
+	{
+		CircularQueue<Integer> queue = new CircularQueue<Integer>( 1 );
+		
+		System.nanoTime();
+		assertNull( queue.get( 10 ) );
+		TestHelp.assertRelError( 1, 1, 1 );
+
+		for (int i: new int[] { 10, 20, 30, 50, 80, 130, 210, 340, 550, 890, 1440 } )
+		{
+//			System.out.printf( "get delay = %d\n", i );
+			long t0 = System.nanoTime();
+			assertNull( queue.get( i ) );
+			double t = (System.nanoTime() - t0) / 1000000.0;
+			// TODO is there a better way for choosing relative error?
+			TestHelp.assertRelError( i, t, REL_ERROR );
+		}
+	}
+	
+	/** @throws Exception */
+	@Test( expected = NullPointerException.class )
+	public void put() throws Exception
+	{
+		CircularQueue<Integer> queue = new CircularQueue<Integer>();
+		queue.put( null );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void full() throws Exception
+	{
+		CircularQueue<Integer> queue = new CircularQueue<Integer>( 1 );
+		
+		assertFalse( queue.isFull() );
+		assertTrue( queue.put( 0 ) );
+		assertTrue( queue.isFull() );
+		assertEquals( 0, queue.get() );
+		assertFalse( queue.isFull() );
+		
+		assertTrue( queue.put( 0 ) );
+		assertFalse( queue.put( 0, -1 ) );
+		assertFalse( queue.put( 0, 1 ) );
+		assertFalse( queue.put( 0, 10 ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void close1() throws Exception
+	{
+		CircularQueue<Integer> queue = new CircularQueue<Integer>();
+		
+		assertFalse( queue.isClosed() );
+		queue.close();
+		assertTrue( queue.isClosed() );
+		
+		assertNull( queue.get() );
+		assertNull( queue.get( -1 ) );
+		assertNull( queue.get( 0 ) );
+		assertNull( queue.get( 1 ) );
+		
+		queue.close();
+		assertTrue( queue.isClosed() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void close2() throws Exception
+	{
+		CircularQueue<Integer> queue = new CircularQueue<Integer>();
+
+		assertFalse( queue.isClosed() );
+		queue.close();
+		assertTrue( queue.isClosed() );
+		
+		assertFalse( queue.put( 0 ) );
+		assertFalse( queue.put( 0, -1 ) );
+		assertFalse( queue.put( 0, 0 ) );
+		assertFalse( queue.put( 0, 1 ) );
+		
+		queue.close();
+		assertTrue( queue.isClosed() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void close3() throws Exception
+	{
+		CircularQueue<Integer> queue = new CircularQueue<Integer>();
+		queue.put( 1 );
+		queue.put( 2 );
+		queue.put( 3 );
+		queue.close();
+		assertEquals( 1, queue.get() );
+		assertEquals( 2, queue.get() );
+		assertEquals( 3, queue.get() );
+		assertNull( queue.get() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void delay1() throws Exception
+	{
+		final CircularQueue<Integer> queue = new CircularQueue<Integer>();
+		
+		TestHelp.delayAndStart( 10, new TestHelp.DelayRunnable() { public void run() throws Exception { queue.put( 99 ); } } );
+		assertEquals( 99, queue.get() );
+		
+		TestHelp.delayAndStart( 10, new TestHelp.DelayRunnable() { public void run() throws Exception { queue.close(); } } );
+		assertNull( queue.get() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void delay2() throws Exception
+	{
+		final CircularQueue<Integer> queue = new CircularQueue<Integer>( 1 );
+		
+		assertTrue( queue.put( 1 ) );
+		TestHelp.delayAndStart( 10, new TestHelp.DelayRunnable() { public void run() throws Exception { assertEquals( 1, queue.get() ); } } );
+		assertTrue( queue.put( 2 ) );
+		assertEquals( 2, queue.get() );
+		
+		assertTrue( queue.put( 1 ) );
+		TestHelp.delayAndStart( 10, new TestHelp.DelayRunnable() { public void run() throws Exception { queue.close(); } } );
+		assertFalse( queue.put( 2 ) );
+		assertEquals( 1, queue.get() );
+		assertNull( queue.get() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void stress1() throws Exception
+	{
+		final CircularQueue<Integer> queue = new CircularQueue<Integer>( 1 );
+		final int n = 10000;
+		
+		new Thread( new Runnable()
+		{
+			public void run()
+			{
+				for (int i = 0; i < n; i++)
+				{
+					try
+					{
+						queue.put( i );
+					}
+					catch ( InterruptedException e )
+					{
+						///CLOVER:OFF
+						e.printStackTrace();
+						///CLOVER:ON
+					}
+				}
+			}
+		} ).start();
+		
+		for (int i = 0; i < n; i++)
+			assertEquals( i, queue.get() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void stress2() throws Exception
+	{
+		final CircularQueue<Integer> queue = new CircularQueue<Integer>( 1 );
+		final int n = 1000;
+		
+		new Thread( new Runnable()
+		{
+			public void run()
+			{
+				for (int i = 0; i < n; i++)
+				{
+					try
+					{
+						Thread.sleep( 5 );
+						queue.put( i );
+					}
+					catch ( InterruptedException e )
+					{
+						///CLOVER:OFF
+						e.printStackTrace();
+						///CLOVER:ON
+					}
+				}
+			}
+		} ).start();
+		
+		for (int i = 0; i < n; i++)
+			assertEquals( i, queue.get() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void stress3() throws Exception
+	{
+		final CircularQueue<Integer> queue = new CircularQueue<Integer>( 1 );
+		final int n = 1000;
+		
+		new Thread( new Runnable()
+		{
+			public void run()
+			{
+				for (int i = 0; i < n; i++)
+				{
+					try
+					{
+						queue.put( i );
+					}
+					catch ( InterruptedException e )
+					{
+						///CLOVER:OFF
+						e.printStackTrace();
+						///CLOVER:ON
+					}
+				}
+			}
+		} ).start();
+		
+		for (int i = 0; i < n; i++)
+		{
+			Thread.sleep( 5 );
+			assertEquals( i, queue.get() );
+		}
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void stress4() throws Exception
+	{
+		final CircularQueue<Integer> queue = new CircularQueue<Integer>();
+		
+		// we will setup two threads waiting to get and
+		// then in a single synchronized step put two
+		// items in the queue. the first thread will be
+		// woken to get, and once done the second thread
+		// should be woken by the first.
+		
+		Thread t1 = new Thread( new Runnable()
+		{
+			public void run()
+			{
+				try
+				{
+					assertNotNull( queue.get() );
+				}
+				catch ( InterruptedException e )
+				{
+					// e.printStackTrace();
+				}
+			}
+		}, "t1" );
+		
+		Thread t2 = new Thread( new Runnable()
+		{
+			public void run()
+			{
+				try
+				{
+					assertNotNull( queue.get() );
+				}
+				catch ( InterruptedException e )
+				{
+					// e.printStackTrace();
+				}
+			}
+		}, "t2" );
+
+		t1.start();
+		t2.start();
+		
+		// wait until both threads are waiting on queue...
+		
+		Thread.sleep( 100 );
+		
+		synchronized (queue)
+		{
+			queue.put( 1 );
+			queue.put( 2 );
+		}
+
+		harvest( t1 );
+		harvest( t2 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void stress5() throws Exception
+	{
+		final CircularQueue<Integer> queue = new CircularQueue<Integer>( 3 );
+		
+		// we will setup two threads waiting to put to the queue,
+		// then in a single synchronized step, read two items from
+		// the queue. the first thread will be woken to put, and
+		// once done the second thread should be woken by the first.
+		
+		queue.put( 0 );
+		queue.put( 1 );
+		queue.put( 2 );
+		assertTrue( queue.isFull() );
+		
+		Thread t1 = new Thread( new Runnable()
+		{
+			public void run()
+			{
+				try
+				{
+					assertTrue( queue.put( 3 ) );
+				}
+				catch ( InterruptedException e )
+				{
+					// e.printStackTrace();
+				}
+			}
+		}, "t1" );
+		
+		Thread t2 = new Thread( new Runnable()
+		{
+			public void run()
+			{
+				try
+				{
+					assertTrue( queue.put( 4 ) );
+				}
+				catch ( InterruptedException e )
+				{
+					// e.printStackTrace();
+				}
+			}
+		}, "t2" );
+		
+		t1.start();
+		t2.start();
+		
+		// wait until both threads are waiting on queue...
+		
+		Thread.sleep( 100 );
+		
+		synchronized (queue)
+		{
+			assertNotNull( queue.get() );
+			assertNotNull( queue.get() );
+		}
+
+		harvest( t1 );
+		harvest( t2 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void stress6() throws Exception
+	{
+		final CircularQueue<Integer> queue = new CircularQueue<Integer>( 5 );
+		
+		// start two getters and two putters and let 'em duke it out...
+		
+		Thread t1 = new Thread( new Runnable()
+		{
+			public void run()
+			{
+				try
+				{
+					for (int i = 0; i < 100; i++)
+						assertTrue( queue.put( i ) );
+				}
+				catch ( InterruptedException e )
+				{
+					// e.printStackTrace();
+				}
+			}
+		}, "t1" );
+		
+		Thread t2 = new Thread( new Runnable()
+		{
+			public void run()
+			{
+				try
+				{
+					for (int i = 0; i < 100; i++)
+						assertTrue( queue.put( i ) );
+				}
+				catch ( InterruptedException e )
+				{
+					// e.printStackTrace();
+				}
+			}
+		}, "t2" );
+		
+		Thread t3 = new Thread( new Runnable()
+		{
+			public void run()
+			{
+				try
+				{
+					for (int i = 0; i < 100; i++)
+						assertNotNull( queue.get() );
+				}
+				catch ( InterruptedException e )
+				{
+					// e.printStackTrace();
+				}
+			}
+		}, "t3" );
+		
+		Thread t4 = new Thread( new Runnable()
+		{
+			public void run()
+			{
+				try
+				{
+					for (int i = 0; i < 100; i++)
+						assertNotNull( queue.get() );
+				}
+				catch ( InterruptedException e )
+				{
+					// e.printStackTrace();
+				}
+			}
+		}, "t4" );
+		
+		t1.start();
+		t2.start();
+		t3.start();
+		t4.start();
+
+		harvest( t1 );
+		harvest( t2 );
+		harvest( t3 );
+		harvest( t4 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void harvest1() throws Exception
+	{
+		Thread t = new Thread( new Runnable()
+		{
+			public void run()
+			{
+				// nothing to do.
+			}
+		}, "t" );
+		t.start();
+		harvest( t );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = TimeoutException.class )
+	public void harvest2() throws Exception
+	{
+		Thread t = new Thread( new Runnable()
+		{
+			public void run()
+			{
+				try
+				{
+					Thread.sleep( 10000 );
+				}
+				catch ( InterruptedException e )
+				{
+					// ignore.
+				}
+			}
+		}, "t" );
+		t.start();
+		harvest( t );
+	}
+	
+	private void harvest( Thread t ) throws Exception
+	{
+		t.join( 1000 );
+		if (t.isAlive())
+		{
+			t.interrupt();
+			throw new TimeoutException( t.getName()+" is stuck" );
+		}
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/TestFlexBuffer.java b/util/src/test/java/org/apache/etch/util/TestFlexBuffer.java
new file mode 100644
index 0000000..c156917
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/TestFlexBuffer.java
@@ -0,0 +1,1603 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.EOFException;
+import java.io.IOException;
+
+import org.junit.Test;
+
+/**
+ * Tests FlexBuffer.
+ */
+public class TestFlexBuffer
+{
+	private void checkBuf( FlexBuffer buf, int length, int index, int avail )
+	{
+		assertEquals( "length", length, buf.length() );
+		assertEquals( "index", index, buf.index() );
+		assertEquals( "avail", avail, buf.avail() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void initial1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		checkBuf( buf, 0, 0, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void initial2() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[5] );
+		checkBuf( buf, 5, 0, 5 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void initial3() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[5], 2 );
+		checkBuf( buf, 2, 0, 2 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void initial4() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[5], 1, 3 );
+		checkBuf( buf, 4, 1, 3 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void setLength0() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.setLength( 0 );
+		checkBuf( buf, 0, 0, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void setLength1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.setLength( 1 );
+		checkBuf( buf, 1, 0, 1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void setLength2() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.setLength( 2 );
+		checkBuf( buf, 2, 0, 2 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void setLength3() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.setLength( 2 );
+		buf.setLength( 0 );
+		checkBuf( buf, 0, 0, 0 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void setLength4() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.setLength( -1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void setIndex0() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.setIndex( 0 );
+		checkBuf( buf, 0, 0, 0 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void setIndex1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.setIndex( 1 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void setIndex2() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.setIndex( -1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void setIndex3() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.setLength( 5 );
+		buf.setIndex( 1 );
+		checkBuf( buf, 5, 1, 4 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void setIndex4() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.setLength( 5 );
+		buf.setIndex( 4 );
+		checkBuf( buf, 5, 4, 1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void setIndex5() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.setLength( 5 );
+		buf.setIndex( 5 );
+		checkBuf( buf, 5, 5, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void setIndex6() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.setLength( 5 );
+		buf.setIndex( 5 );
+		buf.setLength( 0 );
+		checkBuf( buf, 0, 0, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void setIndex7() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.setLength( 5 );
+		buf.setIndex( 5 );
+		buf.setLength( 2 );
+		checkBuf( buf, 2, 2, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void reset() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.setLength( 2 );
+		buf.setIndex( 1 );
+		buf.reset();
+		checkBuf( buf, 0, 0, 0 );
+	}
+
+	// ------------------------------------------------------
+	// cases for put( int ):
+	// put once or twice (the put 0 case has already been tested).
+
+	/** @throws Exception */
+	@Test
+	public void put1a() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.put( 1 );
+		checkBuf( buf, 1, 1, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void put1b() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.put( 1 );
+		buf.put( 2 );
+		checkBuf( buf, 2, 2, 0 );
+	}
+
+	// ------------------------------------------------------
+	// cases for put( byte[] buf ):
+	// buf.length = null, 0, 1, 2
+
+	private void testPutBytes( int bufLen )
+		throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.put( 1 );
+		buf.put( bufLen >= 0 ? new byte[bufLen] : null );
+		checkBuf( buf, bufLen+1, bufLen+1, 0 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = NullPointerException.class )
+	public void put2a() throws Exception
+	{
+		testPutBytes( -1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void put2b() throws Exception
+	{
+		testPutBytes( 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void put2c() throws Exception
+	{
+		testPutBytes( 1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void put2d() throws Exception
+	{
+		testPutBytes( 2 );
+	}
+	
+	// ------------------------------------------------------
+	// cases for put( byte[] buf, int off, int len ):
+	// buf.length, off, len // failure reason
+	// --- group 3:
+	// null, 0, 0 // fail (buf is null)
+	// null, 0, 1 // fail (buf is null)
+	// null, 1, 0 // fail (buf is null)
+	// --- group 4:
+	// 0, 0, 0
+	// 0, 0, 1 // fail (off+len > buf.length)
+	// 0, 1, 0 // fail (off > buf.length)
+	// --- group 5:
+	// 1, 0, 0
+	// 1, 0, 1
+	// 1, 0, 2 // fail (off+len > buf.length)
+	// 1, 1, 0
+	// 1, 1, 1 // fail (off+len > buf.length)
+	// 1, 1, 2 // fail (off+len > buf.length)
+	// 1, 2, 0 // fail (off > buf.length)
+	// 1, 2, 1 // fail (off > buf.length)
+	// 1, 2, 2 // fail (off > buf.length)
+	// --- group 6:
+	// 2, 0, 0
+	// 2, 0, 1
+	// 2, 0, 2
+	// 2, 1, 0
+	// 2, 1, 1
+	// 2, 1, 2 // fail (off+len > buf.length)
+	// 2, 2, 0
+	// 2, 2, 1 // fail (off+len > buf.length)
+	// 2, 2, 2 // fail (off+len > buf.length)
+	
+	private void testPutBytesOffLen( int bufLen, int offset, int length )
+		throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.put( 1 );
+		buf.put( bufLen >= 0 ? new byte[bufLen] : null, offset, length );
+		checkBuf( buf, length+1, length+1, 0 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = NullPointerException.class )
+	public void put3a() throws Exception
+	{
+		testPutBytesOffLen( -1, 0, 0 ); // fail (buf is null)
+	}
+
+	/** @throws Exception */
+	@Test( expected = NullPointerException.class )
+	public void put3b() throws Exception
+	{
+		testPutBytesOffLen( -1, 0, 1 ); // fail (buf is null)
+	}
+
+	/** @throws Exception */
+	@Test( expected = NullPointerException.class )
+	public void put3c() throws Exception
+	{
+		testPutBytesOffLen( -1, 1, 0 ); // fail (buf is null)
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void put4a() throws Exception
+	{
+		testPutBytesOffLen( 0, 0, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put4b() throws Exception
+	{
+		testPutBytesOffLen( 0, 0, 1 ); // fail (off+len > buf.length)
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put4c() throws Exception
+	{
+		testPutBytesOffLen( 0, 1, 0 ); // fail (off > buf.length)
+	}
+
+	/** @throws Exception */
+	@Test
+	public void put5a() throws Exception
+	{
+		testPutBytesOffLen( 1, 0, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void put5b() throws Exception
+	{
+		testPutBytesOffLen( 1, 0, 1 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put5c() throws Exception
+	{
+		testPutBytesOffLen( 1, 0, 2 ); // fail (off+len > buf.length)
+	}
+
+	/** @throws Exception */
+	@Test
+	public void put5d() throws Exception
+	{
+		testPutBytesOffLen( 1, 1, 0 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put5e() throws Exception
+	{
+		testPutBytesOffLen( 1, 1, 1 ); // fail (off+len > buf.length)
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put5f() throws Exception
+	{
+		testPutBytesOffLen( 1, 1, 2 ); // fail (off+len > buf.length)
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put5g() throws Exception
+	{
+		testPutBytesOffLen( 1, 2, 0 ); // fail (off > buf.length)
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put5h() throws Exception
+	{
+		testPutBytesOffLen( 1, 2, 1 ); // fail (off > buf.length)
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put5i() throws Exception
+	{
+		testPutBytesOffLen( 1, 2, 2 ); // fail (off > buf.length)
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void put6a() throws Exception
+	{
+		testPutBytesOffLen( 2, 0, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void put6b() throws Exception
+	{
+		testPutBytesOffLen( 2, 0, 1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void put6c() throws Exception
+	{
+		testPutBytesOffLen( 2, 0, 2 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void put6d() throws Exception
+	{
+		testPutBytesOffLen( 2, 1, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void put6e() throws Exception
+	{
+		testPutBytesOffLen( 2, 1, 1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put6f() throws Exception
+	{
+		testPutBytesOffLen( 2, 1, 2 ); // fail (off+len > buf.length)
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void put6g() throws Exception
+	{
+		testPutBytesOffLen( 2, 2, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put6h() throws Exception
+	{
+		testPutBytesOffLen( 2, 2, 1 ); // fail (off+len > buf.length)
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void put6i() throws Exception
+	{
+		testPutBytesOffLen( 2, 2, 2 ); // fail (off+len > buf.length)
+	}
+
+	// ------------------------------------------------------
+	// cases for put(int), get():
+	// put 0, get 0. // already tested above
+	// put 0, get 1. // fails with EOFException
+	// put 1, get 0.
+	// put 1, get 1.
+	// put 1, get 2. // fails with EOFException
+	// put 2, get 0.
+	// put 2, get 1.
+	// put 2, get 2.
+	// put 2, get 3. // fails with EOFException
+	// put 10000, get 10000.
+	
+	// just like above, putting byte array instead
+	// just like above, getting byte array instead.
+	// just like above, putting and getting byte array.
+	
+	private void testPutGet( int nPuts, int nGets )
+		throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		
+		for (int i = 0; i < nPuts; i++)
+			buf.put( i );
+		
+		buf.setIndex( 0 );
+		
+		for (int i = 0; i < nGets; i++)
+			assertEquals( (byte) i, (byte) buf.get() );
+		
+		checkBuf( buf, nPuts, nGets, nPuts-nGets );
+	}
+	
+	private void testPutBytesGet( int nPuts, int nGets )
+		throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		
+		byte[] buffer = new byte[nPuts];
+		for (int i = 0; i < nPuts; i++)
+			buffer[i] = (byte) i;
+		
+		buf.put(  buffer );
+		buf.setIndex( 0 );
+		
+		for (int i = 0; i < nGets; i++)
+			assertEquals( (byte) i, (byte) buf.get() );
+		
+		checkBuf( buf, nPuts, nGets, nPuts-nGets );
+	}
+	
+	private void testPutGetBytes( int nPuts, int nGets )
+		throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		
+		for (int i = 0; i < nPuts; i++)
+			buf.put( i );
+		
+		buf.setIndex( 0 );
+		
+		byte[] buffer = new byte[nGets];
+		int n = buf.get( buffer );
+		assertEquals( Math.min( nPuts, nGets ), n );
+		
+		for (int i = 0; i < n; i++)
+			assertEquals( (byte) i, buffer[i] );
+		
+		checkBuf( buf, nPuts, n, nPuts-n );
+	}
+	
+	private void testPutBytesGetBytes( int nPuts, int nGets )
+		throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		
+		byte[] buffer = new byte[nPuts];
+		for (int i = 0; i < nPuts; i++)
+			buffer[i] = (byte) i;
+
+		buf.put(  buffer );
+		buf.setIndex( 0 );
+		
+		buffer = new byte[nGets];
+		int n = buf.get( buffer );
+		assertEquals( Math.min( nPuts, nGets ), n );
+		
+		for (int i = 0; i < n; i++)
+			assertEquals( (byte) i, buffer[i] );
+		
+		checkBuf( buf, nPuts, n, nPuts-n );
+	}
+
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void get1a() throws Exception
+	{
+		testPutGet( 0, 1 ); // fails with EOFException
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get1b() throws Exception
+	{
+		testPutGet( 1, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get1c() throws Exception
+	{
+		testPutGet( 1, 1 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void get1d() throws Exception
+	{
+		testPutGet( 1, 2 ); // fails with EOFException
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get1e() throws Exception
+	{
+		testPutGet( 2, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get1f() throws Exception
+	{
+		testPutGet( 2, 1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get1g() throws Exception
+	{
+		testPutGet( 2, 2 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void get1h() throws Exception
+	{
+		testPutGet( 2, 3 ); // fails with EOFException
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get1i() throws Exception
+	{
+		testPutGet( 10000, 9995 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get1j() throws Exception
+	{
+		testPutGet( 10000, 10000 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get1k() throws Exception
+	{
+		testPutGet( 100000, 100000 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void get2a() throws Exception
+	{
+		testPutBytesGet( 0, 1 ); // fails with EOFException
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get2b() throws Exception
+	{
+		testPutBytesGet( 1, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get2c() throws Exception
+	{
+		testPutBytesGet( 1, 1 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void get2d() throws Exception
+	{
+		testPutBytesGet( 1, 2 ); // fails with EOFException
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get2e() throws Exception
+	{
+		testPutBytesGet( 2, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get2f() throws Exception
+	{
+		testPutBytesGet( 2, 1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get2g() throws Exception
+	{
+		testPutBytesGet( 2, 2 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void get2h() throws Exception
+	{
+		testPutBytesGet( 2, 3 ); // fails with EOFException
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get2i() throws Exception
+	{
+		testPutBytesGet( 10000, 9995 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get2j() throws Exception
+	{
+		testPutBytesGet( 10000, 10000 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get2k() throws Exception
+	{
+		testPutBytesGet( 100000, 100000 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void get3a() throws Exception
+	{
+		testPutGetBytes( 0, 1 ); // fails with EOFException
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get3b() throws Exception
+	{
+		testPutGetBytes( 1, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get3c() throws Exception
+	{
+		testPutGetBytes( 1, 1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get3d() throws Exception
+	{
+		testPutGetBytes( 1, 2 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get3e() throws Exception
+	{
+		testPutGetBytes( 2, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get3f() throws Exception
+	{
+		testPutGetBytes( 2, 1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get3g() throws Exception
+	{
+		testPutGetBytes( 2, 2 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get3h() throws Exception
+	{
+		testPutGetBytes( 2, 3 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get3i() throws Exception
+	{
+		testPutGetBytes( 10000, 9995 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get3j() throws Exception
+	{
+		testPutGetBytes( 10000, 10000 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get3k() throws Exception
+	{
+		testPutGetBytes( 100000, 100000 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void get4a() throws Exception
+	{
+		testPutBytesGetBytes( 0, 1 ); // fails with EOFException
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get4b() throws Exception
+	{
+		testPutBytesGetBytes( 1, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get4c() throws Exception
+	{
+		testPutBytesGetBytes( 1, 1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get4d() throws Exception
+	{
+		testPutBytesGetBytes( 1, 2 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get4e() throws Exception
+	{
+		testPutBytesGetBytes( 2, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get4f() throws Exception
+	{
+		testPutBytesGetBytes( 2, 1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get4g() throws Exception
+	{
+		testPutBytesGetBytes( 2, 2 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get4h() throws Exception
+	{
+		testPutBytesGetBytes( 2, 3 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get4i() throws Exception
+	{
+		testPutBytesGetBytes( 10000, 9995 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get4j() throws Exception
+	{
+		testPutBytesGetBytes( 10000, 10000 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get4k() throws Exception
+	{
+		testPutBytesGetBytes( 100000, 100000 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get5a() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 1, 2, 3 } );
+		assertEquals( 1, buf.get() );
+		assertEquals( 2, buf.get() );
+		assertEquals( 3, buf.get() );
+		checkBuf( buf, 3, 3, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get5b() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 1, 2, 3 }, 2 );
+		assertEquals( 1, buf.get() );
+		assertEquals( 2, buf.get() );
+		checkBuf( buf, 2, 2, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get5c() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 1, 2, 3, 4, 5 }, 1, 2 );
+		assertEquals( 2, buf.get() );
+		assertEquals( 3, buf.get() );
+		checkBuf( buf, 3, 3, 0 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void get6() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 5, 6, 7, 8 } );
+		byte[] buffer = new byte[] { 11, 12, 13, 14, 15 };
+		buf.get( buffer, 1, 3 );
+		assertEquals( (byte) 11, buffer[0] );
+		assertEquals( (byte) 5, buffer[1] );
+		assertEquals( (byte) 6, buffer[2] );
+		assertEquals( (byte) 7, buffer[3] );
+		assertEquals( (byte) 15, buffer[4] );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void compact() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 1, 2, 3, 4, 5 }, 1, 3 );
+		buf.compact();
+		checkBuf( buf, 3, 0, 3 );
+		assertEquals( 2, buf.get() );
+		assertEquals( 3, buf.get() );
+		assertEquals( 4, buf.get() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void getByte1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 127, 1, 0, -1, -128 } );
+		assertEquals( (byte) 127, buf.getByte() );
+		assertEquals( (byte) 1, buf.getByte() );
+		assertEquals( (byte) 0, buf.getByte() );
+		assertEquals( (byte) -1, buf.getByte() );
+		assertEquals( (byte) -128, buf.getByte() );
+		checkBuf( buf, 5, 5, 0 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void getByte2() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.getByte(); // fails with EOFException
+	}
+
+	/** @throws Exception */
+	@Test
+	public void getShort1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 1, 2, -1, -2 } );
+		assertEquals( (short) 0x0102, buf.getShort() );
+		assertEquals( (short) 0xfffe, buf.getShort() );
+		checkBuf( buf, 4, 4, 0 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void getShort2() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.getShort(); // fails with EOFException
+	}
+
+	/** @throws Exception */
+	@Test
+	public void getInt1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 1, 2, 3, 4, -1, -2, -3, -4 } );
+		assertEquals( 0x01020304, buf.getInt() );
+		assertEquals( 0xfffefdfc, buf.getInt() );
+		checkBuf( buf, 8, 8, 0 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void getInt2() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.getInt(); // fails with EOFException
+	}
+
+	/** @throws Exception */
+	@Test
+	public void getLong1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			1, 2, 3, 4, 5, 6, 7, 8,
+			-1, -2, -3, -4, -5, -6, -7, -8
+		} );
+		
+		assertEquals( 0x0102030405060708L, buf.getLong() );
+		assertEquals( 0xfffefdfcfbfaf9f8L, buf.getLong() );
+		checkBuf( buf, 16, 16, 0 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void getLong2() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.getLong(); // fails with EOFException
+	}
+
+	/** @throws Exception */
+	@Test
+	public void getFloat1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			0, 0, 0, 0
+			, 63, -128, 0, 0
+			, 83, -113, 48, -37
+			, 100, -98, -112, -120
+			, 117, -120, 20, 25
+			, -65, -128, 0, 0
+			, -45, -113, 48, -37
+			, -28, -98, -112, -120
+			, -11, -120, 20, 25
+			, 50, 83, 79, -7
+			, 34, 44, -87, 90
+			, 17, -38, -85, 115
+			, -78, 83, 79, -7
+			, -94, 44, -87, 90
+			, -111, -38, -85, 115
+		} );
+
+		assertEquals( 0.0f, buf.getFloat() );
+		assertEquals( 1.0f, buf.getFloat() );
+		assertEquals( 123e10f, buf.getFloat() );
+		assertEquals( 234e20f, buf.getFloat() );
+		assertEquals( 345e30f, buf.getFloat() );
+		assertEquals( -1.0f, buf.getFloat() );
+		assertEquals( -123e10f, buf.getFloat() );
+		assertEquals( -234e20f, buf.getFloat() );
+		assertEquals( -345e30f, buf.getFloat() );
+		assertEquals( 123e-10f, buf.getFloat() );
+		assertEquals( 234e-20f, buf.getFloat() );
+		assertEquals( 345e-30f, buf.getFloat() );
+		assertEquals( -123e-10f, buf.getFloat() );
+		assertEquals( -234e-20f, buf.getFloat() );
+		assertEquals( -345e-30f, buf.getFloat() );
+		checkBuf( buf, 15*4, 15*4, 0 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void getFloat2() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.getFloat(); // fails with EOFException
+	}
+
+	/** @throws Exception */
+	@Test
+	public void getDouble1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			0, 0, 0, 0, 0, 0, 0, 0
+			, 63, -16, 0, 0, 0, 0, 0, 0
+			, 66, 113, -26, 27, 104, -64, 0, 0
+			, 85, 48, -73, 88, 68, 89, -6, -80
+			, 105, -4, 43, 112, 122, -31, 67, -116
+			, -65, -16, 0, 0, 0, 0, 0, 0
+			, -62, 113, -26, 27, 104, -64, 0, 0
+			, -43, 48, -73, 88, 68, 89, -6, -80
+			, -23, -4, 43, 112, 122, -31, 67, -116
+			, 62, 74, 105, -1, 27, 85, 80, 81
+			, 43, -87, -105, 64, -36, -23, -48, -66
+			, 22, -16, -127, 73, 111, 91, -75, -29
+			, -66, 74, 105, -1, 27, 85, 80, 81
+			, -85, -87, -105, 64, -36, -23, -48, -66
+			, -106, -16, -127, 73, 111, 91, -75, -29
+		});
+				
+		assertEquals( 0.0,              buf.getDouble());
+		
+		assertEquals( 1.0,              buf.getDouble());
+		assertEquals( 123e10,           buf.getDouble());
+		assertEquals( 234e100,          buf.getDouble());
+		assertEquals( 345e200,          buf.getDouble());
+		
+		assertEquals( -1.0,             buf.getDouble());
+		assertEquals( -123e10,          buf.getDouble());
+		assertEquals( -234e100,         buf.getDouble());
+		assertEquals( -345e200,         buf.getDouble());
+
+		assertEquals( 123e-10,          buf.getDouble());
+		assertEquals( 234e-100,         buf.getDouble());
+		assertEquals( 345e-200,         buf.getDouble());
+
+		assertEquals( -123e-10,          buf.getDouble());
+		assertEquals( -234e-100,         buf.getDouble());
+		assertEquals( -345e-200,         buf.getDouble());
+
+		checkBuf( buf, 15*8, 15*8, 0 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void getDouble2() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.getDouble(); // fails with EOFException
+	}
+
+	/** @throws Exception */
+	@Test
+	public void getFully1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 1, 2, 3, 4, 5, 6 } );
+		byte[] b = new byte[3];
+		buf.getFully( b );
+		assertEquals( (byte) 1, b[0] );
+		assertEquals( (byte) 2, b[1] );
+		assertEquals( (byte) 3, b[2] );
+		buf.getFully( b );
+		assertEquals( (byte) 4, b[0] );
+		assertEquals( (byte) 5, b[1] );
+		assertEquals( (byte) 6, b[2] );
+		checkBuf( buf, 6, 6, 0 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void getFully2() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 1, 2 } );
+		byte[] b = new byte[3];
+		buf.getFully( b ); // fails with EOFException
+	}
+	
+	// ------------------------------------------------------
+	// cases for FlexBuffer put( FlexBuffer ):
+	// put, put FlexBuffer with valid buffer
+    // put, put Flexbuffer to a Flexbuffer approaching max length, fails with IOException.
+	
+	/** @throws Exception */
+	@Test
+	public void putFlexBuffer1() throws Exception
+	{
+		FlexBuffer buf0 = new FlexBuffer( new byte[] { 1, 2 } );
+		FlexBuffer buf = new FlexBuffer();
+		buf.put( buf0 );
+		checkBuf( buf, buf0.length(), buf0.length(), 0 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IOException.class )
+	public void putFlexBuffer2() throws Exception
+	{
+		FlexBuffer buf0 = new FlexBuffer( new byte[] { 1, 2 } );
+		
+		int max = 4*1024*1024;
+		FlexBuffer buf = new FlexBuffer( new byte[max] );
+		buf.setIndex(max);
+		buf.put( buf0 );
+	}
+		
+	// ------------------------------------------------------
+	// cases for FlexBuffer put( FlexBuffer, int ):
+	// put, put FlexBuffer with length larger than available bytes, fails with IllegalArgumentException
+	// put, put FlexBuffer with valid length value
+    // put, put Flexbuffer to a Flexbuffer approaching max length, fails with IOException.
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void putFlexBuffer3() throws Exception
+	{
+		FlexBuffer buf0 = new FlexBuffer( new byte[] { 1, 2 } );
+		
+		FlexBuffer buf = new FlexBuffer();
+		buf.setIndex(0);
+		buf.put( buf0, 3);
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void putFlexBuffer4() throws Exception
+	{
+		FlexBuffer buf0 = new FlexBuffer( new byte[] { 1, 2 } );
+		FlexBuffer buf = new FlexBuffer();
+		buf.put( buf0, 1 );
+		checkBuf( buf, 1, 1, 0 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IOException.class )
+	public void putFlexBuffer5() throws Exception
+	{
+		FlexBuffer buf0 = new FlexBuffer( new byte[] { 1, 2 } );
+		int max = 4*1024*1024;
+		FlexBuffer buf = new FlexBuffer( new byte[max] );
+		buf.setIndex(max);
+		buf.put( buf0, 1);
+	}
+	
+	// ------------------------------------------------------
+	// cases for void putByte( byte ):
+	// putByte, put byte value and expect getByte to return matched value.
+    // putByte to a Flexbuffer approaching max length, fails with IOException.
+	
+	/** @throws Exception */
+	@Test
+	public void putByte1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.putByte( (byte) 0x01 );
+		checkBuf( buf, 1, 1, 0 );
+		buf.setIndex(0);
+		assertEquals( (byte) 0x01, buf.getByte() );
+		checkBuf( buf, 1, 1, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IOException.class )
+	public void putByte2() throws Exception
+	{
+		int max = 4*1024*1024;
+		FlexBuffer buf = new FlexBuffer( new byte[max] );
+		buf.setIndex(max);
+		buf.putByte( (byte) 0x01 );
+	}
+	
+	// ------------------------------------------------------
+	// cases for void putDouble( double ):
+	// putDouble, put Double and expect getDouble to return matched value.
+    // putDouble to a Flexbuffer approaching max length, fails with IOException.
+	
+	/** @throws Exception */
+	@Test
+	public void putDouble1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		// some reasonable values
+		buf.putDouble( 0.0 );
+		buf.putDouble( 1.0 );
+		buf.putDouble( 123e10 );
+		buf.putDouble( 234e100 );
+		buf.putDouble( 345e200 );
+		// negative of some reasonable values
+		buf.putDouble( -1.0 );
+		buf.putDouble( -123e10 );
+		buf.putDouble( -234e100 );
+		buf.putDouble( -345e200 );
+		// tiny
+		buf.putDouble( 123e-10 );
+		buf.putDouble( 234e-100 );
+		buf.putDouble( 345e-200 );
+		// tiny and negative
+		buf.putDouble( -123e-10 );
+		buf.putDouble( -234e-100 );
+		buf.putDouble( -345e-200 );
+		checkBuf( buf, 15*8, 15*8, 0 );
+		
+		// verify we can reliably read the data we wrote.
+		
+		buf.setIndex( 0 );
+		assertEquals( 0.0, buf.getDouble() );
+		assertEquals( 1.0, buf.getDouble() );
+		assertEquals( 123e10, buf.getDouble() );
+		assertEquals( 234e100, buf.getDouble() );
+		assertEquals( 345e200, buf.getDouble() );
+		assertEquals( -1.0, buf.getDouble() );
+		assertEquals( -123e10, buf.getDouble() );
+		assertEquals( -234e100, buf.getDouble() );
+		assertEquals( -345e200, buf.getDouble() );
+		assertEquals( 123e-10, buf.getDouble() );
+		assertEquals( 234e-100, buf.getDouble() );
+		assertEquals( 345e-200, buf.getDouble() );
+		assertEquals( -123e-10, buf.getDouble() );
+		assertEquals( -234e-100, buf.getDouble() );
+		assertEquals( -345e-200, buf.getDouble() );
+		checkBuf( buf, 15*8, 15*8, 0 );
+		
+		// uncomment this code to get a dump of the actual
+		// bytes for the above data.
+		
+//		buf.setIndex( 0 );
+//		int i = 0;
+//		while (buf.avail() > 0)
+//		{
+//			System.out.printf( i == 0 ? "%d" : ", %d", buf.getByte() );
+//			if (i++ % 8 == 7)
+//				System.out.println();
+//		}
+		
+		byte[] expected =
+		{
+			0, 0, 0, 0, 0, 0, 0, 0
+			, 63, -16, 0, 0, 0, 0, 0, 0
+			, 66, 113, -26, 27, 104, -64, 0, 0
+			, 85, 48, -73, 88, 68, 89, -6, -80
+			, 105, -4, 43, 112, 122, -31, 67, -116
+			, -65, -16, 0, 0, 0, 0, 0, 0
+			, -62, 113, -26, 27, 104, -64, 0, 0
+			, -43, 48, -73, 88, 68, 89, -6, -80
+			, -23, -4, 43, 112, 122, -31, 67, -116
+			, 62, 74, 105, -1, 27, 85, 80, 81
+			, 43, -87, -105, 64, -36, -23, -48, -66
+			, 22, -16, -127, 73, 111, 91, -75, -29
+			, -66, 74, 105, -1, 27, 85, 80, 81
+			, -85, -87, -105, 64, -36, -23, -48, -66
+			, -106, -16, -127, 73, 111, 91, -75, -29
+		};
+		
+		buf.setIndex( 0 );
+		byte[] actual = buf.getAvailBytes();
+		
+		bytesAssertEquals( expected, actual );
+	}
+	
+	private void bytesAssertEquals( byte[] expected, byte[] actual )
+	{
+		assertEquals( expected.length, actual.length );
+		for (int i = 0; i < expected.length; i++)
+			assertEquals( "expected["+i+"]/actual["+i+"]", expected[i], actual[i] );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IOException.class )
+	public void putDouble2() throws Exception
+	{
+		int max = 4*1024*1024;
+		FlexBuffer buf = new FlexBuffer( new byte[max] );
+		buf.setIndex( max );
+		buf.putDouble( 0.0 );
+	}
+		
+	// ------------------------------------------------------
+	// cases for void putFloat( float ):
+	// putFloat, put Float and expect getFloat to return matched value.
+    // putFloat to a Flexbuffer approaching max length, fails with IOException.
+	
+	/** @throws Exception */
+	@Test
+	public void putFloat1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		// some reasonable values
+		buf.putFloat( 0.0f );
+		buf.putFloat( 1.0f );
+		buf.putFloat( 123e10f );
+		buf.putFloat( 234e20f );
+		buf.putFloat( 345e30f );
+		// negative of some reasonable values
+		buf.putFloat( -1.0f );
+		buf.putFloat( -123e10f );
+		buf.putFloat( -234e20f );
+		buf.putFloat( -345e30f );
+		// tiny
+		buf.putFloat( 123e-10f );
+		buf.putFloat( 234e-20f );
+		buf.putFloat( 345e-30f );
+		// tiny and negative
+		buf.putFloat( -123e-10f );
+		buf.putFloat( -234e-20f );
+		buf.putFloat( -345e-30f );
+		checkBuf( buf, 15*4, 15*4, 0 );
+		
+		// verify we can reliably read the data we wrote.
+		
+		buf.setIndex( 0 );
+		assertEquals( 0.0f, buf.getFloat() );
+		assertEquals( 1.0f, buf.getFloat() );
+		assertEquals( 123e10f, buf.getFloat() );
+		assertEquals( 234e20f, buf.getFloat() );
+		assertEquals( 345e30f, buf.getFloat() );
+		assertEquals( -1.0f, buf.getFloat() );
+		assertEquals( -123e10f, buf.getFloat() );
+		assertEquals( -234e20f, buf.getFloat() );
+		assertEquals( -345e30f, buf.getFloat() );
+		assertEquals( 123e-10f, buf.getFloat() );
+		assertEquals( 234e-20f, buf.getFloat() );
+		assertEquals( 345e-30f, buf.getFloat() );
+		assertEquals( -123e-10f, buf.getFloat() );
+		assertEquals( -234e-20f, buf.getFloat() );
+		assertEquals( -345e-30f, buf.getFloat() );
+		checkBuf( buf, 15*4, 15*4, 0 );
+		
+		// uncomment this code to get a dump of the actual
+		// bytes for the above data.
+		
+//		buf.setIndex( 0 );
+//		int i = 0;
+//		while (buf.avail() > 0)
+//		{
+//			System.out.printf( i == 0 ? "%d" : ", %d", buf.getByte() );
+//			if (i++ % 8 == 7)
+//				System.out.println();
+//		}
+		
+		byte[] expected =
+		{
+			0, 0, 0, 0
+			, 63, -128, 0, 0
+			, 83, -113, 48, -37
+			, 100, -98, -112, -120
+			, 117, -120, 20, 25
+			, -65, -128, 0, 0
+			, -45, -113, 48, -37
+			, -28, -98, -112, -120
+			, -11, -120, 20, 25
+			, 50, 83, 79, -7
+			, 34, 44, -87, 90
+			, 17, -38, -85, 115
+			, -78, 83, 79, -7
+			, -94, 44, -87, 90
+			, -111, -38, -85, 115
+		};
+		
+		buf.setIndex( 0 );
+		byte[] actual = buf.getAvailBytes();
+		
+		bytesAssertEquals( expected, actual );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IOException.class )
+	public void putFloat2() throws Exception
+	{
+		int max = 4*1024*1024;
+		FlexBuffer buf = new FlexBuffer( new byte[max] );
+		buf.setIndex(max);
+		buf.putFloat( 0.0f );
+	}
+	
+	// ------------------------------------------------------
+	// cases for void putInt( int ):
+	// putInt, put Int and expect getInt to return matched value.
+    // putInt to a Flexbuffer approaching max length, fails with IOException.
+	
+	/** @throws Exception */
+	@Test
+	public void putInt1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.putInt( Integer.MAX_VALUE );
+		checkBuf( buf, 4, 4, 0 );
+		buf.setIndex(0);
+		assertEquals( Integer.MAX_VALUE, buf.getInt() );
+		checkBuf( buf, 4, 4, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IOException.class )
+	public void putInt2() throws Exception
+	{
+		int max = 4*1024*1024;
+		FlexBuffer buf = new FlexBuffer( new byte[max] );
+		buf.setIndex(max);
+		buf.putInt( Integer.MIN_VALUE );
+	}
+		
+	// ------------------------------------------------------
+	// cases for void putLong( long ):
+	// putLong, put Long and expect getLong to return matched value.
+    // putShort to a Flexbuffer approaching max length, fails with IOException.
+	
+	/** @throws Exception */
+	@Test
+	public void putLong1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.putLong( Long.MAX_VALUE );
+		checkBuf( buf, 8, 8, 0 );
+		buf.setIndex(0);
+		assertEquals( Long.MAX_VALUE, buf.getLong() );
+		checkBuf( buf, 8, 8, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IOException.class )
+	public void putLong2() throws Exception
+	{
+		int max = 4*1024*1024;
+		FlexBuffer buf = new FlexBuffer( new byte[max] );
+		buf.setIndex(max);
+		buf.putLong( Long.MIN_VALUE );
+	}
+		
+	// ------------------------------------------------------
+	// cases for void putShort( short ):
+	// putShort, put short and expect getShort to return matched value.
+    // putShort to a Flexbuffer approaching max length, fails with IOException.
+	
+	/** @throws Exception */
+	@Test
+	public void putShort1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.putShort( Short.MAX_VALUE );
+		checkBuf( buf, 2, 2, 0 );
+		buf.setIndex(0);
+		assertEquals( Short.MAX_VALUE, buf.getShort() );
+		checkBuf( buf, 2, 2, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IOException.class )
+	public void putShort2() throws Exception
+	{
+		int max = 4*1024*1024;
+		FlexBuffer buf = new FlexBuffer( new byte[max] );
+		buf.setIndex(max);
+		buf.putShort( (short) 1 );
+	}
+		
+	// ------------------------------------------------------
+	// cases for FlexBuffer skip( int, boolean ):
+	// skip length < 0, put = false.  				// fails with illegal argument
+	// skip length > buffer length, put = false.  	// fails with EOFException
+	// skip length = 0, put = false.
+	// skip length = buffer length, put = false.
+	// skip length < buffer length, put = false.
+	// skip length > buffer length, put = true.
+	// skip length < buffer length, put = true.
+    // skip length = max buffer length, put = true.	// fails with IOException
+		
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void skip1() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.skip(-1, false);
+	}
+	
+	/** @throws Exception */
+	@Test( expected = EOFException.class )
+	public void skip2() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 1, 2 } );
+		buf.skip(3, false);
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void skip3() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer();
+		buf.skip(0, false);
+		checkBuf( buf, 0, 0, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void skip4() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 1, 2 } );
+		buf.skip(2, false);
+		checkBuf( buf, 2, 2, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void skip5() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 1, 2 } );
+		buf.skip(1, false);
+		checkBuf( buf, 2, 1, 1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void skip6() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 1, 2 } );
+		buf.skip(1, true);
+		checkBuf( buf, 2, 1, 1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void skip7() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 1, 2 } );
+		buf.skip(5, true);
+		checkBuf( buf, 5, 5, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IOException.class )
+	public void skip8() throws Exception
+	{
+		FlexBuffer buf = new FlexBuffer( new byte[] { 1, 2 } );
+		int max = 4*1024*1024;
+		buf.skip(max+1, true);
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/TestHelp.java b/util/src/test/java/org/apache/etch/util/TestHelp.java
new file mode 100644
index 0000000..ddea1ab
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/TestHelp.java
@@ -0,0 +1,180 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+
+/**
+ * Help for junit tests.
+ */
+public class TestHelp
+{
+	/** @throws Exception */
+	@Test
+	public void testRelError1() throws Exception
+	{
+		assertRelError( 10, 9, .11 );
+		assertRelError( 10, 11, .14 );
+		assertRelError( 20, 19, .07 );
+		assertRelError( 19, 23, .22 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = AssertionError.class )
+	public void testRelError2() throws Exception
+	{
+		assertRelError( 9, 8, .1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = AssertionError.class )
+	public void testRelError3() throws Exception
+	{
+		assertRelError( 9, 10, .1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void testAbsError1() throws Exception
+	{
+		assertAbsError( 11, 15, 4 );
+		assertAbsError( 15, 10, 5 );
+		assertAbsError( 5, 3, 2 );
+		assertAbsError( 4, 7, 3 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = AssertionError.class )
+	public void testAbsError2() throws Exception
+	{
+		assertAbsError( 11, 15, 3 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = AssertionError.class )
+	public void testAbsError3() throws Exception
+	{
+		assertAbsError( 19, 15, 3 );
+	}
+	
+	/**
+	 * Creates a thread to delay running something.
+	 * @param delay
+	 * @param runnable
+	 * @return the thread which is not started.
+	 */
+	public static Thread delay( final int delay, final DelayRunnable runnable )
+	{
+		Thread t = new Thread( new Runnable()
+		{
+			public void run()
+			{
+				try
+				{
+					Thread.sleep( delay );
+					runnable.run();
+				}
+				catch ( Exception e )
+				{
+					e.printStackTrace();
+				}
+			}
+		} );
+		return t;
+	}
+
+	/**
+	 * Creates a thread to delay running something.
+	 * @param delay
+	 * @param runnable
+	 * @return the thread which is started.
+	 */
+	public static Thread delayAndStart( final int delay, final DelayRunnable runnable )
+	{
+		Thread t = delay( delay, runnable );
+		t.start();
+		return t;
+	}
+	
+	/**
+	 * Interface to implement when using delay.
+	 */
+	public interface DelayRunnable
+	{
+		/**
+		 * @throws Exception
+		 */
+		public void run() throws Exception;
+	}
+
+	/**
+	 * Compare doubles with relative error.
+	 * @param expected
+	 * @param actual
+	 * @param maxRelError
+	 * @see #relError(double, double)
+	 */
+	public static void assertRelError( double expected, double actual, double maxRelError )
+	{
+		double relError = relError( expected, actual );
+		if (relError > maxRelError)
+			fail( String.format( "expected: <%f> but was: <%f> relative error: <%f>", expected, actual, relError ) );
+	}
+	
+	/**
+	 * Compare doubles with absolute error.
+	 * @param expected
+	 * @param actual
+	 * @param maxAbsError
+	 * @see #absError(double, double)
+	 */
+	public static void assertAbsError( double expected, double actual, double maxAbsError )
+	{
+		double absError = absError( expected, actual );
+		if (absError > maxAbsError)
+			fail( String.format( "expected: <%f> but was: <%f> absolute error: <%f>", expected, actual, absError ) );
+	}
+	
+	/**
+	 * Computes the relative error between actual and expected.
+	 * @param expected
+	 * @param actual
+	 * @return the relative error absError( expected, actual ) / expected.
+	 * @see #absError(double, double)
+	 */
+	public static double relError( double expected, double actual )
+	{
+		return absError( expected, actual ) / expected;
+	}
+	
+	/**
+	 * Computes the absolute error between actual and expected.
+	 * @param expected
+	 * @param actual
+	 * @return the absolute error Math.abs( expected - actual ).
+	 */
+	public static double absError( double expected, double actual )
+	{
+		return Math.abs( expected - actual );
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/TestMonitor.java b/util/src/test/java/org/apache/etch/util/TestMonitor.java
new file mode 100644
index 0000000..55b7a56
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/TestMonitor.java
@@ -0,0 +1,427 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+/** Test of Monitor */
+public class TestMonitor
+{
+	// change this to a much smaller number (e.g., 0.1) to actually test the
+	// circular queue timeout accuracy.
+	private final static double REL_ERROR = 100000;
+	
+	/** @throws Exception */
+	@Test
+	public void construct1() throws Exception
+	{
+		testconstruct1( null );
+		testconstruct1( "a" );
+		testconstruct1( "b" );
+	}
+	
+	private void testconstruct1( String descr )
+	{
+		Monitor<Object> m = new Monitor<Object>( descr );
+		assertEquals( descr, m.getDescription() );
+		assertNull( m.get() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void construct2() throws Exception
+	{
+		testconstruct2( null, null );
+		testconstruct2( null, true );
+		testconstruct2( null, 1 );
+		testconstruct2( null, "abc" );
+		testconstruct2( null, 3.14159 );
+		
+		testconstruct2( "a", null );
+		testconstruct2( "b", true );
+		testconstruct2( "c", 1 );
+		testconstruct2( "d", "abc" );
+		testconstruct2( "e", 3.14159 );
+	}
+	
+	private void testconstruct2( String descr, Object value )
+	{
+		Monitor<Object> m = new Monitor<Object>( descr, value );
+		assertEquals( descr, m.getDescription() );
+		assertEquals( value, m.get() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void mToString() throws Exception
+	{
+		assertEquals( "Monitor null: null", new Monitor<Object>( null, null ).toString() );
+		assertEquals( "Monitor null: true", new Monitor<Object>( null, true ).toString() );
+		assertEquals( "Monitor null: 1", new Monitor<Object>( null, 1 ).toString() );
+		assertEquals( "Monitor null: abc", new Monitor<Object>( null, "abc" ).toString() );
+		assertEquals( "Monitor null: 3.14159", new Monitor<Object>( null, 3.14159 ).toString() );
+
+		assertEquals( "Monitor a: null", new Monitor<Object>( "a", null ).toString() );
+		assertEquals( "Monitor b: true", new Monitor<Object>( "b", true ).toString() );
+		assertEquals( "Monitor c: 1", new Monitor<Object>( "c", 1 ).toString() );
+		assertEquals( "Monitor d: abc", new Monitor<Object>( "d", "abc" ).toString() );
+		assertEquals( "Monitor e: 3.14159", new Monitor<Object>( "e", 3.14159 ).toString() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void set1() throws Exception
+	{
+		Monitor<Object> m = new Monitor<Object>( "a", null );
+		assertEquals( null, m.set( 1 ) );
+		assertEquals( 1, m.set( 2 ) );
+		assertEquals( 2, m.set( null ) );
+		assertEquals( null, m.set( null ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void set2() throws Exception
+	{
+		Monitor<Object> m = new Monitor<Object>( "a", 1 );
+		assertEquals( 1, m.set( 2 ) );
+		assertEquals( 2, m.set( null ) );
+		assertEquals( null, m.set( null ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void setget() throws Exception
+	{
+		Monitor<Object> m = new Monitor<Object>( "a", 1 );
+		
+		assertEquals( 1, m.set( 2 ) );
+		assertEquals( 2, m.get() );
+		
+		assertEquals( 2, m.set( null ) );
+		assertEquals( null, m.get() );
+		
+		assertEquals( null, m.set( null ) );
+		assertEquals( null, m.get() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void setsync() throws Exception
+	{
+		final Monitor<Integer> m = new Monitor<Integer>( "a", null );
+		final boolean[] flag = new boolean[2000];
+		
+		Thread t1 = TestHelp.delay( 0, new TestHelp.DelayRunnable()
+		{
+			public void run()
+			{
+				for (int i = 0; i < 1000; i++)
+				{
+					Integer x = m.set( i );
+					if (x != null)
+						flag[x] = true;
+				}
+			}
+		} );
+		
+		Thread t2 = TestHelp.delay( 0, new TestHelp.DelayRunnable()
+		{
+			public void run()
+			{
+				for (int i = 1000; i < 2000; i++)
+				{
+					Integer x = m.set( i );
+					if (x != null)
+						flag[x] = true;
+				}
+			}
+		} );
+
+		t1.start();
+		t2.start();
+		
+		t1.join();
+		t2.join();
+		
+		Integer x = m.set( null );
+		if (x != null)
+			flag[x] = true;
+		
+		for (boolean b: flag)
+			assertTrue( b );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void waitUntilEq1() throws Exception
+	{
+		Monitor<Integer> m = new Monitor<Integer>( "a", null );
+		m.waitUntilEq( null );
+		m.waitUntilEq( null, 0 );
+		
+		m.set( 1 );
+		m.waitUntilEq( 1 );
+		m.waitUntilEq( 1, 0 );
+		
+		m.set( 2 );
+		m.waitUntilEq( 2 );
+		m.waitUntilEq( 2, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = TimeoutException.class )
+	public void waitUntilEq2() throws Exception
+	{
+		Monitor<Integer> m = new Monitor<Integer>( "a", 1 );
+		m.waitUntilEq( 2, 1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = TimeoutException.class )
+	public void waitUntilEq3() throws Exception
+	{
+		Monitor<Integer> m = new Monitor<Integer>( "a", null );
+		m.waitUntilEq( 2, 1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = TimeoutException.class )
+	public void waitUntilEq4() throws Exception
+	{
+		Monitor<Integer> m = new Monitor<Integer>( "a", 1 );
+		m.waitUntilEq( null, 1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void waitUntilNotEq1() throws Exception
+	{
+		Monitor<Integer> m = new Monitor<Integer>( "a", null );
+		m.waitUntilNotEq( 1 );
+		m.waitUntilNotEq( 1, 0 );
+		
+		m.set( 1 );
+		m.waitUntilNotEq( null );
+		m.waitUntilNotEq( null, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = TimeoutException.class )
+	public void waitUntilNotEq2() throws Exception
+	{
+		Monitor<Integer> m = new Monitor<Integer>( "a", null );
+		m.waitUntilNotEq( null, 1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = TimeoutException.class )
+	public void waitUntilNotEq3() throws Exception
+	{
+		Monitor<Integer> m = new Monitor<Integer>( "a", 1 );
+		m.waitUntilNotEq( 1, 1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void waitUntilEqAndSet1() throws Exception
+	{
+		Monitor<Integer> m = new Monitor<Integer>( "a", null );
+		assertEquals( null, m.waitUntilEqAndSet( null, 1 ) );
+		assertEquals( 1, m.waitUntilEqAndSet( 1, 2 ) );
+		assertEquals( 2, m.waitUntilEqAndSet( 2, null ) );
+		assertEquals( null, m.waitUntilEqAndSet( null, null ) );
+
+		assertEquals( null, m.waitUntilEqAndSet( null, 0, 1 ) );
+		assertEquals( 1, m.waitUntilEqAndSet( 1, 0, 2 ) );
+		assertEquals( 2, m.waitUntilEqAndSet( 2, 0, null ) );
+		assertEquals( null, m.waitUntilEqAndSet( null, 0, null ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = TimeoutException.class )
+	public void waitUntilEqAndSet2() throws Exception
+	{
+		Monitor<Integer> m = new Monitor<Integer>( "a", null );
+		try
+		{
+			m.waitUntilEqAndSet( 1, 1, 2 );
+		}
+		finally
+		{
+			assertEquals( null, m.get() );
+		}
+	}
+	
+	/** @throws Exception */
+	@Test( expected = TimeoutException.class )
+	public void waitUntilEqAndSet3() throws Exception
+	{
+		Monitor<Integer> m = new Monitor<Integer>( "a", 1 );
+		try
+		{
+			m.waitUntilEqAndSet( null, 1, 2 );
+		}
+		finally
+		{
+			assertEquals( 1, m.get() );
+		}
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void waitUntilNotEqAndSet1() throws Exception
+	{
+		Monitor<Integer> m = new Monitor<Integer>( "a", null );
+		assertEquals( null, m.waitUntilNotEqAndSet( 2, 1 ) );
+		assertEquals( 1, m.waitUntilNotEqAndSet( 3, 2 ) );
+		assertEquals( 2, m.waitUntilNotEqAndSet( 4, null ) );
+		assertEquals( null, m.waitUntilNotEqAndSet( 5, null ) );
+
+		assertEquals( null, m.waitUntilNotEqAndSet( 2, 0, 1 ) );
+		assertEquals( 1, m.waitUntilNotEqAndSet( 3, 0, 2 ) );
+		assertEquals( 2, m.waitUntilNotEqAndSet( 4, 0, null ) );
+		assertEquals( null, m.waitUntilNotEqAndSet( 5, 0, null ) );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = TimeoutException.class )
+	public void waitUntilNotEqAndSet2() throws Exception
+	{
+		Monitor<Integer> m = new Monitor<Integer>( "a", null );
+		try
+		{
+			m.waitUntilNotEqAndSet( null, 1, 1 );
+		}
+		finally
+		{
+			assertEquals( null, m.get() );
+		}
+	}
+	
+	/** @throws Exception */
+	@Test( expected = TimeoutException.class )
+	public void waitUntilNotEqAndSet3() throws Exception
+	{
+		Monitor<Integer> m = new Monitor<Integer>( "a", 1 );
+		try
+		{
+			m.waitUntilNotEqAndSet( 1, 1, null );
+		}
+		finally
+		{
+			assertEquals( 1, m.get() );
+		}
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void waitUntilEq5() throws Exception
+	{
+		final Monitor<Integer> m = new Monitor<Integer>( "a", null );
+		
+		Thread t = TestHelp.delayAndStart( 200, new TestHelp.DelayRunnable()
+		{
+			public void run()
+			{
+				m.set( 1 );
+			}
+		} );
+
+		long t0 = System.nanoTime();
+		m.waitUntilEq( 1 );
+		double t1 = (System.nanoTime() - t0) / 1000000.0;
+		TestHelp.assertRelError( 200, t1, REL_ERROR );
+		
+		t.join();
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void waitUntilNotEq4() throws Exception
+	{
+		final Monitor<Integer> m = new Monitor<Integer>( "a", null );
+		
+		Thread t = TestHelp.delayAndStart( 200, new TestHelp.DelayRunnable()
+		{
+			public void run()
+			{
+				m.set( 1 );
+			}
+		} );
+
+		long t0 = System.nanoTime();
+		m.waitUntilNotEq( null );
+		double t1 = (System.nanoTime() - t0) / 1000000.0;
+		TestHelp.assertRelError( 200, t1, REL_ERROR );
+		
+		t.join();
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void waitUntilEqAndSet4() throws Exception
+	{
+		final Monitor<Integer> m = new Monitor<Integer>( "a", null );
+		
+		Thread t = TestHelp.delayAndStart( 200, new TestHelp.DelayRunnable()
+		{
+			public void run()
+			{
+				m.set( 1 );
+			}
+		} );
+		
+		long t0 = System.nanoTime();
+		m.waitUntilEqAndSet( 1, 2 );
+		double t1 = (System.nanoTime() - t0) / 1000000.0;
+		// TODO is there a better way for choosing relative error?
+		TestHelp.assertRelError( 200, t1, REL_ERROR );
+		
+		t.join();
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void waitUntilNotEqAndSet4() throws Exception
+	{
+		final Monitor<Integer> m = new Monitor<Integer>( "a", null );
+		
+		Thread t = TestHelp.delayAndStart( 200, new TestHelp.DelayRunnable()
+		{
+			public void run()
+			{
+				m.set( 1 );
+			}
+		} );
+
+		long t0 = System.nanoTime();
+		m.waitUntilNotEqAndSet( null, 2 );
+		double t1 = (System.nanoTime() - t0) / 1000000.0;
+		TestHelp.assertRelError( 200, t1, REL_ERROR );
+		
+		t.join();
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/TestUrl1.java b/util/src/test/java/org/apache/etch/util/TestUrl1.java
new file mode 100644
index 0000000..e1ceb5d
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/TestUrl1.java
@@ -0,0 +1,1900 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Test;
+
+/**
+ * @author jacapps
+ *
+ */
+public class TestUrl1
+{
+	String nullScheme = null;
+	String nullUser = null;
+	String nullPassword = null;
+	String nullHost = null;
+	Integer nullPort = null;
+	String nullUri = null;
+	Set<String> nullParams = new HashSet<String>();
+	Map<String,Object> nullTerms = new HashMap<String, Object>();
+	String nullFragment = null;
+
+	String defScheme = "tcp";
+	String defUser = "admin";
+	String defPassword = "metreos";
+	String defHost = "localhost";
+	int defPort = 10000;
+	String defUri = "uri";
+	Set<String> defParams = new HashSet<String>();
+	Map<String,Object> defTerms = new HashMap<String, Object>();
+	String defFragment = "frag";
+
+	String urlStr1 = "tcp://admin:metreos@localhost:10000/uri;param1;param2?term1=value1&term2=value2#frag";
+	String urlStr2 = "tcp://admin:metreos@localhost:10000/uri;param2;param1?term1=value1&term2=value2#frag";
+
+//	private URL url = new URL();
+
+	/**
+	 * Verify all fields in url against expected values.
+	 *
+	 * @param url url to verify
+	 * @param fragment expected fragment
+	 * @param host expected host
+	 * @param numParams expected number of params
+	 * @param password expected password
+	 * @param port expected port
+	 * @param scheme expected scheme
+	 * @param hasTerms value for hasTerms
+	 * @param uri expected uri
+	 * @param user expected user
+	 */
+	public void verifyURL(URL url, String fragment, String host,
+			int numParams, String password, Integer port,
+			String scheme, boolean hasTerms, String uri, String user)
+	{
+		// Verify all fields in url against expected values.
+		assertEquals(scheme, url.getScheme());
+		assertEquals(user, url.getUser());
+		assertEquals(password, url.getPassword());
+		assertEquals(host, url.getHost());
+		assertEquals(port, url.getPort());
+		assertEquals(uri, url.getUri());
+		assertEquals(fragment, url.getFragment());
+
+		// Verify that the number of params matches the expected value
+		int count = url.getParams().length;
+		assertEquals(count, numParams);
+
+		/**
+		 * Verify that hasTerms matches the expected value
+		 */
+		assertEquals(hasTerms, url.hasTerms());
+	}
+
+	/**
+	 * Verify creation of empty URL
+	 *
+	 * @throws Exception
+	 *
+	 */
+	@Test
+	public void testConstructor1() throws Exception
+	{
+		URL url = new URL();
+
+		int numParams = 0;
+		boolean hasTerms = false;
+
+		verifyURL(url, nullFragment, nullHost, numParams, nullPassword, nullPort,
+				nullScheme, hasTerms, nullUri, nullUser);
+	}
+
+	/**
+	 * Verify creation of URL from string
+	 *
+	 * @throws Exception
+	 *
+	 */
+	@Test
+	public void testConstructor2() throws Exception
+	{
+		URL url = new URL(urlStr1);
+
+		int numParams = 2;
+		boolean hasTerms = true;
+
+		verifyURL(url, defFragment, defHost, numParams, defPassword, defPort,
+				defScheme, hasTerms, defUri, defUser);
+
+	}
+
+	/**
+	 * Verify creation of URL with null string
+	 *
+	 * @throws Exception
+	 *
+	 */
+	@Test
+	public void testConstructor3() throws Exception
+	{
+		assertEquals( new URL(), new URL( (String) null ) );
+	}
+
+	/**
+	 * Verify creation of URL with empty string
+	 *
+	 * @throws Exception
+	 *
+	 */
+	@Test
+	public void testConstructor3a() throws Exception
+	{
+		assertEquals( new URL(), new URL( "" ) );
+	}
+
+	/**
+	 * Verify creation of URL with invalid string
+	 *
+	 * @throws Exception
+	 *
+	 */
+	@Test(expected = IllegalArgumentException.class)
+	public void testConstructor4() throws Exception
+	{
+		new URL("whateverblah~*}}[");
+	}
+
+	/**
+	 * Verify creation of URL from URL
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testConstructor5() throws Exception
+	{
+		int numParams = 0;
+		boolean hasTerms = false;
+		String uri = "";
+
+		URL url = new URL("tcp://localhost:10000");
+
+		verifyURL(url, nullFragment, defHost, numParams, nullPassword, defPort,
+				defScheme, hasTerms, uri, nullUser);
+	}
+
+	/**
+	 * Verify addParam - no params exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testAddParam1() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		url.addParam("param1=value1");
+		assertEquals("param1=value1", url.getParam("param1="));
+	}
+
+	/**
+	 * Verify addParam - params exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testAddParam2() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		url.addParam("param1=value1");
+		url.addParam("param2=value2");
+		assertEquals("param1=value1", url.getParam("param1="));
+		assertEquals("param2=value2", url.getParam("param2="));
+	}
+
+	/**
+	 * Verify addParam - param prefix is duplicate
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testAddParam3() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		url.addParam("param1=value1");
+		url.addParam("param1=value1");
+
+		assertEquals("param1=value1", url.getParam("param1="));
+	}
+
+	/**
+	 * Verify addParam - param prefix is null
+	 *
+	 * @throws Exception
+	 */
+	@Test(expected = NullPointerException.class)
+	public void testAddParam4() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		url.addParam(null);
+	}
+
+	/**
+	 * Verify addParam - param prefix is blank
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testAddParam5() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		url.addParam("");
+		assertEquals( "", url.getParam("") );
+	}
+
+	/**
+	 * Verify addTerm add double term
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testAddTerm_double1() throws Exception
+	{
+		double value = 1.7976931348623157e308d;
+		String name = "term1";
+
+		URL url = new URL("tcp://localhost:10000");
+		url.addTerm(name, value);
+
+		double termValue = new Double(url.getTerm(name));
+
+		assertEquals(value, termValue);
+
+	}
+
+	/**
+	 * Verify addTerm add double term
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testAddTerm_Double1() throws Exception
+	{
+		Double value = 1.7976931348623157e308d;
+		String name = "term1";
+
+		URL url = new URL("tcp://localhost:10000");
+		url.addTerm(name, value);
+
+		double termValue = new Double (url.getTerm(name));
+		assertEquals(value, termValue);
+	}
+
+	/**
+	 * Verify addTerm add int term
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testAddTerm_int1() throws Exception
+	{
+		int value = 2147483647;
+		String name = "term1";
+
+		URL url = new URL("tcp://localhost:10000");
+		url.addTerm(name, value);
+
+		int termValue = new Integer (url.getTerm(name));
+		assertEquals(value, termValue);
+	}
+
+	/**
+	 * Verify addTerm add Integer term
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testAddTerm_int2() throws Exception
+	{
+		Integer value = 2147483647;
+		String name = "term1";
+
+		URL url = new URL("tcp://localhost:10000");
+		url.addTerm(name, value);
+
+		int termValue = new Integer (url.getTerm(name));
+		assertEquals(value, termValue);
+	}
+
+	/**
+	 * Verify addTerm add String term
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testAddTermString() throws Exception
+	{
+		String value = "value1";
+		String name = "term1";
+
+		URL url = new URL("tcp://localhost:10000");
+		url.addTerm(name, value);
+
+		assertEquals(value, url.getTerm(name));
+	}
+
+	/**
+	 * Verify clearParams params exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testClearParams1() throws Exception
+	{
+
+		URL url = new URL(urlStr1);
+
+		assertTrue(url.hasParams());
+		url.clearParams();
+		assertFalse(url.hasParams());
+	}
+
+	/**
+	 * Verify clearParams params do not exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testClearParams2() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+
+		assertFalse(url.hasParams());
+		url.clearParams();
+		assertFalse(url.hasParams());
+	}
+
+	/**
+	 * Verify clearTerms terms exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testClearTerms1() throws Exception
+	{
+
+		URL url = new URL(urlStr1);
+
+		assertTrue(url.hasTerms());
+		url.clearTerms();
+		assertFalse(url.hasTerms());
+	}
+
+	/**
+	 * Verify clearTerms terms do not exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testClearTerms2() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+
+		assertFalse(url.hasTerms());
+		url.clearTerms();
+		assertFalse(url.hasTerms());
+	}
+
+	/**
+	 * Verify dump
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testDump() throws Exception
+	{
+		URL url = new URL(urlStr1);
+		url.dump();
+	}
+
+	/**
+	 * Verify equals true
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testEquals1() throws Exception
+	{
+		URL url = new URL(urlStr1);
+		URL url2 = new URL(urlStr1);
+
+		assertTrue(url.equals(url2));
+	}
+
+	/**
+	 * Verify equals false
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testEquals2() throws Exception
+	{
+		URL url = new URL(urlStr1);
+		URL url2 = new URL("tcp://localhost:10000");
+
+		assertFalse(url.equals(url2));
+	}
+
+	/**
+	 * Verify equals obj not url
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testEquals3() throws Exception
+	{
+		URL url = new URL(urlStr1);
+		String url2 = "tcp://localhost:10000";
+
+		assertFalse(url.equals(url2));
+	}
+
+	/**
+	 * Verify equals obj null
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testEquals4() throws Exception
+	{
+		URL url = new URL(urlStr1);
+		URL url2 = new URL();
+
+		assertFalse(url.equals(url2));
+	}
+
+	/**
+	 * Verify getBooleanTerm values are boolean
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetBooleanTerm1() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=true&term2=false#defFragment");
+		assertTrue(url.getBooleanTerm("term1"));
+		assertFalse(url.getBooleanTerm("term2"));
+	}
+
+	/**
+	 * Verify getBooleanTerm values are not boolean
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetBooleanTerm2() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=value1&term2=value2#defFragment");
+		assertFalse(url.getBooleanTerm("term1"));
+	}
+
+	/**
+	 * Verify getBooleanTerm (String, boolean)
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetBooleanTerm3() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=true&term2=false&term3=other#defFragment");
+
+		/** Term exists and is true */
+		assertTrue(url.getBooleanTerm("term1",false));
+
+		/** Term exists and is false */
+		assertFalse(url.getBooleanTerm("term2",true));
+
+		/** Term exists and is not a boolean value */
+		assertFalse(url.getBooleanTerm("term3",true));
+
+		/** Term does not exists and default value is true */
+		assertTrue(url.getBooleanTerm("term4",true));
+
+		/** Term does not exists and default value is false */
+		assertFalse(url.getBooleanTerm("term5",false));
+
+		/** Term does not exists and default value is false */
+		assertFalse(url.getBooleanTerm("term5",false));
+
+		/** Term invalid */
+		assertFalse(url.getBooleanTerm("&&?#",false));
+	}
+	
+	/** @throws Exception */
+	@Test(expected = IllegalArgumentException.class )
+	public void testGetBooleanTerm4() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=true&term2=false&term3=other#defFragment");
+
+		/** Term null */
+		url.getBooleanTerm(null);
+	}
+	
+	/** @throws Exception */
+	@Test(expected = IllegalArgumentException.class )
+	public void testGetBooleanTerm5() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=true&term2=false&term3=other#defFragment");
+
+		/** Term blank */
+		url.getBooleanTerm("");
+	}
+
+	/**
+	 * Verify getDoubleTerm
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetDoubleTerm1() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=1.7976931348623157e308d&term2=1d#defFragment");
+
+		/** Term exists and is double */
+		assertEquals(1.7976931348623157e308d, url.getDoubleTerm("term1"));
+
+		/** Term does not exist */
+		assertEquals(null, url.getDoubleTerm("DNE"));
+	}
+	
+	/** @throws Exception */
+	@Test(expected = IllegalArgumentException.class )
+	public void testGetDoubleTerm2() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=1.7976931348623157e308d&term2=1d#defFragment");
+
+		url.getDoubleTerm(null);
+	}
+	
+	/** @throws Exception */
+	@Test(expected = IllegalArgumentException.class )
+	public void testGetDoubleTerm3() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=1.7976931348623157e308d&term2=1d#defFragment");
+
+		url.getDoubleTerm("");
+	}
+
+	/**
+	 * Verify getFragment
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetFragment1() throws Exception
+	{
+		URL url = new URL("tcp://localhost@10000#defFragment");
+		URL url2 = new URL("tcp://localhost@10000");
+
+		/** Fragment exists */
+		assertEquals("defFragment", url.getFragment());
+
+		/** Fragment does not exist */
+		assertEquals(null, url2.getFragment());
+	}
+
+	/**
+	 * Verify getHost
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetHost1() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		URL url2 = new URL();
+
+		/** Host defined for url */
+		assertEquals("localhost", url.getHost());
+
+		/** Host not defined for url */
+		assertNull(url2.getHost());
+
+	}
+
+	/**
+	 * Verify getIntegerTerm(String)
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetIntegerTerm1() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=1&term2=10#defFragment");
+
+		/** Term exists and is integer */
+		assertEquals(1, url.getIntegerTerm("term1"));
+
+		/** Term does not exist */
+		assertEquals(null, url.getIntegerTerm("DNE"));
+	}
+	
+	/** @throws Exception */
+	@Test(expected = IllegalArgumentException.class)
+	public void testGetIntegerTerm5() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=1&term2=10#defFragment");
+
+		url.getIntegerTerm(null);
+	}
+	
+	/** @throws Exception */
+	@Test(expected = IllegalArgumentException.class)
+	public void testGetIntegerTerm6() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=1&term2=10#defFragment");
+
+		url.getIntegerTerm("");
+	}
+
+	/**
+	 * Verify getIntegerTerm (String, int)
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetIntegerTerm2() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=1&term2=1.7d&term3=stringValue#defFragment");
+
+		/** Term exists and is integer */
+		assertEquals(1,url.getIntegerTerm("term1",1000));
+
+		/** Term does not exist and default value is integer */
+		assertEquals(1000,url.getIntegerTerm("term4",1000));
+
+		/** Term invalid */
+		assertEquals(1000,url.getIntegerTerm("&&?#",1000));
+	}
+
+	/**
+	 * Verify getIntegerTerm (String, int)
+	 * Term exists and is a double
+	 *
+	 * @throws Exception
+	 */
+	@Test(expected = NumberFormatException.class)
+	public void testGetIntegerTerm3() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=1&term2=1.7d&term3=stringValue#defFragment");
+
+		/** Term exists and is a double */
+		assertEquals(1.7d,url.getIntegerTerm("term2",1000));
+	}
+
+	/**
+	 * Verify getIntegerTerm (String, int)
+	 * Term exists and is a String
+	 *
+	 * @throws Exception
+	 */
+	@Test(expected = NumberFormatException.class)
+	public void testGetIntegerTerm4() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=1&term2=1.7d&term3=stringValue#defFragment");
+
+		/** Term exists and is a string */
+		assertEquals("stringValue", url.getIntegerTerm("term3",1000));
+	}
+
+
+	/**
+	 * Verify getParams - no params
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetParams1() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		assertEquals( 0, url.getParams().length );
+
+	}
+
+	/**
+	 * Verify getParams - params exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetParams2() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000/defUri;param1=value1;param2=value2;param3");
+		assertEquals( 3, url.getParams().length );
+
+		url.removeParam("param1=");
+		assertEquals( 2, url.getParams().length );
+
+		url.removeParam("param2=");
+		assertEquals( 1, url.getParams().length );
+
+		url.removeParam("param3");
+		assertEquals( 0, url.getParams().length );
+	}
+
+	/**
+	 * Verify getPassword - password exists
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetPassword1() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000");
+		assertEquals("metreos",url.getPassword());
+	}
+
+	/**
+	 * Verify getPassword - password does not exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetPassword2() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		assertNull(url.getPassword());
+	}
+
+	/**
+	 * Verify getScheme - scheme exists
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetScheme1() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		assertEquals("tcp",url.getScheme());
+	}
+
+	/**
+	 * Verify getScheme - port does not exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetScheme2() throws Exception
+	{
+		URL url = new URL();
+		assertNull(url.getScheme());
+	}
+
+	/**
+	 * Verify getTerm(String) - no terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetTerm1() throws Exception
+	{
+		URL url = new URL();
+		assertNull(url.getTerm("term1"));
+	}
+
+	/**
+	 * Verify getTerm - term exists
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetTerm2() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=value1&term2=#defFragment");
+
+		/** Term exists and has value */
+		assertEquals("value1",url.getTerm("term1"));
+
+		/** Term exists but has no value */
+		assertEquals("",url.getTerm("term2"));
+	}
+
+	/**
+	 * Verify getTerm (String, String) - no terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetTerm3() throws Exception
+	{
+		URL url = new URL();
+
+		/** No terms exist */
+		assertEquals("default", url.getTerm("term1","default"));
+	}
+
+	/**
+	 * Verify getTerm (String, String) - term exists and have value
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetTerm4() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=value1&term2=#defFragment");
+
+		/** Term exists and has value */
+		assertEquals("value1", url.getTerm("term1","default"));
+
+		/** TODO I think this should set the value for term2 but it doesn't */
+		/** Term exists and has no value */
+		//assertEquals("default", url.getTerm("term2","default"));
+
+		/** Terms exists but not this term */
+		assertEquals("default", url.getTerm("term3","default"));
+	}
+
+	/**
+	 * Verify getTermNames - no terms exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetTermNames1() throws Exception
+	{
+		URL url = new URL();
+		assertEquals( 0, url.getTermNames().length );
+	}
+
+	/**
+	 * Verify getTermNames - terms exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetTermNames2() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=value1&term2=value2#defFragment");
+
+		for( String s: url.getTermNames())
+		{
+			assertTrue(s.equals("term1") || s.equals("term2"));
+		}
+	}
+
+	/**
+	 * Verify getTerms - no terms exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetTerms1() throws Exception
+	{
+		URL url = new URL();
+		assertEquals( 0, url.getTerms("term1").length );
+	}
+
+	/**
+	 * Verify getTerms - terms exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetTerms2() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=value1&term2=value2#defFragment");
+
+		assertEquals( 1, url.getTerms("term1").length );
+		assertEquals( "value1", url.getTerms("term1")[0] );
+	}
+
+	/**
+	 * Verify getUri - uri exists
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetUri1() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000/defUri");
+		assertEquals("defUri",url.getUri());
+	}
+
+	/**
+	 * Verify getUri - uri does not exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetUri2() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		assertEquals("",url.getUri());
+	}
+
+	/**
+	 * Verify getUser - user exists
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetUser1() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000");
+		assertEquals("admin",url.getUser());
+	}
+
+	/**
+	 * Verify getUri - uri does not exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetUser2() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		assertNull(url.getUser());
+	}
+
+	/**
+	 * Verify hasMultipleValues - no terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasMultipleValues1() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		assertFalse(url.hasMultipleValues("term1"));
+	}
+
+	/**
+	 * Verify hasMultipleValues - term exists
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasMultipleValues2() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri;param1;param2?term1=value1&term2=value2&term3=#defFragment");
+
+		/** Term exists and has 1 value */
+		assertFalse(url.hasMultipleValues("term1"));
+
+		/** Term exists and has multiple values */
+		/** TODO: Find out format for multiple values in query term */
+		//assertTrue(url.hasMultipleValues("term2"));
+
+		/** Term exists and has no values */
+		assertFalse(url.hasMultipleValues("term3"));
+	}
+
+	/**
+	 * Verify hasParams - no params
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasParams1() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		assertFalse(url.hasParams());
+	}
+
+	/**
+	 * Verify hasParams - params exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasParams2() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000/defUri;param1;param2");
+
+		/**  Url has params */
+		assertTrue(url.hasParams());
+	}
+
+	/**
+	 * Verify hasTerm(String) - no terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasTerm1() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		assertFalse(url.hasTerm("term1"));
+	}
+
+	/**
+	 * Verify hasTerm(String) - url has terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasTerm2() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000/defUri;param1;param2?term1=value1&term2=value2&term3=");
+
+		/** Term exists */
+		assertTrue(url.hasTerm("term1"));
+
+		/** Term does not exist */
+		assertFalse(url.hasTerm("DNE"));
+	}
+
+	/**
+	 * Verify hasTerm(String, double) - no terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasTerm3() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		assertFalse(url.hasTerm("term1",1.7d));
+	}
+
+	/**
+	 * Verify hasTerm(String, double) - url has terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasTerm4() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000/defUri;param1;param2?term1=1.7");
+
+		/**  Term exists with matching value  */
+		assertTrue(url.hasTerm("term1",1.7d));
+
+		/** Term exists but value does not match */
+		assertFalse(url.hasTerm("term1",3.0d));
+	}
+
+	/**
+	 * Verify hasTerm(String, Double) - no terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasTerm5() throws Exception
+	{
+		Double d = new Double(1.7d);
+
+		URL url = new URL("tcp://localhost:10000");
+		assertFalse(url.hasTerm("term1",d));
+	}
+
+	/**
+	 * Verify hasTerm(String, Double) - url has terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasTerm6() throws Exception
+	{
+		Double d1 = new Double(1.7d);
+		Double d2 = new Double(3.0d);
+
+		URL url = new URL("tcp://localhost:10000/defUri;param1;param2?term1=1.7");
+
+		/**  Term exists with matching value  */
+		assertTrue(url.hasTerm("term1",d1));
+
+		/** Term exists but value does not match */
+		assertFalse(url.hasTerm("term1",d2));
+	}
+
+	/**
+	 * Verify hasTerm(String, int) - no terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasTerm7() throws Exception
+	{
+		int i = 10;
+
+		URL url = new URL("tcp://localhost:10000");
+		assertFalse(url.hasTerm("term1",i));
+	}
+
+	/**
+	 * Verify hasTerm(String, int) - url has terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasTerm8() throws Exception
+	{
+		int i1 = 10;
+		int i2 = 100;
+
+		URL url = new URL("tcp://localhost:10000/defUri;param1;param2?term1=10");
+
+		/**  Term exists with matching value  */
+		assertTrue(url.hasTerm("term1",i1));
+
+		/** Term exists but value does not match */
+		assertFalse(url.hasTerm("term1",i2));
+	}
+
+	/**
+	 * Verify hasTerm(String, Integer) - no terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasTerm9() throws Exception
+	{
+		Integer i = new Integer(10);
+
+		URL url = new URL("tcp://localhost:10000");
+		assertFalse(url.hasTerm("term1",i));
+	}
+
+	/**
+	 * Verify hasTerm(String, Integer) - url has terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasTerm10() throws Exception
+	{
+		Integer i1 = new Integer(10);
+		Integer i2 = new Integer(100);
+
+		URL url = new URL("tcp://localhost:10000/defUri;param1;param2?term1=10");
+
+		/**  Term exists with matching value  */
+		assertTrue(url.hasTerm("term1",i1));
+
+		/** Term exists but value does not match */
+		assertFalse(url.hasTerm("term1",i2));
+	}
+
+	/**
+	 * Verify hasTerm(String, String) - no terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasTerm11() throws Exception
+	{
+		String s = "value1";
+
+		URL url = new URL("tcp://localhost:10000");
+		assertFalse(url.hasTerm("term1",s));
+	}
+
+	/**
+	 * Verify hasTerm(String, String) - url has terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasTerm12() throws Exception
+	{
+		String s1 = "value1";
+		String s2 = "DNE";
+
+		URL url = new URL("tcp://localhost:10000/defUri;param1;param2?term1=value1");
+
+		/**  Term exists with matching value  */
+		assertTrue(url.hasTerm("term1",s1));
+
+		/** Term exists but value does not match */
+		assertFalse(url.hasTerm("term1",s2));
+	}
+
+	/**
+	 * Verify hasTerms - no terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasTerms1() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+		assertFalse(url.hasTerms());
+	}
+
+	/**
+	 * Verify hasTerms - terms exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasTerms2() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000/defUri;param1;param2?term1=value1&term2=value2");
+
+		/**  Url has params */
+		assertTrue(url.hasTerms());
+	}
+
+	/**
+	 * Verify isScheme - no scheme
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testIsScheme1() throws Exception
+	{
+		URL url = new URL();
+		assertFalse(url.isScheme("tcp"));
+	}
+
+	/**
+	 * Verify isScheme - scheme exists
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testIsScheme2() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+
+		/**  true - same case */
+		assertTrue(url.isScheme("tcp"));
+
+		/**  true different case */
+		assertTrue(url.isScheme("TCP"));
+
+		/** false */
+		assertFalse(url.isScheme("udp"));
+	}
+
+	/**
+	 * Verify removeParam - no params
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testRemoveParam1() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+
+		/** No params */
+		assertNull(url.removeParam("param1"));
+	}
+
+	/**
+	 * Verify removeParam - params exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testRemoveParam2() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000/defUri;param1=value1;param2=");
+
+		/** Param exists and has value */
+		assertEquals("param1=value1",url.getParam("param1="));
+		assertEquals("param1=value1",url.removeParam("param1="));
+		assertNull(url.getParam("param1="));
+
+		/** Param exists and has blank value */
+		assertEquals("param2=",url.getParam("param2="));
+		assertEquals("param2=",url.removeParam("param2="));
+		assertNull(url.getParam("param2="));
+
+		/** Param does not exist */
+		assertNull(url.removeParam("DNE="));
+	}
+
+	/**
+	 * Verify removeTerm(String) - no terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testRemoveTerm1() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+
+		/** No terms */
+		assertFalse( url.removeTerm("DNE") );
+		
+		url.addTerm( "a", 1 );
+		assertFalse( url.removeTerm("DNE") );
+	}
+
+	/**
+	 * Verify removeTerm(String) - Terms exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testRemoveTerm2() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000/defUri;param1=value1;param2=?term1=value1&term2=");
+
+		/** Term exists and has value */
+		assertEquals("value1",url.getTerm("term1"));
+		assertTrue(url.removeTerm("term1"));
+		assertNull(url.getTerm("term1"));
+
+		/** Term exists and has blank value */
+		assertEquals("",url.getTerm("term2"));
+		assertTrue(url.removeTerm("term2"));
+		assertNull(url.getTerm("term2"));
+
+		/** Param does not exist */
+		assertFalse(url.removeTerm("DNE"));
+	}
+
+	/**
+	 * Verify removeTerm(String,String) - no terms
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testRemoveTerm3() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+
+		/** No terms */
+		assertFalse(url.removeTerm("DNE","value1"));
+	}
+
+	/**
+	 * Verify removeTerm(String,String) - Terms exist
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testRemoveTerm4() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000/defUri;param1=value1;param2=?term1=value1&term2=");
+
+		/** Term exists and has value */
+		assertEquals("value1",url.getTerm("term1"));
+		assertTrue(url.removeTerm("term1","value1"));
+		assertNull(url.getTerm("term1"));
+
+		/** Term exists and has blank value */
+		assertEquals("",url.getTerm("term2"));
+		assertTrue(url.removeTerm("term2",""));
+		assertNull(url.getTerm("term2"));
+
+		/** Param does not exist */
+		assertFalse(url.removeTerm("DNE","value1"));
+	}
+
+	/**
+	 * Verify setFragment - no fragment in url
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetFragment1() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+
+		/** Set fragment.  No fragment exists in url */
+		url.setFragment("fragment1");
+		assertEquals("fragment1",url.getFragment());
+	}
+
+	/**
+	 * Verify setFragment - fragment exists in url
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetFragment2() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000/#defFragment");
+
+		/** Set fragment.  Fragment exists in url */
+		url.setFragment("fragment1");
+		assertEquals("fragment1",url.getFragment());
+
+	}
+
+	/**
+	 * Verify setFragment - set fragment to null
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetFragment3() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000/#defFragment");
+
+		/** Set fragment to null */
+		url.setFragment(null);
+		assertNull(url.getFragment());
+	}
+
+	/**
+	 * Verify setFragment - set fragment to blank
+	 *
+	 * @throws Exception
+	 */
+	@Test(expected = IllegalArgumentException.class)
+	public void testSetFragment4() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000/#defFragment");
+
+		/** Set fragment to blank */
+		url.setFragment("");
+		assertEquals("",url.getFragment());
+	}
+
+	/**
+	 * Verify setFHost - no host in url
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetHost1() throws Exception
+	{
+		URL url = new URL();
+
+		/** Set host.  No host exists in url */
+		url.setHost("host1");
+		assertEquals("host1",url.getHost());
+	}
+
+	/**
+	 * Verify setHost - host exists in url
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetHost2() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+
+		/** Set host.  Host exists in url */
+		url.setHost("host1");
+		assertEquals("host1",url.getHost());
+	}
+
+	/**
+	 * Verify setHost- set host to null
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetHost3() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+
+		/** Set host to null */
+		url.setHost(null);
+		assertNull(url.getHost());
+	}
+
+	/**
+	 * Verify setHostt - set host to blank
+	 *
+	 * @throws Exception
+	 */
+	@Test(expected = IllegalArgumentException.class)
+	public void testSetHost4() throws Exception
+	{
+		URL url = new URL("tcp://localhost:10000");
+
+		/** Set host to blank */
+		url.setHost("");
+		assertEquals("",url.getHost());
+	}
+
+	/**
+	 * Verify setPassword - no password in url
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetPassword1() throws Exception
+	{
+		URL url = new URL();
+
+		/** Set password.  No password exists in url */
+		url.setPassword("password1");
+		assertEquals("password1",url.getPassword());
+	}
+
+	/**
+	 * Verify setPassword - password exists in url
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetPassword2() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000");
+
+		/** Set password.  Password exists in url */
+		url.setPassword("password1");
+		assertEquals("password1",url.getPassword());
+	}
+
+	/**
+	 * Verify setPassword- set password to null
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetPassword3() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000");
+
+		/** Set password to null */
+		url.setPassword(null);
+		assertNull(url.getPassword());
+	}
+
+	/**
+	 * Verify setPassword - set password to blank
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetPassword4() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000");
+
+		/** Set password to blank */
+		url.setPassword("");
+		assertEquals("",url.getPassword());
+	}
+
+	/**
+	 * Verify setPort - no port in url
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetPort1() throws Exception
+	{
+		URL url = new URL();
+
+		/** Set port.  No port exists in url */
+		url.setPort(10000);
+		assertEquals(10000,url.getPort());
+	}
+
+	/**
+	 * Verify setPort - port exists in url
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetPort2() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000");
+
+		/** Set port.  Port exists in url */
+		url.setPort(5000);
+		assertEquals(5000,url.getPort());
+	}
+
+	/**
+	 * Verify setPort - set port less than min value
+	 *
+	 * @throws Exception
+	 */
+	@Test(expected = IllegalArgumentException.class)
+	public void testSetPort3() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000");
+
+		/** Set port less than min value */
+		url.setPort(-1);
+	}
+
+	/**
+	 * Verify setPort - set port greater than max value
+	 *
+	 * @throws Exception
+	 */
+	@Test(expected = IllegalArgumentException.class)
+	public void testSetPort4() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000");
+
+		/** Set port to negative number */
+		url.setPort(65536);
+	}
+
+	/**
+	 * Verify setScheme - no scheme in url
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetScheme1() throws Exception
+	{
+		URL url = new URL();
+
+		/** Set scheme.  No scheme exists in url */
+		url.setScheme("scheme1");
+		assertEquals("scheme1",url.getScheme());
+	}
+
+	/**
+	 * Verify setScheme - scheme exists in url
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetScheme2() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000");
+
+		/** Set scheme.  Scheme exists in url */
+		url.setScheme("scheme1");
+		assertEquals("scheme1",url.getScheme());
+	}
+
+	/**
+	 * Verify setScheme- set scheme to null
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetScheme3() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000");
+
+		/** Set scheme to null */
+		url.setScheme(null);
+		assertNull(url.getScheme());
+	}
+
+	/**
+	 * Verify setScheme - set scheme to blank
+	 *
+	 * @throws Exception
+	 */
+	@Test(expected = IllegalArgumentException.class)
+	public void testSetScheme4() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000");
+
+		/** Set scheme to blank */
+		url.setScheme("");
+		assertEquals("",url.getScheme());
+	}
+
+	/**
+	 * Verify setUri - no uri in url
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetUri1() throws Exception
+	{
+		URL url = new URL();
+
+		/** Set uri.  No uri exists in url */
+		url.setUri("uri1");
+		assertEquals("uri1",url.getUri());
+	}
+
+	/**
+	 * Verify setUri - uri exists in url
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetUri2() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri");
+
+		/** Set uri.  Uri exists in url */
+		url.setUri("uri1");
+		assertEquals("uri1",url.getUri());
+	}
+
+	/**
+	 * Verify setUri- set uri to null
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetUri3() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri");
+
+		/** Set uri to null */
+		url.setUri(null);
+		assertNull(url.getUri());
+	}
+
+	/**
+	 * Verify setUri - set uri to blank
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetUri4() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000/defUri");
+		assertEquals("defUri",url.getUri());
+		
+		/** Set uri to blank */
+		url.setUri("");
+		assertEquals("",url.getUri());
+	}
+
+	/**
+	 * Verify setUser - no user in url
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetUser1() throws Exception
+	{
+		URL url = new URL();
+		assertNull( url.getUser() );
+		
+		/** Set user.  No user exists in url */
+		url.setUser("user1");
+		assertEquals("user1",url.getUser());
+	}
+
+	/**
+	 * Verify setUser - user exists in url
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetUser2() throws Exception
+	{
+		URL url = new URL(urlStr1);
+		assertEquals("admin",url.getUser());
+
+		/** Set user.  User exists in url */
+		url.setUser("user1");
+		assertEquals("user1",url.getUser());
+	}
+
+	/**
+	 * Verify setUser- set user to null
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testSetUser3() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000");
+
+		/** Set user to null */
+		url.setUser(null);
+		assertNull(url.getUser());
+	}
+
+	/**
+	 * Verify setUser - set user to blank
+	 *
+	 * @throws Exception
+	 */
+	@Test(expected = IllegalArgumentException.class)
+	public void testSetUser4() throws Exception
+	{
+		URL url = new URL("tcp://admin:metreos@localhost:10000");
+
+		/** Set user to blank */
+		url.setUser("");
+		assertEquals("",url.getUser());
+	}
+
+	/**
+	 * Verify toString - url is null
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testToString1a() throws Exception
+	{
+		assertEquals( "null:", new URL().toString() );
+	}
+
+	/**
+	 * Verify toString - url is null
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testToString1b() throws Exception
+	{
+		assertEquals( "null:", new URL( (String) null ).toString() );
+	}
+
+	/**
+	 * Verify toString - url is null
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testToString1c() throws Exception
+	{
+		assertEquals( "null:", new URL( "" ).toString() );
+	}
+
+	/**
+	 * Verify toString
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testToString2() throws Exception
+	{
+//		checkToString( urlStr1 );
+		
+		checkToString( "null:" );
+		
+		checkToString( "a:b" );
+		checkToString( "a:b/c" );
+		checkToString( "a:/b" );
+		checkToString( "a:b/" );
+		
+//		checkToString( "a://host" ); // cannot distinguish from next case.
+		checkToString( "a://h/" );
+		checkToString( "a://h/b" );
+//		checkToString( "a:///b" ); // host is blank.
+
+//		checkToString( "a://h:-1" ); // port too negative
+		checkToString( "a://h:0/" );
+		checkToString( "a://h:1/" );
+		checkToString( "a://h:65535/" );
+//		checkToString( "a://h:65536" ); // port too big
+//		checkToString( "a://h:/" ); // port is blank
+//		checkToString( "a://h:b/" ); // port is not integer
+
+		checkToString( "a://u:p@h/" );
+//		checkToString( "a://:p@h/" ); // user is blank
+//		checkToString( "a://u:@h/" ); // password is blank
+//		checkToString( "a://:@h/" ); // user is blank
+
+		checkToString( "a:?b=c" );
+		checkToString( "a:?d=e" );
+
+		checkToString( "a:;p" );
+		checkToString( "a:;q" );
+
+		checkToString( "a:#f" );
+		checkToString( "a:#g" );
+	}
+
+	private void checkToString( String s )
+	{
+		assertEquals( s, new URL( s ).toString() );
+	}
+}
+
+
diff --git a/util/src/test/java/org/apache/etch/util/cmd/TestCommandParser.java b/util/src/test/java/org/apache/etch/util/cmd/TestCommandParser.java
new file mode 100644
index 0000000..e1b3110
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/cmd/TestCommandParser.java
@@ -0,0 +1,592 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.cmd;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+/**
+ * Test of CommandParser.
+ */
+public class TestCommandParser extends org.apache.etch.util.cmd.Program
+{
+	/**
+	 * @param args
+	 */
+	public static void main( String[] args )
+	{
+		try
+		{
+			prog = new TestCommandParser();
+			main( prog, args );
+		}
+		catch ( Throwable e )
+		{
+			cmdParseError = true;
+			e.printStackTrace();
+		}
+	}
+	
+	private static TestCommandParser prog;
+	
+	private static boolean cmdParseError;
+
+	@Override
+	protected void defineOptionsAndParameters( CommandParser cp )
+		throws Exception
+	{
+		cp.defineNullOption( "-a|--alpha", "setAlpha",
+			"set the alpha option",
+			Option.NONE );
+
+		cp.defineNullOption( "-b|--beta", "setBeta",
+			"set the beta option",
+			Option.NONE );
+
+		cp.defineStringOption( "-f|--foo", "value",
+			"setFooValue",
+			"specifies the foo value",
+			Option.NONE, null, null );
+
+		cp.defineStringOption( "-B|--bar", "value",
+			"setBarValue",
+			"specifies the bar value",
+			Option.NONE, null, null );
+		
+		cp.defineStringParameter( "one",
+			"one",
+			"first param",
+			false, false, null );
+		
+		cp.defineStringParameter( "two",
+			"two",
+			"second param",
+			false, false, null );
+		
+		cp.defineStringParameter( "rest",
+			"rest",
+			"args",
+			false, true, null );
+	}
+
+	/**
+	 * Command parser method to set the alpha flag.
+	 * 
+	 * @param cp
+	 * @param option
+	 * @param token
+	 */
+	public void setAlpha( CommandParser cp, Option option, String token )
+	{
+		alpha = true;
+	}
+
+	private boolean alpha;
+
+	/**
+	 * Command parser method to set the beta flag.
+	 * 
+	 * @param cp
+	 * @param option
+	 * @param token
+	 */
+	public void setBeta( CommandParser cp, Option option, String token )
+	{
+		beta = true;
+	}
+
+	private boolean beta;
+
+	/**
+	 * Command parser method to set the foo value.
+	 * 
+	 * @param cp
+	 * @param option
+	 * @param token
+	 * @param value
+	 */
+	public void setFooValue( CommandParser cp, Option option, String token,
+		String value )
+	{
+		fooValue = value;
+	}
+
+	private String fooValue;
+
+	/**
+	 * Command parser method to set the bar value.
+	 * 
+	 * @param cp
+	 * @param option
+	 * @param token
+	 * @param value
+	 */
+	public void setBarValue( CommandParser cp, Option option, String token,
+		String value )
+	{
+		barValue = value;
+	}
+
+	private String barValue;
+	
+	/**
+	 * @param cp
+	 * @param param
+	 * @param value
+	 */
+	public void one( CommandParser cp, Parameter param, String value )
+	{
+		one = value;
+	}
+	
+	private String one;
+	
+	/**
+	 * @param cp
+	 * @param param
+	 * @param value
+	 */
+	public void two( CommandParser cp, Parameter param, String value )
+	{
+		two = value;
+	}
+	
+	private String two;
+	
+	/**
+	 * @param cp
+	 * @param param
+	 * @param value
+	 */
+	public void rest( CommandParser cp, Parameter param, String value )
+	{
+		rest.add( value );
+	}
+	
+	private List<String> rest = new ArrayList<String>();
+	
+	@Override
+	public void exit( int code, String source, String reason, boolean emergency )
+	{
+		exitCode = code;
+	}
+	
+	private int exitCode;
+
+	@Override
+	protected void run() throws Exception
+	{
+		run = true;
+	}
+
+	private boolean run;
+	
+	/** @throws Exception */
+	@Test
+	public void nothing() throws Exception
+	{
+		main( new String[] {} );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertFalse( prog.alpha );
+		assertFalse( prog.beta );
+		assertNull( prog.fooValue );
+		assertNull( prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void short1() throws Exception
+	{
+		main( new String[] { "-a" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertTrue( prog.alpha );
+		assertFalse( prog.beta );
+		assertNull( prog.fooValue );
+		assertNull( prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void short2() throws Exception
+	{
+		main( new String[] { "-b" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertFalse( prog.alpha );
+		assertTrue( prog.beta );
+		assertNull( prog.fooValue );
+		assertNull( prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void short3a() throws Exception
+	{
+		main( new String[] { "-f", "abc" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertFalse( prog.alpha );
+		assertFalse( prog.beta );
+		assertEquals( "abc", prog.fooValue );
+		assertNull( prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void short3b() throws Exception
+	{
+		main( new String[] { "-fabc" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertFalse( prog.alpha );
+		assertFalse( prog.beta );
+		assertEquals( "abc", prog.fooValue );
+		assertNull( prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void short4a() throws Exception
+	{
+		main( new String[] { "-B", "def" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertFalse( prog.alpha );
+		assertFalse( prog.beta );
+		assertNull( prog.fooValue );
+		assertEquals( "def", prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void short4b() throws Exception
+	{
+		main( new String[] { "-Bdef" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertFalse( prog.alpha );
+		assertFalse( prog.beta );
+		assertNull( prog.fooValue );
+		assertEquals( "def", prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void allshort1() throws Exception
+	{
+		main( new String[] { "-abf", "abc" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertTrue( prog.alpha );
+		assertTrue( prog.beta );
+		assertEquals( "abc", prog.fooValue );
+		assertNull( prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void allshort2() throws Exception
+	{
+		main( new String[] { "-abfabc" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertTrue( prog.alpha );
+		assertTrue( prog.beta );
+		assertEquals( "abc", prog.fooValue );
+		assertNull( prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void long1() throws Exception
+	{
+		main( new String[] { "--alpha" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertTrue( prog.alpha );
+		assertFalse( prog.beta );
+		assertNull( prog.fooValue );
+		assertNull( prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void long2() throws Exception
+	{
+		main( new String[] { "--beta" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertFalse( prog.alpha );
+		assertTrue( prog.beta );
+		assertNull( prog.fooValue );
+		assertNull( prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void long3a() throws Exception
+	{
+		main( new String[] { "--foo", "abc" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertFalse( prog.alpha );
+		assertFalse( prog.beta );
+		assertEquals( "abc", prog.fooValue );
+		assertNull( prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void long3b() throws Exception
+	{
+		main( new String[] { "--foo", "" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertFalse( prog.alpha );
+		assertFalse( prog.beta );
+		assertEquals( "", prog.fooValue );
+		assertNull( prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void long3c() throws Exception
+	{
+		main( new String[] { "--foo=abc" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertFalse( prog.alpha );
+		assertFalse( prog.beta );
+		assertEquals( "abc", prog.fooValue );
+		assertNull( prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void long3d() throws Exception
+	{
+		main( new String[] { "--foo=" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertFalse( prog.alpha );
+		assertFalse( prog.beta );
+		assertEquals( "", prog.fooValue );
+		assertNull( prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void long4a() throws Exception
+	{
+		main( new String[] { "--bar", "def" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertFalse( prog.alpha );
+		assertFalse( prog.beta );
+		assertNull( prog.fooValue );
+		assertEquals( "def", prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void long4b() throws Exception
+	{
+		main( new String[] { "--bar=def" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertFalse( prog.alpha );
+		assertFalse( prog.beta );
+		assertNull( prog.fooValue );
+		assertEquals( "def", prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void alllong1() throws Exception
+	{
+		main( new String[] { "--alpha", "--beta", "--foo", "abc", "--bar", "def" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertTrue( prog.alpha );
+		assertTrue( prog.beta );
+		assertEquals( "abc", prog.fooValue );
+		assertEquals( "def", prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void alllong2() throws Exception
+	{
+		main( new String[] { "--alpha", "--beta", "--foo=abc", "--bar=def" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertTrue( prog.alpha );
+		assertTrue( prog.beta );
+		assertEquals( "abc", prog.fooValue );
+		assertEquals( "def", prog.barValue );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void param1() throws Exception
+	{
+		main( new String[] { "abc" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertEquals( "abc", prog.one );
+		assertEquals( null, prog.two );
+		assertEquals( 0, prog.rest.size() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void param2() throws Exception
+	{
+		main( new String[] { "abc", "def" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertEquals( "abc", prog.one );
+		assertEquals( "def", prog.two );
+		assertEquals( 0, prog.rest.size() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void param3() throws Exception
+	{
+		main( new String[] { "abc", "def", "ghi" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertEquals( "abc", prog.one );
+		assertEquals( "def", prog.two );
+		assertEquals( 1, prog.rest.size() );
+		assertEquals( "ghi", prog.rest.get( 0 ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void param4() throws Exception
+	{
+		main( new String[] { "abc", "def", "ghi", "jkl" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertEquals( "abc", prog.one );
+		assertEquals( "def", prog.two );
+		assertEquals( 2, prog.rest.size() );
+		assertEquals( "ghi", prog.rest.get( 0 ) );
+		assertEquals( "jkl", prog.rest.get( 1 ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void mixed1() throws Exception
+	{
+		main( new String[] { "abc", "-a", "def", "ghi", "-f", "123", "jkl" } );
+		assertTrue( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 0, prog.exitCode );
+		assertTrue( prog.alpha );
+		assertFalse( prog.beta );
+		assertEquals( "123", prog.fooValue );
+		assertEquals( null, prog.barValue );
+		assertEquals( "abc", prog.one );
+		assertEquals( "def", prog.two );
+		assertEquals( 2, prog.rest.size() );
+		assertEquals( "ghi", prog.rest.get( 0 ) );
+		assertEquals( "jkl", prog.rest.get( 1 ) );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void error1() throws Exception
+	{
+		// unknown short option
+		main( new String[] { "-x" } );
+		assertFalse( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 1, prog.exitCode );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void error2() throws Exception
+	{
+		// unknown long option
+		main( new String[] { "--x" } );
+		assertFalse( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 1, prog.exitCode );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void error3() throws Exception
+	{
+		// missing value for short option
+		main( new String[] { "-f" } );
+		assertFalse( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 1, prog.exitCode );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void error4() throws Exception
+	{
+		// missing value for long option
+		main( new String[] { "--foo" } );
+		assertFalse( prog.run );
+		assertFalse( cmdParseError );
+		assertEquals( 1, prog.exitCode );
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/core/io/TestPacketizer.java b/util/src/test/java/org/apache/etch/util/core/io/TestPacketizer.java
new file mode 100644
index 0000000..d63f728
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/core/io/TestPacketizer.java
@@ -0,0 +1,971 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.core.Who;
+import org.junit.Before;
+import org.junit.Test;
+
+
+/**
+ * JUnit Test for Packetizer
+ */
+public class TestPacketizer
+{
+	private final MyTransportData transport = new MyTransportData();
+	private final MySessionPacket session = new MySessionPacket();
+	private final Packetizer p = new Packetizer( transport, "tcp:", null );
+	private final Who who = new Who() { /* nothing */ };
+
+	/** setup test */
+	@Before
+	public void setUp()
+	{
+		p.setSession( session );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void connections() throws Exception
+	{
+		assertSame( transport, p.getTransport() );
+		assertSame( session, p.getSession() );
+		assertSame( p, transport.getSession() );
+	}
+
+	////////////////////////////////////////////////////////////////
+	// these tests are for packets delivered to the packet source //
+	////////////////////////////////////////////////////////////////
+
+	/** @throws Exception */
+	@Test
+	public void packet1() throws Exception
+	{
+		// Create empty packet to send
+		assert p.headerSize() == 8;
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// space for header:
+			0, 0, 0, 0, 0, 0, 0, 0
+		    // packet data:
+		} );
+		
+		// this is the result we expect.
+		byte[][] result = new byte[][]
+		{
+			{
+				// header:
+				-34, -83, -66, -17, 0, 0, 0, 0
+			    // packet data:
+			}
+		};
+
+		p.transportPacket( who, buf );
+		
+		assertSame( What.DATA, transport.what );
+		assertTrue( transport.check( result ) );
+		assertSame( who, transport.recipient );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void packet2() throws Exception
+	{
+		// Create 1 byte packet to send
+		assert p.headerSize() == 8;
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// space for header:
+		    0, 0, 0, 0, 0, 0, 0, 0,
+		    // packet data:
+		    1
+		} );
+		
+		// this is the result we expect.
+		byte[][] result = new byte[][]
+		{
+			{
+				// header:
+				-34, -83, -66, -17, 0, 0, 0, 1,
+			    // packet data:
+			    1
+			}
+		};
+
+		p.transportPacket( who, buf );
+		
+		assertSame( What.DATA, transport.what );
+		assertTrue( transport.check( result ) );
+		assertSame( who, transport.recipient );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void packet3() throws Exception
+	{
+		// Create 2 byte packet to send
+		assert p.headerSize() == 8;
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// space for header:
+		    0, 0, 0, 0, 0, 0, 0, 0,
+		    // packet data:
+		    2, 3
+		} );
+		
+		byte[][] result = new byte[][]
+		{
+			{
+				// header:
+				-34, -83, -66, -17, 0, 0, 0, 2,
+			    // packet data:
+			    2, 3
+			}
+		};
+
+		p.transportPacket( who, buf );
+		
+		assertSame( What.DATA, transport.what );
+		assertTrue( transport.check( result ) );
+		assertSame( who, transport.recipient );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void packet4() throws Exception
+	{
+		// Create too-small packet to send
+		assert p.headerSize() > 7;
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// space for header:
+			0, 0, 0, 0, 0, 0, 0 // too short!
+		    // packet data:
+		} );
+
+		p.transportPacket( who, buf );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void packet5() throws Exception
+	{
+		// Create too-small packet to send
+		assert p.headerSize() > 0;
+		FlexBuffer buf = new FlexBuffer( new byte[] {} );
+		p.transportPacket( who, buf );
+	}
+
+	/////////////////////////////////////////////
+	// these tests are for various bad packets //
+	/////////////////////////////////////////////
+
+	/** @throws Exception */
+	@Test( expected = IOException.class )
+	public void bad1() throws Exception
+	{
+		// Create data to send
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// packet header:
+			0, 0, 0, 0, 0, 0, 0, 0 // bad sig
+		    // packet data:
+		} );
+
+		p.sessionData( who, buf );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IOException.class )
+	public void bad2() throws Exception
+	{
+		// Create data to send
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// packet header:
+			1, 2, 3, 4, 0, 0, 0, 0 // bad sig
+		    // packet data:
+		} );
+
+		p.sessionData( who, buf );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IOException.class )
+	public void bad3() throws Exception
+	{
+		// Create data to send
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// packet header:
+			-34, -83, -66, -17, 0, 1, 0, 0 // size too big
+		    // packet data:
+		} );
+
+		p.sessionData( who, buf );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IOException.class )
+	public void bad4() throws Exception
+	{
+		// Create data to send
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// packet header:
+			-34, -83, -66, -17, -1, -1, -1, -1 // negative packet size
+		    // packet data:
+		} );
+
+		p.sessionData( who, buf );
+	}
+	
+	////////////////////////////////////////////////////////////
+	// these tests are for a single packet in a single buffer //
+	////////////////////////////////////////////////////////////
+
+	/** @throws Exception */
+	@Test
+	public void singleSingleData0() throws Exception
+	{
+		// Create data to send
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// packet header:
+			-34, -83, -66, -17, 0, 0, 0, 0
+		    // packet data:
+		} );
+
+		p.sessionData( who, buf );
+		
+		assertNull( session.what );
+		assertTrue( session.check( null ) );
+		assertNull( session.sender );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void singleSingleData1() throws Exception
+	{
+		// length = 1
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// packet header:
+			-34, -83, -66, -17, 0, 0, 0, 1,
+		    // packet data:
+		    1
+		} );
+		byte[][] result = new byte[][]
+		{
+			{
+			    // packet data:
+				1
+			}
+		};
+
+		p.sessionData( who, buf );
+
+		assertSame( What.PACKET, session.what );
+		assertTrue( session.check( result ) );
+		assertSame( who, session.sender );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void singleSingleData2() throws Exception
+	{
+		// length = 2
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// packet header:
+			-34, -83, -66, -17, 0, 0, 0, 2,
+		    // packet data:
+		    3, 4
+		} );
+		byte[][] result = new byte[][]
+		{
+			{
+			    // packet data:
+			    3, 4
+			}
+		};
+
+		p.sessionData( who, buf );
+
+		assertSame( What.PACKET, session.what );
+		assertTrue( session.check( result ) );
+		assertSame( who, session.sender );
+	}
+
+	// //////////////////////////////////////////////////////
+	// these tests are for two packets in a single buffer //
+	// //////////////////////////////////////////////////////
+
+	/** @throws Exception */
+	@Test
+	public void data1() throws Exception
+	{
+		// 2x length = 0
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// packet header:
+			-34, -83, -66, -17, 0, 0, 0, 0,
+			// packet header:
+			-34, -83, -66, -17, 0, 0, 0, 0
+		} );
+
+		p.sessionData( who, buf );
+
+		assertNull( session.what );
+		assertTrue( session.check( null ) );
+		assertNull( session.sender );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void data2() throws Exception
+	{
+		// length = 1, length = 0
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// packet 1 header:
+			-34, -83, -66, -17, 0, 0, 0, 1,
+		    // packet 1 data:
+		    1,
+			// packet 2 header:
+		    -34, -83, -66, -17, 0, 0, 0, 0,
+		    // packet 2 data:
+		} );
+		
+		byte[][] result = new byte[][]
+		{
+		    {
+			    // packet 1 data:
+			    1
+		    }
+		};
+
+		p.sessionData( who, buf );
+
+		assertSame( What.PACKET, session.what );
+		assertTrue( session.check( result ) );
+		assertSame( who, session.sender );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void data3() throws Exception
+	{
+		// length = 0, length = 1
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// packet 1 header:
+			-34, -83, -66, -17, 0, 0, 0, 0,
+		    // packet 1 data:
+			// packet 2 header:
+			-34, -83, -66, -17, 0, 0, 0, 1,
+		    // packet 2 data:
+		    2
+		} );
+		
+		byte[][] result = new byte[][]
+		{
+		    {
+			    // packet 2 data:
+			    2
+		    }
+		};
+
+		p.sessionData( who, buf );
+
+		assertSame( What.PACKET, session.what );
+		assertTrue( session.check( result ) );
+		assertSame( who, session.sender );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void data4() throws Exception
+	{
+		// 2x length = 1
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// packet 1 header:
+			-34, -83, -66, -17, 0, 0, 0, 1,
+		    // packet 1 data:
+		    1,
+			// packet 2 header:
+		    -34, -83, -66, -17, 0, 0, 0, 1,
+		    // packet 2 data:
+		    2
+		} );
+		
+		byte[][] result = new byte[][]
+		{
+		    {
+			    // packet 1 data:
+			    1
+		    },
+		    {
+			    // packet 2 data:
+			    2
+		    }
+		};
+
+		p.sessionData( who, buf );
+
+		assertSame( What.PACKET, session.what );
+		assertTrue( session.check( result ) );
+		assertSame( who, session.sender );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void doubleSingleData2() throws Exception
+	{
+		// length = 2
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// packet 1 header:
+			-34, -83, -66, -17, 0, 0, 0, 2,
+		    // packet 1 data:
+		    3, 4,
+			// packet 2 header:
+		    -34, -83, -66, -17, 0, 0, 0, 2,
+		    // packet 2 data:
+		    5, 6
+		} );
+		byte[][] result = new byte[][]
+		{
+		    {
+			    // packet 1 data:
+		        3, 4
+		    },
+		    {
+			    // packet 2 data:
+		        5, 6
+		    }
+		};
+
+		p.sessionData( who, buf );
+
+		assertSame( What.PACKET, session.what );
+		assertTrue( session.check( result ) );
+		assertSame( who, session.sender );
+	}
+
+	// ////////////////////////////////////////////////////////////////////
+	// these tests are for two packets in two buffers with header split //
+	// ////////////////////////////////////////////////////////////////////
+
+	/** @throws Exception */
+	@Test
+	public void doubleSingle_HeaderSplit_Data0() throws Exception
+	{
+		// length = 0
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// packet 1 header (partial):
+			-34, -83, -66, -17, 0, 0
+		} );
+
+		p.sessionData( who, buf );
+
+		assertNull( session.what );
+		assertTrue( session.check( null ) );
+		assertNull( session.sender );
+
+		FlexBuffer buf2 = new FlexBuffer( new byte[]
+		{
+			// packet 1 header (remainder):
+		    0, 0,
+			// packet 2 header
+		    -34, -83, -66, -17, 0, 0, 0, 0
+		} );
+
+		p.sessionData( null, buf2 );
+
+		assertNull( session.what );
+		assertTrue( session.check( null ) );
+		assertNull( session.sender );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void doubleSingle_HeaderSplit_Data1() throws Exception
+	{
+		// length = 1
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			// packet 1 header (partial):
+			-34, -83, -66, -17, 0, 0
+		} );
+
+		p.sessionData( who, buf );
+
+		assertNull( session.what );
+		assertTrue( session.check( null ) );
+		assertNull( session.sender );
+
+		FlexBuffer buf2 = new FlexBuffer( new byte[]
+		{
+			// packet 1 header (remainder):
+		    0, 1,
+		    // packet 1 data:
+		    1,
+			// packet 2 header:
+		    -34, -83, -66, -17, 0, 0, 0, 1,
+		    // packet 2 data:
+		    2
+		} );
+		
+		byte[][] result2 = new byte[][]
+		{
+		    {
+			    // packet 1 data:
+			    1
+		    },
+		    {
+			    // packet 2 data:
+			    2
+		    }
+		};
+
+		p.sessionData( who, buf2 );
+
+		assertSame( What.PACKET, session.what );
+		assertTrue( session.check( result2 ) );
+		assertSame( who, session.sender );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void doubleSingle_HeaderSplit_Data2() throws Exception
+	{
+		// length = 2
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			-34, -83, -66, -17, 0, 0
+		} );
+
+		p.sessionData( who, buf );
+
+		assertNull( session.what );
+		assertTrue( session.check( null ) );
+		assertNull( session.sender );
+
+		FlexBuffer buf2 = new FlexBuffer( new byte[]
+		{
+		    0, 2, 3, 4, -34, -83, -66, -17, 0, 0, 0, 2, 5, 6
+		} );
+		byte[][] result2 = new byte[][]
+		{
+		    {
+		        3, 4
+		    },
+		    {
+		        5, 6
+		    }
+		};
+
+		p.sessionData( null, buf2 );
+
+		assertSame( What.PACKET, session.what );
+		assertTrue( session.check( result2 ) );
+		assertNull( session.sender );
+	}
+
+	// //////////////////////////////////////////////////////////////////
+	// these tests are for two packets in two buffers with body split //
+	// //////////////////////////////////////////////////////////////////
+
+	/** @throws Exception */
+	@Test
+	public void doubleSingle_BodySplit_Data2() throws Exception
+	{
+		// length = 2
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			-34, -83, -66, -17, 0, 0, 0, 2, 1
+		} );
+
+		p.sessionData( who, buf );
+
+		assertNull( session.what );
+		assertTrue( session.check( null ) );
+		assertNull( session.sender );
+
+		FlexBuffer buf2 = new FlexBuffer( new byte[]
+		{
+		    2, -34, -83, -66, -17, 0, 0, 0, 2, 3, 4
+		} );
+		byte[][] result2 = new byte[][]
+		{
+		    {
+		        1, 2
+		    },
+		    {
+		        3, 4
+		    }
+		};
+
+		p.sessionData( null, buf2 );
+
+		assertSame( What.PACKET, session.what );
+		assertTrue( session.check( result2 ) );
+		assertNull( session.sender );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void doubleSingle_BodySplit_Data3() throws Exception
+	{
+		// length = 3
+		FlexBuffer buf = new FlexBuffer( new byte[]
+		{
+			-34, -83, -66, -17, 0, 0, 0, 3, 5, 6
+		} );
+
+		p.sessionData( who, buf );
+
+		assertNull( session.what );
+		assertTrue( session.check( null ) );
+		assertNull( session.sender );
+
+		FlexBuffer buf2 = new FlexBuffer( new byte[]
+		{
+		    7, -34, -83, -66, -17, 0, 0, 0, 3, 8, 9, 10
+		} );
+		byte[][] result2 = new byte[][]
+		{
+		    {
+		        5, 6, 7
+		    },
+		    {
+		        8, 9, 10
+		    }
+		};
+
+		p.sessionData( null, buf2 );
+
+		assertSame( What.PACKET, session.what );
+		assertTrue( session.check( result2 ) );
+		assertNull( session.sender );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void sessionQuery() throws Exception
+	{
+		Object QUERY = "foo";
+		Object RESULT = "bar";
+		
+		assertNull( session.what );
+		assertNull( session.query );
+		session.query_result = RESULT;
+		
+		Object result = p.sessionQuery( QUERY );
+
+		assertSame( What.SESSION_QUERY, session.what );
+		assertSame( QUERY, session.query );
+		assertSame( RESULT, result );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void sessionControl() throws Exception
+	{
+		Object CONTROL = "foo";
+		Object VALUE = "bar";
+		
+		assertNull( session.what );
+		assertNull( session.control );
+		assertNull( session.value );
+		
+		p.sessionControl( CONTROL, VALUE );
+
+		assertSame( What.SESSION_CONTROL, session.what );
+		assertSame( CONTROL, session.control );
+		assertSame( VALUE, session.value );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void sessionNotify() throws Exception
+	{
+		Object EVENT = "foo";
+		
+		assertNull( session.what );
+		assertNull( session.event );
+		
+		p.sessionNotify( EVENT );
+
+		assertSame( What.SESSION_NOTIFY, session.what );
+		assertSame( EVENT, session.event );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportQuery() throws Exception
+	{
+		Object QUERY = "foo";
+		Object RESULT = "bar";
+		
+		assertNull( transport.what );
+		assertNull( transport.query );
+		transport.query_result = RESULT;
+		
+		Object result = p.transportQuery( QUERY );
+
+		assertSame( What.TRANSPORT_QUERY, transport.what );
+		assertSame( QUERY, transport.query );
+		assertSame( RESULT, result );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportControl() throws Exception
+	{
+		Object CONTROL = "foo";
+		Object VALUE = "bar";
+		
+		assertNull( transport.what );
+		assertNull( transport.control );
+		assertNull( transport.value );
+		
+		p.transportControl( CONTROL, VALUE );
+
+		assertSame( What.TRANSPORT_CONTROL, transport.what );
+		assertSame( CONTROL, transport.control );
+		assertSame( VALUE, transport.value );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void transportNotify() throws Exception
+	{
+		Object EVENT = "foo";
+		
+		assertNull( transport.what );
+		assertNull( transport.event );
+		
+		p.transportNotify( EVENT );
+
+		assertSame( What.TRANSPORT_NOTIFY, transport.what );
+		assertSame( EVENT, transport.event );
+	}
+
+	/**
+	 * testing events.
+	 */
+	enum What
+	{
+		/** */ DATA,
+		/** */ PACKET,
+		/** */ SESSION_QUERY,
+		/** */ SESSION_CONTROL,
+		/** */ SESSION_NOTIFY,
+		/** */ TRANSPORT_QUERY,
+		/** */ TRANSPORT_CONTROL,
+		/** */ TRANSPORT_NOTIFY
+	};
+	
+	/**
+	 * Test jig
+	 */
+	public static class MyTransportData implements TransportData
+	{
+		/** */ public What what;
+		/** */ public Object query;
+		/** */ public Object query_result;
+		/** */ public Object control;
+		/** */ public Object value;
+		/** */ public Object event;
+		/** */ public Who recipient;
+		/** */ public List<byte[]> list = new ArrayList<byte[]>();
+		
+		public Object transportQuery( Object query ) throws Exception
+		{
+			what = What.TRANSPORT_QUERY;
+			this.query = query;
+			return query_result;
+		}
+
+		public void transportControl( Object control, Object value )
+			throws Exception
+		{
+			what = What.TRANSPORT_CONTROL;
+			this.control = control;
+			this.value = value;
+		}
+
+		public void transportNotify( Object event ) throws Exception
+		{
+			what = What.TRANSPORT_NOTIFY;
+			this.event = event;
+		}
+		
+		public void transportData( Who recipient, FlexBuffer buf )
+			throws Exception
+		{
+			what = What.DATA;
+			this.recipient = recipient;
+			list.add( buf.getAvailBytes() );
+		}
+
+		public SessionData getSession()
+		{
+			return session;
+		}
+
+		public void setSession( SessionData session )
+		{
+			this.session = session;
+		}
+		
+		private SessionData session;
+
+		// Auxiliary methods
+
+		/**
+		 * @param result
+		 * @return true if the result matches list.
+		 */
+		public boolean check( byte[][] result )
+		{
+			if (result == null)
+				return list.size() == 0;
+			
+			if (list.size() != result.length)
+				return false;
+
+			for (int i = 0; i < list.size(); i++)
+				if (!check( list.get( i ), result[i] ))
+					return false;
+			
+			return true;
+		}
+
+		private boolean check( byte[] a, byte[] b )
+		{
+			if (a.length != b.length)
+				return false;
+
+			for (int i = 0; i < a.length; i++)
+			{
+				if (a[i] != b[i])
+					return false;
+			}
+			
+			return true;
+		}
+	}
+
+	/**
+	 * A packet handler test jig.
+	 */
+	public static class MySessionPacket implements SessionPacket
+	{
+		/** */ public What what;
+		/** */ public Who sender;
+		/** */ public List<byte[]> list = new ArrayList<byte[]>();
+		/** */ public Object query;
+		/** */ public Object query_result;
+		/** */ public Object control;
+		/** */ public Object value;
+		/** */ public Object event;
+
+		// Auxiliary methods
+
+		/**
+		 * @param result
+		 * @return true if the result matches list.
+		 */
+		public boolean check( byte[][] result )
+		{
+			if (result == null)
+				return list.size() == 0;
+			
+			if (list.size() != result.length)
+				return false;
+
+			for (int i = 0; i < list.size(); i++)
+				if (!check( list.get( i ), result[i] ))
+					return false;
+			
+			return true;
+		}
+
+		private boolean check( byte[] a, byte[] b )
+		{
+			if (a.length != b.length)
+				return false;
+
+			for (int i = 0; i < a.length; i++)
+			{
+				if (a[i] != b[i])
+					return false;
+			}
+			
+			return true;
+		}
+
+		// PacketHandler methods
+
+		public void sessionPacket( Who sender, FlexBuffer buf )
+		    throws Exception
+		{
+			what = What.PACKET;
+			this.sender = sender;
+			list.add( buf.getAvailBytes() );
+
+		}
+
+		public Object sessionQuery( Object query )
+		{
+			what = What.SESSION_QUERY;
+			this.query = query;
+			return query_result;
+		}
+
+		public void sessionControl( Object control, Object value )
+		{
+			what = What.SESSION_CONTROL;
+			this.control = control;
+			this.value = value;
+		}
+
+		public void sessionNotify( Object event )
+		{
+			what = What.SESSION_NOTIFY;
+			this.event = event;
+		}
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/core/io/TestTcpConnection.java b/util/src/test/java/org/apache/etch/util/core/io/TestTcpConnection.java
new file mode 100644
index 0000000..b578244
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/core/io/TestTcpConnection.java
@@ -0,0 +1,768 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.Monitor;
+import org.apache.etch.util.core.Who;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+/**
+ * Tests TcpConnection.
+ */
+public class TestTcpConnection
+{
+	private final static MyListener lh = new MyListener();
+
+	private final static TcpListener l = new TcpListener( "tcp://0.0.0.0:0", null );
+
+	private static final int TIMEOUT = 4000;
+	
+	private static int port;
+
+	/** @throws Exception */
+	@BeforeClass
+	public static void startListener() throws Exception
+	{
+		l.setSession( lh );
+		
+		// start listener
+		l.start();
+		l.waitUp( TIMEOUT );
+		
+		port = ((InetSocketAddress) l.localAddress()).getPort();
+		
+		Log.addSink( null );
+		Log.report( "TestTcpConnection" );
+	}
+	
+	/** @throws Exception */
+	@AfterClass
+	public static void stopListener() throws Exception
+	{
+		l.stop();
+		l.waitDown( TIMEOUT );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor1() throws Exception
+	{
+		// no host or port
+		new TcpConnection( null, "tcp:", null );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void constructor2() throws Exception
+	{
+		Socket s = new Socket( "127.0.0.1", port );
+		Socket t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		TcpTransport c = new TcpConnection( s, "tcp:", null );
+		assertNull( c.getSession() );
+		
+		s.close();
+		t.close();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void constructor3() throws Exception
+	{
+		SessionData dh = new MyDataHandler();
+		Socket s = new Socket( "127.0.0.1", port );
+		Socket t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		TcpTransport c = new TcpConnection( s, "tcp:", null );
+		c.setSession( dh );
+		assertSame( dh, c.getSession() );
+		
+		s.close();
+		t.close();
+	}
+
+//	/** @throws Exception */
+//	@Test( expected = IllegalArgumentException.class )
+//	public void constructor4() throws Exception
+//	{
+//		// null host
+//		new TcpConnection( null, "tcp://0.0.0.0:1", null );
+//	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor5a() throws Exception
+	{
+		// no port
+		new TcpConnection( null, "tcp://localhost", null );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor5b() throws Exception
+	{
+		// zero port
+		new TcpConnection( null, "tcp://localhost:0", null );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor6() throws Exception
+	{
+		// too big port
+		new TcpConnection( null, "tcp://localhost:65536", null );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor7() throws Exception
+	{
+		// negative reconnect delay
+		new TcpConnection( null, "tcp://localhost:1?TcpTransport.reconnectDelay=-1", null );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void constructor8() throws Exception
+	{
+		TcpTransport c = new TcpConnection( null, "tcp://localhost:"+port, null );
+		assertNull( c.getSession() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void constructor9() throws Exception
+	{
+		SessionData dh = new MyDataHandler();
+		TcpTransport c = new TcpConnection( null, "tcp://localhost:"+port, null );
+		c.setSession( dh );
+		assertSame( dh, c.getSession() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start1() throws Exception
+	{
+		Socket s = new Socket( "127.0.0.1", port );
+		Socket t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		MyDataHandler dh = new MyDataHandler();
+		TcpTransport c = new TcpConnection( s, "tcp:", null );
+		c.setSession( dh );
+
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		c.waitUp( TIMEOUT );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		c.flush();
+		assertNotNull( c.remoteAddress() );
+		assertNotNull( c.localAddress() );
+		assertEquals( c.remoteAddress(), t.getLocalSocketAddress() );
+		assertEquals( c.localAddress(), t.getRemoteSocketAddress() );
+		
+		t.close();
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start2() throws Exception
+	{
+		Socket s = new Socket( "127.0.0.1", port );
+		Socket t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		MyDataHandler dh = new MyDataHandler();
+		TcpTransport c = new TcpConnection( s, "tcp:", null );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		assertTrue( c.isStarted() );
+		c.stop();
+		assertFalse( c.isStarted() );
+		
+		c.waitDown( TIMEOUT );
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start3() throws Exception
+	{
+		Socket s = new Socket( "127.0.0.1", port );
+		Socket t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		MyDataHandler dh = new MyDataHandler();
+		TcpTransport c = new TcpConnection( s, "tcp:", null );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		assertTrue( c.isStarted() );
+		c.close();
+		
+		c.waitDown( TIMEOUT );
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start4() throws Exception
+	{
+		Socket s = new Socket( "127.0.0.1", port );
+		Socket t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		MyDataHandler dh = new MyDataHandler();
+		TcpTransport c = new TcpConnection( s, "tcp:", null );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		assertTrue( c.isStarted() );
+		c.close( false );
+		
+		c.waitDown( TIMEOUT );
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start5() throws Exception
+	{
+		Socket s = new Socket( "127.0.0.1", port );
+		Socket t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		MyDataHandler dh = new MyDataHandler();
+		TcpTransport c = new TcpConnection( s, "tcp:", null );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		assertTrue( c.isStarted() );
+		c.close( true );
+		
+		c.waitDown( TIMEOUT );
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start6() throws Exception
+	{
+		MyDataHandler dh = new MyDataHandler();
+		TcpTransport c = new TcpConnection( null, "tcp://127.0.0.1:"+port, null );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		Socket t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		assertTrue( c.isStarted() );
+		c.stop();
+		assertFalse( c.isStarted() );
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void restart1() throws Exception
+	{
+		Log.report( "--- restart1 ------------------------------" );
+		
+		MyDataHandler dh = new MyDataHandler();
+		TcpTransport c = new TcpConnection( null, "tcp://127.0.0.1:"+port+"?TcpTransport.reconnectDelay=200", null );
+		c.setSession( dh );
+		
+		c.start();
+		c.waitUp( TIMEOUT );
+		
+		int n = 10;
+		int i = 0;
+		while (++i <= n)
+		{
+			Socket t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+
+			Log.report( "accepted", "i", i,
+				"t.local", t.getLocalSocketAddress(),
+				"t.remote", t.getRemoteSocketAddress() );
+			
+			assertWhat( What.UP, dh.what );
+			
+			assertEquals( t.getLocalSocketAddress(), c.remoteAddress() );
+			assertEquals( t.getRemoteSocketAddress(), c.localAddress() );
+			
+			t.getOutputStream().write( i );
+			assertWhat( What.DATA, dh.what );
+			assertNull( dh.xsender );
+			assertNotNull( dh.xbuf );
+			assertEquals( 1, dh.xbuf.length );
+			assertEquals( (byte) i, dh.xbuf[0] );
+
+			t.shutdownOutput();
+			t.close();
+			t = null;
+			
+			assertWhat( What.DOWN, dh.what );
+		}
+		
+		Thread t1 = new MonitorHarvester<Socket>( lh.accepted );
+		t1.start();
+		Thread t2 = new MonitorHarvester<What>( dh.what );
+		t2.start();
+
+		Log.report( "stopping" );
+		c.stop();
+		c.waitDown( TIMEOUT );
+		Log.report( "stoppped" );
+		
+		t1.join();
+		t2.join();
+	}
+	
+	/**
+	 * @param <T>
+	 */
+	public static class MonitorHarvester<T> extends Thread
+	{
+		/**
+		 * @param mon
+		 */
+		public MonitorHarvester( Monitor<T> mon )
+		{
+			this.mon = mon;
+		}
+		
+		private final Monitor<T> mon;
+
+		@Override
+		public void run()
+		{
+			try
+			{
+				Object t;
+				while ((t = mon.waitUntilNotEqAndSet( null, TIMEOUT, null )) != null)
+					Log.report( "harvested", "mon", mon, "t", t );
+			}
+			catch ( Exception e )
+			{
+				// ignore
+			}
+		}
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void restart2() throws Exception
+	{
+		Log.report( "--- restart2 ------------------------------" );
+		
+		MyDataHandler dh = new MyDataHandler();
+		TcpTransport c = new TcpConnection( null, "tcp://127.0.0.1:"+port+"?TcpTransport.reconnectDelay=200", null );
+		c.setSession( dh );
+		
+		c.start();
+		c.waitUp( TIMEOUT );
+		
+		int n = 10;
+		int i = 0;
+		while (++i <= n)
+		{
+//			Log.report( "--- waitAccepted" );
+			Socket t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+
+			Log.report( "accepted", "i", i,
+				"t.local", t.getLocalSocketAddress(),
+				"t.remote", t.getRemoteSocketAddress() );
+			
+			assertWhat( What.UP, dh.what );
+//			Log.report( "up", "c.local", c.localAddress(), "c.remote", c.remoteAddress() );
+			
+			assertEquals( t.getLocalSocketAddress(), c.remoteAddress() );
+			assertEquals( t.getRemoteSocketAddress(), c.localAddress() );
+			
+			t.getOutputStream().write( i );
+			assertWhat( What.DATA, dh.what );
+			assertNull( dh.xsender );
+			assertNotNull( dh.xbuf );
+			assertEquals( 1, dh.xbuf.length );
+			assertEquals( (byte) i, dh.xbuf[0] );
+
+//			Log.report( "c.shutingDownOutput" );
+			c.shutdownOutput();
+//			Log.report( "c.shutdownOutput" );
+			
+//			Log.report( "t.reading" );
+			assertEquals( -1, t.getInputStream().read() );
+//			Log.report( "t.eof" );
+			
+			t.shutdownOutput();
+			t.close();
+			t = null;
+			
+			assertWhat( What.DOWN, dh.what );
+//			Log.report( "down" );
+		}
+		
+		Thread t1 = new MonitorHarvester<Socket>( lh.accepted );
+		t1.start();
+		Thread t2 = new MonitorHarvester<What>( dh.what );
+		t2.start();
+		
+		Log.report( "stopping" );
+		c.stop();
+		c.waitDown( TIMEOUT );
+		Log.report( "stopped" );
+		
+		t1.join();
+		t2.join();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void data1() throws Exception
+	{
+		MyDataHandler dh = new MyDataHandler();
+		TcpTransport c = new TcpConnection( null, "tcp://127.0.0.1:"+port, null );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		Socket t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.getOutputStream().write( 23 );
+		t.getOutputStream().flush();
+		
+		assertWhat( What.DATA, dh.what );
+		assertNull( dh.xsender );
+		assertNotNull( dh.xbuf );
+		assertEquals( 1, dh.xbuf.length );
+		assertEquals( (byte) 23, dh.xbuf[0] );
+		
+		assertTrue( c.isStarted() );
+		c.stop();
+		assertFalse( c.isStarted() );
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void data2() throws Exception
+	{
+		MyDataHandler dh = new MyDataHandler();
+		TcpTransport c = new TcpConnection( null, "tcp://127.0.0.1:"+port, null );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		Socket t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		byte[] buf = { 21, 22, 23 };
+		
+		t.getOutputStream().write( buf );
+		t.getOutputStream().flush();
+		
+		assertWhat( What.DATA, dh.what );
+		assertNull( dh.xsender );
+		assertNotNull( dh.xbuf );
+		assertEquals( 3, dh.xbuf.length );
+		assertEquals( (byte) 21, dh.xbuf[0] );
+		assertEquals( (byte) 22, dh.xbuf[1] );
+		assertEquals( (byte) 23, dh.xbuf[2] );
+		
+		assertTrue( c.isStarted() );
+		c.stop();
+		assertFalse( c.isStarted() );
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void data3() throws Exception
+	{
+		MyDataHandler dh = new MyDataHandler();
+		TcpTransport c = new TcpConnection( null, "tcp://127.0.0.1:"+port, null );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		Socket t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.shutdownOutput();
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+		c.close();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void data4() throws Exception
+	{
+		MyDataHandler dh = new MyDataHandler();
+		TcpTransport c = new TcpConnection( null, "tcp://127.0.0.1:"+port, null );
+		c.setSession( dh );
+
+		c.start();
+		
+		Socket t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		c.transportData( null, new FlexBuffer( new byte[] { 21, 22, 23 } ) );
+		c.flush();
+		
+		InputStream is = t.getInputStream();
+		assertEquals( 21, is.read() );
+		assertEquals( 22, is.read() );
+		assertEquals( 23, is.read() );
+		
+		c.shutdownOutput();
+		
+		assertEquals( -1, is.read() );
+		
+		c.close();
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+	
+	private void assertWhat( What what, Monitor<What> mon )
+		throws Exception
+	{
+		mon.waitUntilEqAndSet( what, TIMEOUT, null );
+	}
+	
+	/**
+	 * Test events.
+	 */
+	enum What
+	{
+		/** connection is up */
+		UP,
+		/** connection is down */
+		DOWN,
+		/** connection read some data */
+		DATA
+	}
+
+	/**
+	 * ListenerHandler for testing.
+	 */
+	static class MyListener implements SessionListener<Socket>
+	{
+		/** monitor to report accepted socket */
+		public Monitor<Socket> accepted = new Monitor<Socket>( "accepted" );
+		
+		public void sessionAccepted( Socket s ) throws Exception
+		{
+//			Log.report( "listener.accepted",
+//				"s.local", s.getLocalSocketAddress(),
+//				"s.remote", s.getRemoteSocketAddress() );
+			
+			accepted.waitUntilEqAndSet( null, TIMEOUT, s );
+		}
+
+		public Object sessionQuery( Object query )
+		{
+			throw new UnsupportedOperationException( "unknown query "+query );
+		}
+
+		public void sessionControl( Object control, Object value )
+		{
+			throw new UnsupportedOperationException( "unknown control "+control );
+		}
+
+		public void sessionNotify( Object event )
+		{
+			if (event instanceof Exception)
+				Log.report( "listener.notify", "event", event );
+		}
+	}
+	
+	/**
+	 * DataHandler for testing.
+	 */
+	static class MyDataHandler implements SessionData
+	{
+		/** holds event type */
+		public Monitor<What> what = new Monitor<What>( "what" );
+
+		/** sender of the event if DATA */
+		public Who xsender;
+
+		/** data of the event if DATA */
+		public byte[] xbuf;
+		
+		public void sessionData( Who sender, FlexBuffer buf ) throws Exception
+		{
+			xsender = sender;
+			xbuf = buf.getAvailBytes();
+			what.waitUntilEqAndSet( null, TIMEOUT, What.DATA );
+		}
+
+		public Object sessionQuery( Object query ) throws Exception
+		{
+			throw new UnsupportedOperationException( "unknown query "+query );
+		}
+
+		public void sessionControl( Object control, Object value ) throws Exception
+		{
+			throw new UnsupportedOperationException( "unknown control "+control );
+		}
+
+		public void sessionNotify( Object event ) throws Exception
+		{
+//			Log.report( "data.notify", "event", event );
+			
+			if (event.equals( Session.UP ))
+			{
+				xbuf = null;
+				what.waitUntilEqAndSet( null, TIMEOUT, What.UP );
+				return;
+			}
+			
+			if (event.equals( Session.DOWN ))
+			{
+				xbuf = null;
+				what.waitUntilEqAndSet( null, TIMEOUT, What.DOWN );
+				return;
+			}
+			
+			Log.report( "data.notify", "event", event );
+		}
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/core/io/TestTcpListener.java b/util/src/test/java/org/apache/etch/util/core/io/TestTcpListener.java
new file mode 100644
index 0000000..34f393a
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/core/io/TestTcpListener.java
@@ -0,0 +1,408 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.net.InetSocketAddress;
+import java.net.Socket;
+
+import org.apache.etch.util.Monitor;
+import org.apache.etch.util.TimeoutException;
+import org.junit.Test;
+
+
+/**
+ * Tests Listener.
+ */
+public class TestTcpListener
+{
+	private final static int TIMEOUT = 4000;
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor1() throws Exception
+	{
+		// negative port
+		new TcpListener( "tcp://0.0.0.0:-1", null );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor2() throws Exception
+	{
+		// too positive port
+		new TcpListener( "tcp://0.0.0.0:65536", null );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor3() throws Exception
+	{
+		// negative backlog
+		new TcpListener( "tcp://0.0.0.0:0?TcpListener.backlog=-1", null );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void constructor6() throws Exception
+	{
+		MyListenerHandler lh = new MyListenerHandler();
+
+		TcpListener l = new TcpListener( "tcp://0.0.0.0:0", null );
+		l.setSession( lh );
+		
+		assertSame( lh, l.getSession() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void setHandler() throws Exception
+	{
+		MyListenerHandler lh = new MyListenerHandler();
+
+		TcpListener l = new TcpListener( "tcp://0.0.0.0:0", null );
+		assertNull( l.getSession() );
+
+		l.setSession( lh );
+		assertSame( lh, l.getSession() );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void stop1() throws Exception
+	{
+		TcpListener l = new TcpListener( "tcp://0.0.0.0:0", null );
+		l.stop(); // illegal state: not started.
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start1() throws Exception
+	{
+		MyListenerHandler lh = new MyListenerHandler();
+		
+		TcpListener l = new TcpListener( "tcp://0.0.0.0:0", null );
+		l.setSession( lh );
+		
+		assertWhat( null, lh.what );
+		assertNull( lh.xsocket );
+
+		l.start();
+		l.waitUp( TIMEOUT );
+
+		assertTrue( l.isStarted() );
+
+		assertWhat( What.UP, lh.what );
+		assertNull( lh.xsocket );
+
+		InetSocketAddress a = (InetSocketAddress) l.localAddress();
+		assertEquals( "0.0.0.0", a.getAddress().getHostAddress().toString() );
+		assertTrue( a.getPort() > 0 && a.getPort() < 65536 );
+
+		l.stop();
+		l.waitDown( TIMEOUT );
+
+		assertFalse( l.isStarted() );
+
+		assertWhat( What.DOWN, lh.what );
+		assertNull( lh.xsocket );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start2() throws Exception
+	{
+		MyListenerHandler lh = new MyListenerHandler();
+		TcpListener l = new TcpListener( "tcp://127.0.0.1:0", null );
+		l.setSession( lh );
+		
+		assertWhat( null, lh.what );
+		assertNull( lh.xsocket );
+
+		l.start();
+		l.waitUp( TIMEOUT );
+
+		assertTrue( l.isStarted() );
+
+		assertWhat( What.UP, lh.what );
+		assertNull( lh.xsocket );
+
+		InetSocketAddress a = (InetSocketAddress) l.localAddress();
+		assertEquals( "127.0.0.1", a.getAddress().getHostAddress().toString() );
+		assertTrue( a.getPort() > 0 && a.getPort() < 65536 );
+
+		l.stop();
+		l.waitDown( TIMEOUT );
+		assertFalse( l.isStarted() );
+		assertWhat( What.DOWN, lh.what );
+		assertNull( lh.xsocket );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start3() throws Exception
+	{
+		MyListenerHandler lh = new MyListenerHandler();
+		TcpListener l = new TcpListener( "tcp://0.0.0.0:4009", null );
+		l.setSession( lh );
+
+		assertWhat( null, lh.what );
+		assertNull( lh.xsocket );
+
+		l.start();
+		l.waitUp( TIMEOUT );
+		assertTrue( l.isStarted() );
+
+		assertWhat( What.UP, lh.what );
+		assertNull( lh.xsocket );
+
+		InetSocketAddress a = (InetSocketAddress) l.localAddress();
+		assertEquals( "0.0.0.0", a.getAddress().getHostAddress().toString() );
+		assertEquals( 4009, a.getPort() );
+
+		l.stop();
+		l.waitDown( TIMEOUT );
+
+		assertFalse( l.isStarted() );
+
+		assertWhat( What.DOWN, lh.what );
+		assertNull( lh.xsocket );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start4() throws Exception
+	{
+		MyListenerHandler lh = new MyListenerHandler();
+		TcpListener l = new TcpListener( "tcp://127.0.0.1:4006", null );
+		l.setSession( lh );
+
+		assertWhat( null, lh.what );
+		assertNull( lh.xsocket );
+
+		l.start();
+		l.waitUp( TIMEOUT );
+
+		assertTrue( l.isStarted() );
+
+		assertWhat( What.UP, lh.what );
+		assertNull( lh.xsocket );
+
+		InetSocketAddress a = (InetSocketAddress) l.localAddress();
+		assertEquals( "127.0.0.1", a.getAddress().getHostAddress().toString() );
+		assertEquals( 4006, a.getPort() );
+
+		l.stop();
+		l.waitDown( TIMEOUT );
+
+		assertFalse( l.isStarted() );
+
+		assertWhat( What.DOWN, lh.what );
+		assertNull( lh.xsocket );
+	}
+
+	/** @throws Exception */
+	@Test( expected = TimeoutException.class )
+	public void start5() throws Exception
+	{
+		MyListenerHandler lh = new MyListenerHandler();
+		TcpListener l = new TcpListener( "tcp://1.2.3.4.5:4007", null );
+		l.setSession( lh );
+
+		assertWhat( null, lh.what );
+		assertNull( lh.xsocket );
+
+		l.start();
+		l.waitUp( TIMEOUT );
+
+		assertTrue( l.isStarted() );
+
+		// this will timeout because of bad listening address.
+	}
+
+	/** @throws Exception */
+	@Test
+	public void accept1() throws Exception
+	{
+		MyListenerHandler lh = new MyListenerHandler();
+		TcpListener l = new TcpListener( "tcp://0.0.0.0:4008", null );
+		l.setSession( lh );
+
+		l.start();
+		l.waitUp( TIMEOUT );
+
+		Socket s = new Socket( "127.0.0.1", 4008 );
+		assertWhat( What.ACCEPTED, lh.what );
+		assertNotNull( lh.xsocket );
+
+		// verify they are connected to each other
+
+		assertEquals( s.getLocalSocketAddress(), lh.xsocket.getRemoteSocketAddress() );
+		assertEquals( s.getRemoteSocketAddress(), lh.xsocket.getLocalSocketAddress() );
+
+		// verify they can talk to each other
+
+		s.getOutputStream().write( 23 );
+		s.getOutputStream().flush();
+		assertEquals( 23, lh.xsocket.getInputStream().read() );
+
+		lh.xsocket.getOutputStream().write( 23 );
+		lh.xsocket.getOutputStream().flush();
+		assertEquals( 23, s.getInputStream().read() );
+
+		// shut 'em down.
+
+		s.close();
+		lh.xsocket.close();
+
+		l.stop();
+		l.waitDown( TIMEOUT );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void accept2() throws Exception
+	{
+		MyOtherListenerHandler lh = new MyOtherListenerHandler();
+		TcpListener l = new TcpListener( "tcp://0.0.0.0:0?TcpListener.backlog=100", null );
+		l.setSession( lh );
+
+		l.start();
+		l.waitUp( TIMEOUT );
+
+		int port = ((InetSocketAddress) l.localAddress()).getPort();
+
+		int n = 1000;
+
+		for (int i = 0; i < n; i++)
+			new Socket( "127.0.0.1", port ).close();
+
+		// wait for things to settle down...
+		Thread.sleep( 100 );
+
+		assertEquals( n, lh.accepted );
+
+		l.stop();
+		l.waitDown( TIMEOUT );
+	}
+
+	private void assertWhat( What what, Monitor<What> mon )
+		throws Exception
+	{
+		mon.waitUntilEqAndSet( what, 4000, null );
+	}
+
+	/**
+	 * Event types.
+	 */
+	enum What
+	{
+		/** the event seen was ACCEPTED */
+		ACCEPTED,
+		/** the event seen was UP */
+		UP,
+		/** the event seen was DOWN */
+		DOWN
+	}
+
+	/**
+	 * ListenerHandler for testing.
+	 */
+	public static class MyListenerHandler implements SessionListener<Socket>
+	{
+		/** the event seen */
+		public Monitor<What> what = new Monitor<What>( null );
+
+		/** the socket accepted (if accept) */
+		public Socket xsocket;
+
+		public void sessionAccepted( Socket socket ) throws Exception
+		{
+			xsocket = socket;
+			what.set( What.ACCEPTED );
+		}
+		
+		public Object sessionQuery( Object query )
+		{
+			throw new UnsupportedOperationException( "unknown query "+query );
+		}
+		
+		public void sessionControl( Object control, Object value )
+		{
+			throw new UnsupportedOperationException( "unknown control "+control );
+		}
+		
+		public void sessionNotify( Object event )
+		{
+			if (event.equals( Session.UP ))
+			{
+				what.set( What.UP );
+				return;
+			}
+			
+			if (event.equals( Session.DOWN ))
+			{
+				what.set( What.DOWN );
+				return;
+			}
+			
+			System.out.println("MyListenerHandler " + event);
+		}
+	}
+
+	/**
+	 * ListenerHandler for testing.
+	 */
+	public static class MyOtherListenerHandler implements SessionListener<Socket>
+	{
+		/** count of accepted connections. */
+		public int accepted;
+
+		public void sessionAccepted( Socket socket ) throws Exception
+		{
+			accepted++;
+			socket.close();
+		}
+
+		public void sessionControl( Object control, Object value )
+			throws Exception
+		{
+			// ignore
+		}
+
+		public void sessionNotify( Object event ) throws Exception
+		{
+			// ignore
+		}
+
+		public Object sessionQuery( Object query ) throws Exception
+		{
+			// ignore
+			return null;
+		}
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/core/io/TestUdpConnection.java b/util/src/test/java/org/apache/etch/util/core/io/TestUdpConnection.java
new file mode 100644
index 0000000..f3888c5
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/core/io/TestUdpConnection.java
@@ -0,0 +1,158 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.io;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.core.Who;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+
+/** Test UdpConnection. */
+public class TestUdpConnection
+{
+	/** @throws Exception */
+	@Before @Ignore
+	public void init() throws Exception
+	{
+		aph = new MyPacketHandler();
+		ac = new UdpConnection( "udp://localhost:4011", null );
+		ac.setSession( aph );
+		ac.start();
+		ac.waitUp( 4000 );
+		System.out.println( "ac up" );
+		
+		bph = new MyPacketHandler();
+		bc = new UdpConnection( "udp://localhost:4010", null );
+		bc.setSession( bph );
+		bc.start();
+		bc.waitUp( 4000 );
+		System.out.println( "bc up" );
+	}
+	
+	/** @throws Exception */
+	@After @Ignore
+	public void fini() throws Exception
+	{
+		ac.close( false );
+		bc.close( false );
+	}
+	
+	private MyPacketHandler aph;
+	
+	private UdpConnection ac;
+	
+	private MyPacketHandler bph;
+	
+	private UdpConnection bc;
+	
+	/** @throws Exception */
+	@Test @Ignore
+	public void blah() throws Exception
+	{
+		assertEquals( What.UP, aph.what );
+		assertEquals( What.UP, bph.what );
+		FlexBuffer buf = new FlexBuffer();
+		buf.put( 1 );
+		buf.put( 2 );
+		buf.put( 3 );
+		buf.put( 4 );
+		buf.put( 5 );
+		buf.setIndex( 0 );
+		ac.transportPacket( null, buf );
+		Thread.sleep( 500 );
+		assertEquals( What.PACKET, bph.what );
+		assertNotNull( bph.xsender );
+		assertNotSame( buf, bph.xbuf );
+		assertEquals( 0, bph.xbuf.index() );
+		assertEquals( 5, bph.xbuf.length() );
+		assertEquals( 1, bph.xbuf.get() );
+		assertEquals( 2, bph.xbuf.get() );
+		assertEquals( 3, bph.xbuf.get() );
+		assertEquals( 4, bph.xbuf.get() );
+		assertEquals( 5, bph.xbuf.get() );
+	}
+	
+	/** */
+	public enum What
+	{
+		/** */ UP,
+		/** */ PACKET,
+		/** */ DOWN
+	}
+	
+	/**
+	 * receive packets from the udp connection
+	 */
+	public static class MyPacketHandler implements SessionPacket
+	{
+		/** */
+		public What what;
+		/** */
+		public Who xsender;
+		/** */
+		public FlexBuffer xbuf;
+
+		public void sessionPacket( Who sender, FlexBuffer buf ) throws Exception
+		{
+			assertEquals( What.UP, what );
+			what = What.PACKET;
+			xsender = sender;
+			xbuf = buf;
+		}
+
+		public void sessionControl( Object control, Object value )
+		{
+			// ignore.
+		}
+
+		public void sessionNotify( Object event )
+		{
+			if (event.equals( Session.UP ))
+			{
+				assertNull( what );
+				what = What.UP;
+				return;
+			}
+			
+			if (event.equals( Session.DOWN ))
+			{
+				assertTrue( what == What.UP || what == What.PACKET );
+				what = What.DOWN;
+				return;
+			}
+		}
+
+		public Object sessionQuery( Object query )
+		{
+			// ignore.
+			return null;
+		}
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/core/nio/TestByteBufferPool.java b/util/src/test/java/org/apache/etch/util/core/nio/TestByteBufferPool.java
new file mode 100644
index 0000000..a83ef5d
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/core/nio/TestByteBufferPool.java
@@ -0,0 +1,287 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.apache.etch.util.core.nio.ByteBufferPool.Notify;
+import org.junit.Test;
+
+
+
+
+/** Test of ByteBufferPool */
+public class TestByteBufferPool
+{
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void construct1() throws Exception
+	{
+		// bufferSize <= 0
+		new ByteBufferPool( -1, -1, -1, -1, -1 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void construct2() throws Exception
+	{
+		// bufferSize <= 0
+		new ByteBufferPool( 0, -1, -1, -1, -1 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void construct3() throws Exception
+	{
+		// historyInterval < 0
+		new ByteBufferPool( 4096, -1, -1, -1, -1 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void construct4() throws Exception
+	{
+		// min < 0
+		new ByteBufferPool( 4096, -1, -1, 0, -1 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void construct5() throws Exception
+	{
+		// limit < min
+		new ByteBufferPool( 4096, 0, -1, 0, -1 );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void construct6() throws Exception
+	{
+		// len < 0
+		new ByteBufferPool( 4096, 0, 10, 1, -1 );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void construct7() throws Exception
+	{
+		ByteBufferPool p = new ByteBufferPool( 1, 2, 3, 4, 5 );
+		assertEquals( 1, p.bufferSize() );
+		assertEquals( 2, p.min() );
+		assertEquals( 3, p.limit() );
+		assertEquals( 4, p.interval() );
+		assertEquals( 5, p.length() );
+		p.shutdown();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void construct8() throws Exception
+	{
+		ByteBufferPool p = new ByteBufferPool( 101, 103, 105, 107, 109 );
+		assertEquals( 101, p.bufferSize() );
+		assertEquals( 103, p.min() );
+		assertEquals( 105, p.limit() );
+		assertEquals( 107, p.interval() );
+		assertEquals( 109, p.length() );
+		p.shutdown();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void construct9() throws Exception
+	{
+		ByteBufferPool p = new ByteBufferPool( 101, 103, 105, 0, 109 );
+		assertEquals( 101, p.bufferSize() );
+		assertEquals( 103, p.min() );
+		assertEquals( 105, p.limit() );
+		assertEquals( 0, p.interval() );
+		assertEquals( 0, p.length() );
+		p.shutdown();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void construct10() throws Exception
+	{
+		ByteBufferPool p = new ByteBufferPool( 101, 103, 105, 107, 0 );
+		assertEquals( 101, p.bufferSize() );
+		assertEquals( 103, p.min() );
+		assertEquals( 105, p.limit() );
+		assertEquals( 0, p.interval() );
+		assertEquals( 0, p.length() );
+		p.shutdown();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void construct11() throws Exception
+	{
+		ByteBufferPool p = new ByteBufferPool( 101, 103, 105, 0, 0 );
+		assertEquals( 101, p.bufferSize() );
+		assertEquals( 103, p.min() );
+		assertEquals( 105, p.limit() );
+		assertEquals( 0, p.interval() );
+		assertEquals( 0, p.length() );
+		p.shutdown();
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void alloc1() throws Exception
+	{
+		ByteBufferPool p = new ByteBufferPool( 4096, 0, 10, 0, 0 );
+		ByteBuffer b = p.alloc( null );
+		assertNotNull( b );
+		assertEquals( 4096, b.limit() );
+		assertEquals( 1, p.used() );
+		p.release( b );
+		assertEquals( 0, p.used() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void alloc2() throws Exception
+	{
+		ByteBufferPool p = new ByteBufferPool( 1024, 0, 10, 0, 0 );
+		ByteBuffer b = p.alloc( null );
+		assertNotNull( b );
+		assertEquals( 1024, b.limit() );
+		assertEquals( 1, p.used() );
+		p.release( b );
+		assertEquals( 0, p.used() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void alloc3() throws Exception
+	{
+		ByteBufferPool p = new ByteBufferPool( 4096, 0, 10, 0, 0 );
+		ByteBuffer[] b = p.alloc( null, 2 );
+		assertNotNull( b );
+		assertEquals( 2, b.length );
+		assertNotNull( b[0] );
+		assertEquals( 4096, b[0].limit() );
+		assertNotNull( b[1] );
+		assertEquals( 4096, b[1].limit() );
+		assertEquals( 2, p.used() );
+		p.release( b );
+		assertEquals( 0, p.used() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IOException.class )
+	public void alloc4() throws Exception
+	{
+		// out of buffers
+		ByteBufferPool p = new ByteBufferPool( 1024, 0, 1, 0, 0 );
+		p.alloc( null );
+		p.alloc( null );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void alloc5() throws Exception
+	{
+		// slower because of no pooling.
+		ByteBufferPool p = new ByteBufferPool( 1024, 0, 1, 0, 0 );
+		for (int i = 0; i < 100000; i++)
+			p.release( p.alloc( null ) );
+		assertEquals( 0, p.used() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void alloc6() throws Exception
+	{
+		// faster because of pooling.
+		ByteBufferPool p = new ByteBufferPool( 1024, 1, 1, 0, 0 );
+		for (int i = 0; i < 100000; i++)
+			p.release( p.alloc( null ) );
+		assertEquals( 0, p.used() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void notify1() throws Exception
+	{
+		ByteBufferPool p = new ByteBufferPool( 1024, 1, 1, 0, 0 );
+		MyNotify n1 = new MyNotify();
+		MyNotify n2 = new MyNotify();
+		
+		ByteBuffer b1 = p.alloc( n1 );
+		assertNotNull( b1 );
+		assertEquals( 1, p.used() );
+		Thread.sleep( 15 );
+		assertFalse( n1.available );
+		assertFalse( n2.available );
+		
+		ByteBuffer b2 = p.alloc( n2 );
+		assertNull( b2 );
+		assertEquals( 1, p.used() );
+		Thread.sleep( 15 );
+		assertFalse( n1.available );
+		assertFalse( n2.available );
+		
+		// the alloc of b2 failed, but n2 should be registered to be notified
+		// when a block is freed. release of b1 should notify n2 of availability
+		
+		p.release( b1 );
+		b1 = null;
+		assertEquals( 0, p.used() );
+		Thread.sleep( 15 );
+		assertFalse( n1.available );
+		assertTrue( n2.available );
+		
+		n2.available = false;
+		b2 = p.alloc( n2 );
+		assertNotNull( b2 );
+		assertEquals( 1, p.used() );
+		Thread.sleep( 15 );
+		assertFalse( n1.available );
+		assertFalse( n2.available );
+		
+		p.release( b2 );
+		b2 = null;
+		assertEquals( 0, p.used() );
+		Thread.sleep( 15 );
+		assertFalse( n1.available );
+		assertFalse( n2.available );
+	}
+	
+	/** */
+	public static class MyNotify implements Notify
+	{
+		/** */
+		public boolean available;
+		public void bufferAvailable( ByteBufferPool pool )
+		{
+			available = true;
+		}
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/core/nio/TestHistory.java b/util/src/test/java/org/apache/etch/util/core/nio/TestHistory.java
new file mode 100644
index 0000000..d4174d0
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/core/nio/TestHistory.java
@@ -0,0 +1,439 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+
+
+
+/** Test of History */
+public class TestHistory
+{
+	/** @throws Exception */
+	@Test
+	public void construct1() throws Exception
+	{
+		History h = new History( 1, 2, 3 );
+		assertEquals( 1, h.min() );
+		assertEquals( 2, h.limit() );
+		assertEquals( 3, h.length() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void construct2() throws Exception
+	{
+		History h = new History( 102, 119, 7 );
+		assertEquals( 102, h.min() );
+		assertEquals( 119, h.limit() );
+		assertEquals( 7, h.length() );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void construct3() throws Exception
+	{
+		// min < 0
+		new History( -1, 2, 3 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void construct4() throws Exception
+	{
+		// limit < min
+		new History( 0, -1, 3 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void construct5() throws Exception
+	{
+		// len < 0
+		new History( 0, 0, -1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void used1() throws Exception
+	{
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		assertTrue( h.used( 1 ) );
+		checkUsedAlloc( h, 1, 0 );
+		assertTrue( h.used( -1 ) );
+		checkUsedAlloc( h, 0, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void used2() throws Exception
+	{
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		assertTrue( h.used( 2 ) );
+		checkUsedAlloc( h, 2, 0 );
+		assertTrue( h.used( -2 ) );
+		checkUsedAlloc( h, 0, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void used3() throws Exception
+	{
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		assertTrue( h.used( 1 ) );
+		checkUsedAlloc( h, 1, 0 );
+		assertTrue( h.used( 1 ) );
+		checkUsedAlloc( h, 2, 0 );
+		assertTrue( h.used( -1 ) );
+		checkUsedAlloc( h, 1, 0 );
+		assertTrue( h.used( -1 ) );
+		checkUsedAlloc( h, 0, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void used4() throws Exception
+	{
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		// try to overflow
+		assertFalse( h.used( 11 ) );
+		checkUsedAlloc( h, 0, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void used5() throws Exception
+	{
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		assertTrue( h.used( 1 ) );
+		checkUsedAlloc( h, 1, 0 );
+		assertTrue( h.used( 9 ) );
+		checkUsedAlloc( h, 10, 0 );
+		// try to overflow
+		assertFalse( h.used( 1 ) );
+		checkUsedAlloc( h, 10, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void used6() throws Exception
+	{
+		// newUsed < 0
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		h.used( -1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void used7() throws Exception
+	{
+		// newUsed < 0
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		h.used( 1 );
+		checkUsedAlloc( h, 1, 0 );
+		h.used( -2 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void used8() throws Exception
+	{
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		h.used( 1 );
+		checkUsedAlloc( h, 1, 0 );
+		try
+		{
+			h.used( -2 );
+			fail( "never reached" );
+		}
+		catch ( IllegalStateException e )
+		{
+			// make sure used was not adjusted...
+			checkUsedAlloc( h, 1, 0 );
+		}
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void used9() throws Exception
+	{
+		// k == 0
+		History h = new History( 0, 10, 5 );
+		h.used( 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void alloc1() throws Exception
+	{
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		h.alloc( 1 );
+		checkUsedAlloc( h, 0, 1 );
+		h.alloc( -1 );
+		checkUsedAlloc( h, 0, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void alloc2() throws Exception
+	{
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		h.alloc( 2 );
+		checkUsedAlloc( h, 0, 2 );
+		h.alloc( -2 );
+		checkUsedAlloc( h, 0, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void alloc3() throws Exception
+	{
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		h.alloc( 1 );
+		checkUsedAlloc( h, 0, 1 );
+		h.alloc( 1 );
+		checkUsedAlloc( h, 0, 2 );
+		h.alloc( -1 );
+		checkUsedAlloc( h, 0, 1 );
+		h.alloc( -1 );
+		checkUsedAlloc( h, 0, 0 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void alloc4() throws Exception
+	{
+		// newAlloc > limit
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		// try to overflow
+		h.alloc( 11 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void alloc5() throws Exception
+	{
+		// newAlloc > limit
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		h.alloc( 1 );
+		checkUsedAlloc( h, 0, 1 );
+		h.alloc( 9 );
+		checkUsedAlloc( h, 0, 10 );
+		// try to overflow
+		h.alloc( 1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void alloc6() throws Exception
+	{
+		// newAlloc < 0
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		// try to underflow
+		h.alloc( -1 );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void alloc7() throws Exception
+	{
+		// newAlloc < 0
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		h.alloc( 1 );
+		checkUsedAlloc( h, 0, 1 );
+		// try to underflow
+		h.alloc( -2 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void alloc8() throws Exception
+	{
+		History h = new History( 0, 10, 5 );
+		checkUsedAlloc( h, 0, 0 );
+		h.alloc( 1 );
+		checkUsedAlloc( h, 0, 1 );
+		try
+		{
+			// try to underflow
+			h.alloc( -2 );
+			fail( "never reached" );
+		}
+		catch ( IllegalStateException e )
+		{
+			// make sure alloc was not adjusted...
+			checkUsedAlloc( h, 0, 1 );
+		}
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void alloc9() throws Exception
+	{
+		// k == 0
+		History h = new History( 0, 10, 5 );
+		h.alloc( 0 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void suggested1() throws Exception
+	{
+		History h = new History( 0, 10, 5 );
+		assertEquals( 0, h.suggested() );
+		h.tickle();
+		assertEquals( 0, h.suggested() );
+		h.init();
+		assertEquals( 0, h.suggested() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void suggested2() throws Exception
+	{
+		History h = new History( 2, 10, 5 );
+		assertEquals( 2, h.suggested() );
+		h.tickle();
+		assertEquals( 2, h.suggested() );
+		h.init();
+		assertEquals( 2, h.suggested() );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void suggested3() throws Exception
+	{
+		History h = new History( 0, 10, 5 );
+		assertEquals( 0, h.suggested() );
+		
+		assertTrue( h.used( 10 ) );
+		assertEquals( 10, h.getUsed() );
+		
+		assertEquals( 0, h.suggested() ); // avg(0, 0, 0, 0, 0) == 0
+		h.tickle();
+		assertEquals( 2, h.suggested() ); // avg(10, 0, 0, 0, 0) == 2
+		h.tickle();
+		assertEquals( 4, h.suggested() ); // avg(10, 10, 0, 0, 0) == 4
+		h.tickle();
+		assertEquals( 6, h.suggested() ); // avg(10, 10, 10, 0, 0) == 6
+		h.tickle();
+		assertEquals( 8, h.suggested() ); // avg(10, 10, 10, 10, 0) == 8
+		h.tickle();
+		assertEquals( 10, h.suggested() ); // avg(10, 10, 10, 10, 10) == 10
+		h.tickle();
+		assertEquals( 10, h.suggested() ); // avg(10, 10, 10, 10, 10) == 10
+		
+		assertTrue( h.used( -10 ) );
+		assertEquals( 0, h.getUsed() );
+		
+		h.tickle();
+		assertEquals( 10, h.suggested() ); // avg(10, 10, 10, 10, 10) == 10
+		h.tickle();
+		assertEquals( 8, h.suggested() ); // avg(0, 10, 10, 10, 10) == 8
+		h.tickle();
+		assertEquals( 6, h.suggested() ); // avg(0, 0, 10, 10, 10) == 6
+		h.tickle();
+		assertEquals( 4, h.suggested() ); // avg(0, 0, 0, 10, 10) == 4
+		h.tickle();
+		assertEquals( 2, h.suggested() ); // avg(0, 0, 0, 0, 10) == 2
+		h.tickle();
+		assertEquals( 0, h.suggested() ); // avg(0, 0, 0, 0, 0) == 0
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void suggested4() throws Exception
+	{
+		History h = new History( 2, 10, 5 );
+		assertEquals( 2, h.suggested() );
+		
+		assertTrue( h.used( 10 ) );
+		assertEquals( 10, h.getUsed() );
+		
+		assertEquals( 2, h.suggested() ); // avg(2, 2, 2, 2, 2) == 2
+		h.tickle();
+		assertEquals( 3, h.suggested() ); // avg(10, 2, 2, 2, 2) == 3
+		h.tickle();
+		assertEquals( 5, h.suggested() ); // avg(10, 10, 2, 2, 2) == 5
+		h.tickle();
+		assertEquals( 6, h.suggested() ); // avg(10, 10, 10, 2, 2) == 6
+		h.tickle();
+		assertEquals( 8, h.suggested() ); // avg(10, 10, 10, 10, 2) == 8
+		h.tickle();
+		assertEquals( 10, h.suggested() ); // avg(10, 10, 10, 10, 10) == 10
+		h.tickle();
+		assertEquals( 10, h.suggested() ); // avg(10, 10, 10, 10, 10) == 10
+		
+		assertTrue( h.used( -10 ) );
+		assertEquals( 0, h.getUsed() );
+		
+		h.tickle();
+		assertEquals( 10, h.suggested() ); // avg(10, 10, 10, 10, 10) == 10
+		h.tickle();
+		assertEquals( 8, h.suggested() ); // avg(2, 10, 10, 10, 10) == 8
+		h.tickle();
+		assertEquals( 6, h.suggested() ); // avg(2, 2, 10, 10, 10) == 6
+		h.tickle();
+		assertEquals( 5, h.suggested() ); // avg(2, 2, 2, 10, 10) == 5
+		h.tickle();
+		assertEquals( 3, h.suggested() ); // avg(2, 2, 2, 2, 10) == 3
+		h.tickle();
+		assertEquals( 2, h.suggested() ); // avg(2, 2, 2, 2, 2) == 2
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void suggested5() throws Exception
+	{
+		History h = new History( 0, 10, 0 );
+		assertEquals( 0, h.suggested() );
+		assertTrue( h.used( 5 ) );
+		assertEquals( 0, h.suggested() );
+		h.tickle();
+		assertEquals( 0, h.suggested() );
+	}
+	
+	private void checkUsedAlloc( History h, int u, int a )
+	{
+		assertEquals( u, h.getUsed() );
+		assertEquals( a, h.getAlloc() );
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/core/nio/TestTcp2Connection.java b/util/src/test/java/org/apache/etch/util/core/nio/TestTcp2Connection.java
new file mode 100644
index 0000000..8161f84
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/core/nio/TestTcp2Connection.java
@@ -0,0 +1,842 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+
+import org.apache.etch.util.FlexBuffer;
+import org.apache.etch.util.Log;
+import org.apache.etch.util.Monitor;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.core.Who;
+import org.apache.etch.util.core.io.Session;
+import org.apache.etch.util.core.io.SessionData;
+import org.apache.etch.util.core.io.SessionListener;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+/**
+ * Tests Tcp2Connection.
+ */
+public class TestTcp2Connection
+{
+	private final static MyListener lh = new MyListener();
+
+	private final static int TIMEOUT = 4000;
+	
+	private final static SuperSelector selector = new SuperSelector();
+	static
+	{
+		selector.start();
+	}
+	
+	private final static ByteBufferPool pool = new ByteBufferPool(1024, 10, 1000, 0, 0 );
+	
+	private final static Resources r = new Resources();
+	static
+	{
+		r.put( "bufferPool", pool );
+		r.put( "selector", selector );
+	}
+
+	private final static Tcp2Listener l = new Tcp2Listener( "tcp://0.0.0.0:0", r );
+	
+	private static int port;
+
+	/** @throws Exception */
+	@BeforeClass
+	public static void startListener() throws Exception
+	{
+		l.setSession( lh );
+		
+		// start listener
+		l.start();
+		l.waitUp( TIMEOUT );
+		
+		port = ((InetSocketAddress) l.localAddress()).getPort();
+		
+		Log.addSink( null );
+		Log.report( "TestTcp2Connection" );
+	}
+	
+	/** @throws Exception */
+	@AfterClass
+	public static void stopListener() throws Exception
+	{
+		l.stop();
+		l.waitDown( TIMEOUT );
+	}
+	
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor1() throws Exception
+	{
+		// no host or port
+		new Tcp2Connection( "tcp:", r );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void constructor2() throws Exception
+	{
+		SocketChannel s = newSocketChannel( "127.0.0.1", port );
+		SocketChannel t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		r.put( "connection", s );
+		Tcp2Connection c = new Tcp2Connection( "tcp:", r );
+		assertNull( c.getSession() );
+		
+		s.close();
+		t.close();
+	}
+
+	private static SocketChannel newSocketChannel( String host, int port )
+		throws IOException
+	{
+		return SocketChannel.open( new InetSocketAddress( host, port )  );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void constructor3() throws Exception
+	{
+		SessionData dh = new MyDataHandler();
+		SocketChannel s = newSocketChannel( "127.0.0.1", port );
+		SocketChannel t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+
+		r.put( "connection", s );
+		Tcp2Connection c = new Tcp2Connection( "tcp:", r );
+		c.setSession( dh );
+		assertSame( dh, c.getSession() );
+		
+		s.close();
+		t.close();
+	}
+
+//	/** @throws Exception */
+//	@Test( expected = IllegalArgumentException.class )
+//	public void constructor4() throws Exception
+//	{
+//		// null host
+//		new Tcp2Connection( "tcp://0.0.0.0:1", null );
+//	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor5a() throws Exception
+	{
+		// no port
+		new Tcp2Connection( "tcp://localhost", r );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor5b() throws Exception
+	{
+		// zero port
+		new Tcp2Connection( "tcp://localhost:0", r );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor6() throws Exception
+	{
+		// too big port
+		new Tcp2Connection( "tcp://localhost:65536", r );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor7() throws Exception
+	{
+		// negative reconnect delay
+		new Tcp2Connection( "tcp://localhost:1?TcpTransport.reconnectDelay=-1", r );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void constructor8() throws Exception
+	{
+		Tcp2Connection c = new Tcp2Connection( "tcp://localhost:"+port, r );
+		assertNull( c.getSession() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void constructor9() throws Exception
+	{
+		SessionData dh = new MyDataHandler();
+		Tcp2Connection c = new Tcp2Connection( "tcp://localhost:"+port, r );
+		c.setSession( dh );
+		assertSame( dh, c.getSession() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start1() throws Exception
+	{
+		SocketChannel s = newSocketChannel( "127.0.0.1", port );
+		SocketChannel t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		MyDataHandler dh = new MyDataHandler();
+		
+		r.put( "connection", s );
+		Tcp2Connection c = new Tcp2Connection( "tcp:", r );
+		c.setSession( dh );
+
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		c.waitUp( TIMEOUT );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+//		c.flush();
+		assertNotNull( c.remoteAddress() );
+		assertNotNull( c.localAddress() );
+		assertEquals( c.remoteAddress(), t.socket().getLocalSocketAddress() );
+		assertEquals( c.localAddress(), t.socket().getRemoteSocketAddress() );
+		
+		t.close();
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start2() throws Exception
+	{
+		SocketChannel s = newSocketChannel( "127.0.0.1", port );
+		SocketChannel t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		MyDataHandler dh = new MyDataHandler();
+
+		r.put( "connection", s );
+		Tcp2Connection c = new Tcp2Connection( "tcp:", r );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		assertTrue( c.isStarted() );
+		c.stop();
+		assertFalse( c.isStarted() );
+		
+		c.waitDown( TIMEOUT );
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start3() throws Exception
+	{
+		SocketChannel s = newSocketChannel( "127.0.0.1", port );
+		SocketChannel t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		MyDataHandler dh = new MyDataHandler();
+
+		r.put( "connection", s );
+		Tcp2Connection c = new Tcp2Connection( "tcp:", r );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		assertTrue( c.isStarted() );
+		c.close();
+		
+		c.waitDown( TIMEOUT );
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start4() throws Exception
+	{
+		SocketChannel s = newSocketChannel( "127.0.0.1", port );
+		SocketChannel t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		MyDataHandler dh = new MyDataHandler();
+
+		r.put( "connection", s );
+		Tcp2Connection c = new Tcp2Connection( "tcp:", r );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		assertTrue( c.isStarted() );
+		c.close( false );
+		
+		c.waitDown( TIMEOUT );
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start5() throws Exception
+	{
+		SocketChannel s = newSocketChannel( "127.0.0.1", port );
+		SocketChannel t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		MyDataHandler dh = new MyDataHandler();
+
+		r.put( "connection", s );
+		Tcp2Connection c = new Tcp2Connection( "tcp:", r );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		assertTrue( c.isStarted() );
+		c.close( true );
+		
+		c.waitDown( TIMEOUT );
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start6() throws Exception
+	{
+		MyDataHandler dh = new MyDataHandler();
+		
+		Tcp2Connection c = new Tcp2Connection( "tcp://127.0.0.1:"+port, r );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		SocketChannel t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		assertTrue( c.isStarted() );
+		c.stop();
+		assertFalse( c.isStarted() );
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void restart1() throws Exception
+	{
+		Log.report( "--- restart1 ------------------------------" );
+		
+		MyDataHandler dh = new MyDataHandler();
+		
+		Tcp2Connection c = new Tcp2Connection( "tcp://127.0.0.1:"+port+"?TcpTransport.reconnectDelay=200", r );
+		c.setSession( dh );
+		
+		c.start();
+		c.waitUp( TIMEOUT );
+		
+		int n = 10;
+		int i = 0;
+		while (++i <= n)
+		{
+			SocketChannel t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+
+			Log.report( "accepted", "i", i,
+				"t.local", t.socket().getLocalSocketAddress(),
+				"t.remote", t.socket().getRemoteSocketAddress() );
+			
+			assertWhat( What.UP, dh.what );
+			
+			assertEquals( t.socket().getLocalSocketAddress(), c.remoteAddress() );
+			assertEquals( t.socket().getRemoteSocketAddress(), c.localAddress() );
+			
+			write( t, i );
+			assertWhat( What.DATA, dh.what );
+			assertNull( dh.xsender );
+			assertNotNull( dh.xbuf );
+			assertEquals( 1, dh.xbuf.length );
+			assertEquals( (byte) i, dh.xbuf[0] );
+
+			t.socket().shutdownOutput();
+			t.close();
+			t = null;
+			
+			assertWhat( What.DOWN, dh.what );
+		}
+		
+		Thread t1 = new MonitorHarvester<SocketChannel>( lh.accepted );
+		t1.start();
+		Thread t2 = new MonitorHarvester<What>( dh.what );
+		t2.start();
+
+		Log.report( "stopping" );
+		c.stop();
+		c.waitDown( TIMEOUT );
+		Log.report( "stoppped" );
+		
+		t1.join();
+		t2.join();
+	}
+	
+	private void write( SocketChannel t, int b ) throws IOException
+	{
+		ByteBuffer buf = ByteBuffer.allocate( 1 );
+		buf.put( (byte) b );
+		buf.flip();
+		int n = t.write( buf );
+		if (n != 1)
+			throw new IOException( "n != 1" );
+	}
+
+	/**
+	 * @param <T>
+	 */
+	public static class MonitorHarvester<T> extends Thread
+	{
+		/**
+		 * @param mon
+		 */
+		public MonitorHarvester( Monitor<T> mon )
+		{
+			this.mon = mon;
+		}
+		
+		private final Monitor<T> mon;
+
+		@Override
+		public void run()
+		{
+			try
+			{
+				Object t;
+				while ((t = mon.waitUntilNotEqAndSet( null, TIMEOUT, null )) != null)
+					Log.report( "harvested", "mon", mon, "t", t );
+			}
+			catch ( Exception e )
+			{
+				// ignore
+			}
+		}
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void restart2() throws Exception
+	{
+		Log.report( "--- restart2 ------------------------------" );
+		
+		MyDataHandler dh = new MyDataHandler();
+		
+		Tcp2Connection c = new Tcp2Connection( "tcp://127.0.0.1:"+port+"?TcpTransport.reconnectDelay=200", r );
+		c.setSession( dh );
+		
+		c.start();
+		c.waitUp( TIMEOUT );
+		
+		int n = 10;
+		int i = 0;
+		while (++i <= n)
+		{
+//			Log.report( "--- waitAccepted" );
+			SocketChannel t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+
+			Log.report( "accepted", "i", i,
+				"t.local", t.socket().getLocalSocketAddress(),
+				"t.remote", t.socket().getRemoteSocketAddress() );
+			
+			assertWhat( What.UP, dh.what );
+//			Log.report( "up", "c.local", c.localAddress(), "c.remote", c.remoteAddress() );
+			
+			assertEquals( t.socket().getLocalSocketAddress(), c.remoteAddress() );
+			assertEquals( t.socket().getRemoteSocketAddress(), c.localAddress() );
+			
+			write( t, i );
+			assertWhat( What.DATA, dh.what );
+			assertNull( dh.xsender );
+			assertNotNull( dh.xbuf );
+			assertEquals( 1, dh.xbuf.length );
+			assertEquals( (byte) i, dh.xbuf[0] );
+
+//			Log.report( "c.shutingDownOutput" );
+			c.shutdownOutput();
+//			Log.report( "c.shutdownOutput" );
+			
+//			Log.report( "t.reading" );
+			assertEquals( -1, read( t ) );
+//			Log.report( "t.eof" );
+			
+			t.socket().shutdownOutput();
+			t.close();
+			t = null;
+			
+			assertWhat( What.DOWN, dh.what );
+//			Log.report( "down" );
+		}
+		
+		Thread t1 = new MonitorHarvester<SocketChannel>( lh.accepted );
+		t1.start();
+		Thread t2 = new MonitorHarvester<What>( dh.what );
+		t2.start();
+		
+		Log.report( "stopping" );
+		c.stop();
+		c.waitDown( TIMEOUT );
+		Log.report( "stopped" );
+		
+		t1.join();
+		t2.join();
+	}
+
+	private int read( SocketChannel t ) throws IOException
+	{
+		ByteBuffer buf = ByteBuffer.allocate( 1 );
+		int n = t.read( buf );
+		if (n <= 0)
+			return -1;
+		buf.flip();
+		return buf.get() & 255;
+	}
+
+	/** @throws Exception */
+	@Test
+	public void data1() throws Exception
+	{
+		MyDataHandler dh = new MyDataHandler();
+		
+		Tcp2Connection c = new Tcp2Connection( "tcp://127.0.0.1:"+port, r );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		SocketChannel t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		write( t, 23 );
+		
+		assertWhat( What.DATA, dh.what );
+		assertNull( dh.xsender );
+		assertNotNull( dh.xbuf );
+		assertEquals( 1, dh.xbuf.length );
+		assertEquals( (byte) 23, dh.xbuf[0] );
+		
+		assertTrue( c.isStarted() );
+		c.stop();
+		assertFalse( c.isStarted() );
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void data2() throws Exception
+	{
+		MyDataHandler dh = new MyDataHandler();
+		
+		Tcp2Connection c = new Tcp2Connection( "tcp://127.0.0.1:"+port, r );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		SocketChannel t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		byte[] buf = { 21, 22, 23 };
+		
+		write( t, buf );
+		
+		assertWhat( What.DATA, dh.what );
+		assertNull( dh.xsender );
+		assertNotNull( dh.xbuf );
+		assertEquals( 3, dh.xbuf.length );
+		assertEquals( (byte) 21, dh.xbuf[0] );
+		assertEquals( (byte) 22, dh.xbuf[1] );
+		assertEquals( (byte) 23, dh.xbuf[2] );
+		
+		assertTrue( c.isStarted() );
+		c.stop();
+		assertFalse( c.isStarted() );
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+
+	private void write( SocketChannel t, byte[] b ) throws IOException
+	{
+		ByteBuffer buf = ByteBuffer.allocate( b.length );
+		buf.put( b );
+		buf.flip();
+		int n = t.write( buf );
+		if (n != b.length)
+			throw new IOException( "n != b.length" );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void data3() throws Exception
+	{
+		MyDataHandler dh = new MyDataHandler();
+		
+		Tcp2Connection c = new Tcp2Connection( "tcp://127.0.0.1:"+port, r );
+		c.setSession( dh );
+		
+		assertFalse( c.isStarted() );
+		c.start();
+		assertTrue( c.isStarted() );
+		
+		SocketChannel t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.socket().shutdownOutput();
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+		c.close();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void data4() throws Exception
+	{
+		MyDataHandler dh = new MyDataHandler();
+		
+		Tcp2Connection c = new Tcp2Connection( "tcp://127.0.0.1:"+port, r );
+		c.setSession( dh );
+
+		c.start();
+		
+		SocketChannel t = lh.accepted.waitUntilNotEqAndSet( null, TIMEOUT, null );
+		
+		assertWhat( What.UP, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		c.transportData( null, new FlexBuffer( new byte[] { 21, 22, 23 } ) );
+//		c.flush();
+		
+		assertEquals( 21, read( t ) );
+		assertEquals( 22, read( t ) );
+		assertEquals( 23, read( t ) );
+		
+		c.shutdownOutput();
+		
+		assertEquals( -1, read( t ) );
+		
+		c.close();
+		
+		assertWhat( What.DOWN, dh.what );
+		assertNull( dh.xsender );
+		assertNull( dh.xbuf );
+		
+		t.close();
+	}
+	
+	private void assertWhat( What what, Monitor<What> mon )
+		throws Exception
+	{
+		mon.waitUntilEqAndSet( what, TIMEOUT, null );
+	}
+	
+	/**
+	 * Test events.
+	 */
+	enum What
+	{
+		/** connection is up */
+		UP,
+		/** connection is down */
+		DOWN,
+		/** connection read some data */
+		DATA
+	}
+
+	/**
+	 * ListenerHandler for testing.
+	 */
+	static class MyListener implements SessionListener<SocketChannel>
+	{
+		/** monitor to report accepted socket */
+		public Monitor<SocketChannel> accepted = new Monitor<SocketChannel>( "accepted" );
+		
+		public void sessionAccepted( SocketChannel s ) throws Exception
+		{
+//			Log.report( "listener.accepted",
+//				"s.local", s.getLocalSocketAddress(),
+//				"s.remote", s.getRemoteSocketAddress() );
+			
+			accepted.waitUntilEqAndSet( null, TIMEOUT, s );
+		}
+
+		public Object sessionQuery( Object query )
+		{
+			throw new UnsupportedOperationException( "unknown query "+query );
+		}
+
+		public void sessionControl( Object control, Object value )
+		{
+			throw new UnsupportedOperationException( "unknown control "+control );
+		}
+
+		public void sessionNotify( Object event )
+		{
+			if (event instanceof Exception)
+				Log.report( "listener.notify", "event", event );
+			
+			System.out.println( "TestTcp2Connection.MyListener: event = " + event );
+		}
+	}
+	
+	/**
+	 * DataHandler for testing.
+	 */
+	static class MyDataHandler implements SessionData
+	{
+		/** holds event type */
+		public Monitor<What> what = new Monitor<What>( "what" );
+
+		/** sender of the event if DATA */
+		public Who xsender;
+
+		/** data of the event if DATA */
+		public byte[] xbuf;
+		
+		public void sessionData( Who sender, FlexBuffer buf ) throws Exception
+		{
+			xsender = sender;
+			xbuf = buf.getAvailBytes();
+			what.waitUntilEqAndSet( null, TIMEOUT, What.DATA );
+		}
+
+		public Object sessionQuery( Object query ) throws Exception
+		{
+			throw new UnsupportedOperationException( "unknown query "+query );
+		}
+
+		public void sessionControl( Object control, Object value ) throws Exception
+		{
+			throw new UnsupportedOperationException( "unknown control "+control );
+		}
+
+		public void sessionNotify( Object event ) throws Exception
+		{
+//			Log.report( "data.notify", "event", event );
+			
+			if (event.equals( Session.UP ))
+			{
+				xbuf = null;
+				what.waitUntilEqAndSet( null, TIMEOUT, What.UP );
+				return;
+			}
+			
+			if (event.equals( Session.DOWN ))
+			{
+				xbuf = null;
+				what.waitUntilEqAndSet( null, TIMEOUT, What.DOWN );
+				return;
+			}
+			
+			Log.report( "data.notify", "event", event );
+		}
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/core/nio/TestTcp2Listener.java b/util/src/test/java/org/apache/etch/util/core/nio/TestTcp2Listener.java
new file mode 100644
index 0000000..157f4a6
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/core/nio/TestTcp2Listener.java
@@ -0,0 +1,467 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.nio;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.net.Inet6Address;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+
+import org.apache.etch.util.Monitor;
+import org.apache.etch.util.Resources;
+import org.apache.etch.util.core.io.Session;
+import org.apache.etch.util.core.io.SessionListener;
+import org.junit.Test;
+
+
+/**
+ * Tests Listener.
+ */
+public class TestTcp2Listener
+{
+	private final static int TIMEOUT = 4000;
+	
+	private final SuperSelector selector = new SuperSelector();
+	{
+		selector.start();
+	}
+	
+	private final Resources r = new Resources();
+	{
+		r.put( "selector", selector );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor1() throws Exception
+	{
+		// negative port
+		new Tcp2Listener( "tcp://0.0.0.0:-1", r );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor2() throws Exception
+	{
+		// too positive port
+		new Tcp2Listener( "tcp://0.0.0.0:65536", r );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor3() throws Exception
+	{
+		// missing port
+		new Tcp2Listener( "tcp://0.0.0.0", r );
+	}
+
+	/** @throws Exception */
+	@Test( expected = IllegalArgumentException.class )
+	public void constructor4() throws Exception
+	{
+		// negative backlog
+		new Tcp2Listener( "tcp://0.0.0.0:0?backlog=-1", r );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void constructor5() throws Exception
+	{
+		Tcp2Listener l = new Tcp2Listener( "tcp://0.0.0.0:45", r );
+		assertEquals( "0.0.0.0", l.getHost() );
+		assertEquals( 45, l.getPort() );
+		assertEquals( 0, l.getBacklog() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void constructor6() throws Exception
+	{
+		Tcp2Listener l = new Tcp2Listener( "tcp://foo:2001?backlog=19", r );
+		assertEquals( "foo", l.getHost() );
+		assertEquals( 2001, l.getPort() );
+		assertEquals( 19, l.getBacklog() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void session1() throws Exception
+	{
+		MyListenerHandler lh = new MyListenerHandler();
+		
+		Tcp2Listener l = new Tcp2Listener( "tcp://0.0.0.0:0", r );
+		l.setSession( lh );
+		
+		assertSame( lh, l.getSession() );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void stop1() throws Exception
+	{
+		// illegal state: not started.
+		Tcp2Listener l = new Tcp2Listener( "tcp://0.0.0.0:0", r );
+		l.stop();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start1() throws Exception
+	{
+		MyListenerHandler lh = new MyListenerHandler();
+		
+		Tcp2Listener l = new Tcp2Listener( "tcp://0.0.0.0:0", r );
+		l.setSession( lh );
+		
+		assertWhat( null, lh.what );
+		assertNull( lh.xsocket );
+
+		l.start();
+		l.waitUp( TIMEOUT );
+
+		assertTrue( l.isStarted() );
+
+		assertWhat( What.UP, lh.what );
+		assertNull( lh.xsocket );
+
+		InetSocketAddress a = (InetSocketAddress) l.localAddress();
+		if ( a.getAddress() instanceof Inet6Address )
+			assertEquals( "0:0:0:0:0:0:0:0", a.getAddress().getHostAddress().toString() );
+		else
+			assertEquals( "0.0.0.0", a.getAddress().getHostAddress().toString() );
+		assertTrue( a.getPort() > 0 && a.getPort() < 65536 );
+
+		l.stop();
+		l.waitDown( TIMEOUT );
+
+		assertFalse( l.isStarted() );
+
+		assertWhat( What.DOWN, lh.what );
+		assertNull( lh.xsocket );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start2() throws Exception
+	{
+		MyListenerHandler lh = new MyListenerHandler();
+		Tcp2Listener l = new Tcp2Listener( "tcp://127.0.0.1:0", r );
+		l.setSession( lh );
+		
+		assertWhat( null, lh.what );
+		assertNull( lh.xsocket );
+
+		l.start();
+		l.waitUp( TIMEOUT );
+
+		assertTrue( l.isStarted() );
+
+		assertWhat( What.UP, lh.what );
+		assertNull( lh.xsocket );
+
+		InetSocketAddress a = (InetSocketAddress) l.localAddress();
+		assertEquals( "127.0.0.1", a.getAddress().getHostAddress().toString() );
+		assertTrue( a.getPort() > 0 && a.getPort() < 65536 );
+
+		l.stop();
+		l.waitDown( TIMEOUT );
+		assertFalse( l.isStarted() );
+		assertWhat( What.DOWN, lh.what );
+		assertNull( lh.xsocket );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start3() throws Exception
+	{
+		MyListenerHandler lh = new MyListenerHandler();
+		Tcp2Listener l = new Tcp2Listener( "tcp://0.0.0.0:4998", r );
+		l.setSession( lh );
+
+		assertWhat( null, lh.what );
+		assertNull( lh.xsocket );
+
+		l.start();
+		l.waitUp( TIMEOUT );
+		assertTrue( l.isStarted() );
+
+		assertWhat( What.UP, lh.what );
+		assertNull( lh.xsocket );
+
+		InetSocketAddress a = (InetSocketAddress) l.localAddress();
+		if ( a.getAddress() instanceof Inet6Address )
+			assertEquals( "0:0:0:0:0:0:0:0", a.getAddress().getHostAddress().toString() );
+		else
+			assertEquals( "0.0.0.0", a.getAddress().getHostAddress().toString() );
+		assertEquals( 4998, a.getPort() );
+
+		l.stop();
+		l.waitDown( TIMEOUT );
+
+		assertFalse( l.isStarted() );
+
+		assertWhat( What.DOWN, lh.what );
+		assertNull( lh.xsocket );
+	}
+
+	/** @throws Exception */
+	@Test
+	public void start4() throws Exception
+	{
+		MyListenerHandler lh = new MyListenerHandler();
+		Tcp2Listener l = new Tcp2Listener( "tcp://127.0.0.1:4996", r );
+		l.setSession( lh );
+
+		assertWhat( null, lh.what );
+		assertNull( lh.xsocket );
+
+		l.start();
+		l.waitUp( TIMEOUT );
+
+		assertTrue( l.isStarted() );
+
+		assertWhat( What.UP, lh.what );
+		assertNull( lh.xsocket );
+
+		InetSocketAddress a = (InetSocketAddress) l.localAddress();
+		assertEquals( "127.0.0.1", a.getAddress().getHostAddress().toString() );
+		assertEquals( 4996, a.getPort() );
+
+		l.stop();
+		l.waitDown( TIMEOUT );
+
+		assertFalse( l.isStarted() );
+
+		assertWhat( What.DOWN, lh.what );
+		assertNull( lh.xsocket );
+	}
+
+	/** @throws Exception */
+	@Test( expected = SocketException.class )
+	public void start5() throws Exception
+	{
+		// bad address
+		MyListenerHandler lh = new MyListenerHandler();
+		Tcp2Listener l = new Tcp2Listener( "tcp://1.2.3.4.5:4997", r );
+		l.setSession( lh );
+
+		assertWhat( null, lh.what );
+		assertNull( lh.xsocket );
+
+		l.start();
+	}
+
+	/** @throws Exception */
+	@Test
+	public void accept1() throws Exception
+	{
+		MyListenerHandler lh = new MyListenerHandler();
+		Tcp2Listener l = new Tcp2Listener( "tcp://0.0.0.0:4995", r );
+		l.setSession( lh );
+
+		l.start();
+		l.waitUp( TIMEOUT );
+
+		Socket s = new Socket( "127.0.0.1", 4995 );
+		assertWhat( What.ACCEPTED, lh.what );
+		assertNotNull( lh.xsocket );
+
+		// verify they are connected to each other
+
+		assertEquals( s.getLocalSocketAddress(), lh.xsocket.socket().getRemoteSocketAddress() );
+		assertEquals( s.getRemoteSocketAddress(), lh.xsocket.socket().getLocalSocketAddress() );
+
+		// verify they can talk to each other
+
+		s.getOutputStream().write( 23 );
+		s.getOutputStream().flush();
+		assertEquals( 23, read( lh.xsocket ) );
+
+		s.getOutputStream().write( 67 );
+		s.getOutputStream().flush();
+		assertEquals( 67, read( lh.xsocket ) );
+
+		write( lh.xsocket, 24 );
+		assertEquals( 24, s.getInputStream().read() );
+
+		write( lh.xsocket, 73 );
+		assertEquals( 73, s.getInputStream().read() );
+
+		// shut 'em down.
+
+		s.close();
+		lh.xsocket.close();
+
+		l.stop();
+		l.waitDown( TIMEOUT );
+	}
+
+	private void write( SocketChannel c, int b ) throws IOException
+	{
+		ByteBuffer buf = ByteBuffer.allocate( 1 );
+		buf.put( (byte) b );
+		buf.flip();
+		int n = c.write( buf );
+		if (n != 1)
+			throw new IOException( "m != 1" );
+	}
+
+	private int read( SocketChannel c ) throws IOException
+	{
+		ByteBuffer buf = ByteBuffer.allocate( 1 );
+		int n = c.read( buf );
+		if (n <= 0)
+			return -1;
+		buf.flip();
+		return buf.get() & 255;
+	}
+
+	/** @throws Exception */
+	@Test
+	public void accept2() throws Exception
+	{
+		MyOtherListenerHandler lh = new MyOtherListenerHandler();
+		Tcp2Listener l = new Tcp2Listener( "tcp://0.0.0.0:0?TcpListener.backlog=100", r );
+		l.setSession( lh );
+
+		l.start();
+		l.waitUp( TIMEOUT );
+
+		int port = ((InetSocketAddress) l.localAddress()).getPort();
+
+		int n = 1000;
+
+		for (int i = 0; i < n; i++)
+			new Socket( "127.0.0.1", port ).close();
+
+		// wait for things to settle down...
+		Thread.sleep( 100 );
+
+		assertEquals( n, lh.accepted );
+
+		l.stop();
+		l.waitDown( TIMEOUT );
+	}
+
+	private void assertWhat( What what, Monitor<What> mon )
+		throws Exception
+	{
+		mon.waitUntilEqAndSet( what, 4000, null );
+	}
+
+	/**
+	 * Event types.
+	 */
+	enum What
+	{
+		/** the event seen was ACCEPTED */
+		ACCEPTED,
+		/** the event seen was UP */
+		UP,
+		/** the event seen was DOWN */
+		DOWN
+	}
+
+	/**
+	 * ListenerHandler for testing.
+	 */
+	public static class MyListenerHandler implements SessionListener<SocketChannel>
+	{
+		/** the event seen */
+		public Monitor<What> what = new Monitor<What>( null );
+
+		/** the socket accepted (if accept) */
+		public SocketChannel xsocket;
+
+		public void sessionAccepted( SocketChannel socket ) throws Exception
+		{
+			xsocket = socket;
+			what.set( What.ACCEPTED );
+		}
+		
+		public Object sessionQuery( Object query )
+		{
+			throw new UnsupportedOperationException( "unknown query "+query );
+		}
+		
+		public void sessionControl( Object control, Object value )
+		{
+			throw new UnsupportedOperationException( "unknown control "+control );
+		}
+		
+		public void sessionNotify( Object event )
+		{
+			if (event.equals( Session.UP ))
+			{
+				what.set( What.UP );
+				return;
+			}
+			
+			if (event.equals( Session.DOWN ))
+			{
+				what.set( What.DOWN );
+				return;
+			}
+		}
+	}
+
+	/**
+	 * ListenerHandler for testing.
+	 */
+	public static class MyOtherListenerHandler implements SessionListener<SocketChannel>
+	{
+		/** count of accepted connections. */
+		public int accepted;
+
+		public void sessionAccepted( SocketChannel socket ) throws Exception
+		{
+			accepted++;
+			socket.close();
+		}
+
+		public void sessionControl( Object control, Object value )
+			throws Exception
+		{
+			// ignore
+		}
+
+		public void sessionNotify( Object event ) throws Exception
+		{
+			// ignore
+		}
+
+		public Object sessionQuery( Object query ) throws Exception
+		{
+			// ignore
+			return null;
+		}
+	}
+}
diff --git a/util/src/test/java/org/apache/etch/util/core/xml/testJaxp.java b/util/src/test/java/org/apache/etch/util/core/xml/testJaxp.java
new file mode 100644
index 0000000..943f4c9
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/core/xml/testJaxp.java
@@ -0,0 +1,135 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.xml;
+
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.etch.util.Timer;
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+
+/**
+ * Description of testJaxp.
+ */
+public class testJaxp
+{
+	/**
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main( String[] args )
+		throws Exception
+	{
+		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+		DocumentBuilder db = dbf.newDocumentBuilder();
+		Document d = db.parse( new InputSource( new StringReader( "<x>blah</x>" ) ) );
+		System.out.println( "d = "+d );
+		dump( d );
+		
+		dump( parse( db, TEST_MSG ) );
+		
+		if (false) return;
+		
+		int m = 5;
+		int n = 50000*4;
+		for (int j = 0; j < m; j++)
+		{
+			if (j != 0)
+				Thread.sleep( 5000 );
+			
+			long t0 = Timer.currentTimeMillis();
+			for (int i = 0; i < n; i += 4)
+			{
+				parse( db, TEST_MSG );
+				parse( db, TEST_MSG );
+				parse( db, TEST_MSG );
+				parse( db, TEST_MSG );
+			}
+			long t1 = Timer.currentTimeMillis();
+			
+			double t = (t1-t0)/1000.0;
+			double r = n / t;
+			System.out.println( "took "+t+" for "+n+" iterations ("+r+" per second)" );
+		}
+	}
+	
+	private static void dump( Document d )
+	{
+		dump( "", d.getDocumentElement() );
+		
+	}
+
+	private static void dump( String prefix, Element e )
+	{
+		System.out.println( prefix+"start of element name="+e.getTagName() );
+		
+		NamedNodeMap attrs = e.getAttributes();
+		int n = attrs.getLength();
+		for (int i = 0; i < n; i++)
+		{
+			Node a = attrs.item( i );
+			System.out.println( prefix+"  attr name '"+a.getNodeName()+"' value '"+a.getNodeValue()+"'" );
+		}
+		
+		NodeList nl = e.getChildNodes();
+		n = nl.getLength();
+		for (int i = 0; i < n; i++)
+		{
+			Node sn = nl.item( i );
+			if (sn instanceof Element)
+				dump( prefix+"  ", (Element) sn );
+			else
+				dump( prefix+"  ", (CharacterData ) sn );
+		}
+		
+		System.out.println( prefix+"end of element name="+e.getTagName() );
+	}
+
+	private static void dump( String prefix, CharacterData data )
+	{
+		System.out.println( prefix+"data = '"+data+"'" );
+	}
+
+	private static Document parse( DocumentBuilder db, String msg ) throws Exception
+	{
+		return db.parse( new InputSource( new StringReader( msg ) ) );
+	}
+
+	private final static String TEST_MSG =
+		"<message>" +
+			"<messageId>connect</messageId>" +
+			"<field name='machineName'>xxx</field>" +
+			"<field name='queueName'>xxx</field>" +
+			"<field name='heartbeatInterval'>10</field>" +
+			"<field name='heartbeatPayload'>mediaResources</field>" +
+			"<field name='serverId'>1</field>" +
+			"<field name='transactionId'>1</field>" +
+		"</message>";
+}
diff --git a/util/src/test/java/org/apache/etch/util/core/xml/testXmlParser.java b/util/src/test/java/org/apache/etch/util/core/xml/testXmlParser.java
new file mode 100644
index 0000000..4622be9
--- /dev/null
+++ b/util/src/test/java/org/apache/etch/util/core/xml/testXmlParser.java
@@ -0,0 +1,823 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.etch.util.core.xml;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.apache.etch.util.Timer;
+
+
+
+@SuppressWarnings("all")
+public class testXmlParser extends XmlParser
+{
+	/**
+	 * @param args
+	 * @throws ParseException
+	 * @throws InterruptedException
+	 */
+	public static void main( String[] args ) throws ParseException, InterruptedException
+	{
+		testXmlParser xp = new testXmlParser();
+
+		parse( xp, "<x>" );
+		
+		parse( xp, "<a>" );
+		parse( xp, "</a>" );
+
+		parse( xp, "<a:d>" );
+		parse( xp, "</a:d>" );
+
+		parse( xp, "<abc>" );
+		parse( xp, "<abc:def>" );
+		
+		parse( xp, "<abc >" );
+		parse( xp, "<abc:def >" );
+		
+		parse( xp, "<abc/>" );
+		parse( xp, "<abc:def/>" );
+		
+		parse( xp, "<abc />" );
+		parse( xp, "<abc:def />" );
+		
+		parse( xp, "</abc:def>" );
+		parse( xp, "</abc>" );
+		
+		parse( xp, "</abc:def >" );
+		parse( xp, "</abc >" );
+
+		parse( xp, "<a x='1'/>" );
+		parse( xp, "<a x ='1'/>" );
+		parse( xp, "<a x= '1'/>" );
+		parse( xp, "<a x = '1'/>" );
+		
+		parse( xp, "<a xyz='&#169;123&#169;'/>" );
+		parse( xp, "<a x='1' y='2'/>" );
+
+		parse( xp, "<a q:x='1'/>" );
+		parse( xp, "<a q:xyz='123'/>" );
+		parse( xp, "<a q:x='1' q:y='2'/>" );
+
+		parse( xp, "<a x=\"1\"/>" );
+		parse( xp, "<a xyz=\"123\"/>" );
+		parse( xp, "<a x=\"1\" y=\"2\"/>" );
+		
+		parse( xp, "</x>" );
+		TagElement te = xp.finish();
+		System.out.println( "parsed: "+te );
+		
+		xp.clear();
+		
+		xp.parseOne( TEST_MSG );
+		
+		xp.dump();
+		
+		if (false)
+		{
+			int m = 5;
+			int n = 50000*4;
+			for (int j = 0; j < m; j++)
+			{
+				if (j != 0)
+					Thread.sleep( 5000 );
+				
+				long t0 = Timer.currentTimeMillis();
+				for (int i = 0; i < n; i += 4)
+				{
+					xp.parse( TEST_MSG );
+					xp.parse( TEST_MSG );
+					xp.parse( TEST_MSG );
+					xp.parse( TEST_MSG );
+				}
+				long t1 = Timer.currentTimeMillis();
+				
+				double t = (t1-t0)/1000.0;
+				double r = n / t;
+				System.out.println( "took "+t+" for "+n+" iterations ("+r+" per second)" );
+			}
+		}
+	}
+
+	private final static String TEST_MSG =
+		"<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
+		"<message xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
+			"<field name=\"heartbeatInterval\">10</field>" +
+			"<field name=\"heartbeatPayload\">mediaResources</field>" +
+			"<field name=\"machineName\">JAVAMAN</field>" +
+			"<field name=\"queueName\">NULL</field>" +
+			"<field name=\"serverId\">1</field>" +
+			"<field name=\"transactionId\">3</field>" +
+			"<field name=\"serverId\">1</field>" +
+			"<field name=\"clientId\">NULL</field>" +
+			"<messageId>connect</messageId>" +
+		"</message>";
+
+	private static void parse( XmlParser xp, String s ) throws ParseException
+	{
+		System.out.println( "trying '"+s+"'..." );
+		System.out.flush();
+		
+		xp.parse( s );
+		
+		System.out.println( "... ok!" );
+		System.out.flush();
+		
+		xp.dump();
+	}
+	
+	public TagElement addRootTag( QName qName, Map<QName, String> attrs )
+	{
+		MessageProcessor mp = new MessageProcessor();
+		pushTagElement( mp );
+		return mp.addTag( qName, attrs );
+	}
+	
+	/**
+	 * Description of MessageProcessor
+	 */
+	public class MessageProcessor extends AbstractElement implements TagElement
+	{
+		/**
+		 */
+		public MessageProcessor()
+		{
+			// nothing to do
+		}
+
+		public boolean matches( String qualifier, String name )
+		{
+			return false;
+		}
+
+		public void addCdata( String cdata )
+		{
+			if (cdata.trim().length() > 0)
+				throw new RuntimeException( "cdata not allowed in message processor: "+cdata );
+		}
+		
+		public TagElement addTag( QName childQName, Map<QName, String> childAttrs )
+		{
+			if (childQName.matches( MESSAGE_QUALIFIER, MESSAGE_NAME ))
+				return new Message( childAttrs );
+			
+			return new DefaultTagElement( childQName, childAttrs );
+		}
+
+		public void finish()
+		{
+			// nothing to do
+		}
+
+		public Iterator<Element> getChildren()
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public String getCdataValue()
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public Iterator<QName> getAttrNames()
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public String getAttr( String qualifier, String name )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public QName getQName()
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public boolean matches( QName qName )
+		{
+			// Auto-generated method stub
+			return false;
+		}
+
+		public boolean remove( Element e )
+		{
+			// Auto-generated method stub
+			return false;
+		}
+
+		public void clear()
+		{
+			// Auto-generated method stub
+			
+		}
+
+		public Integer getIntAttr( String qualifier, String name )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public Long getLongAttr( String qualifier, String name )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public TagElement find( String path )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public TagElement find( String oqualifier, String oname )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public TagElement find( QName subQName )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public Iterator<Element> iterator()
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public boolean hasChildren()
+		{
+			// Auto-generated method stub
+			return false;
+		}
+
+		public boolean hasAttrs()
+		{
+			// Auto-generated method stub
+			return false;
+		}
+
+		public TagElement addTag( QName childQName )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public TagElement addTag( String childName, Map<QName, String> childAttrs )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public TagElement addTag( String childName )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public int countChildren()
+		{
+			// Auto-generated method stub
+			return 0;
+		}
+
+		public Element getChild( int index )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public boolean hasCdataValue()
+		{
+			// Auto-generated method stub
+			return false;
+		}
+
+		public void toString( Writer wtr, boolean newlineBetweenTags,
+			boolean collapseEmptyTags ) throws IOException
+		{
+			wtr.write( "mp" );
+		}
+
+		public TagElement setAttr( String qualifier, String name, String value )
+		{
+			return this;
+		}
+
+		public TagElement setAttr( String qualifier, String name, int value )
+		{
+			return this;
+		}
+
+		public TagElement setAttr( String qualifier, String name, long value )
+		{
+			return this;
+		}
+	}
+	
+	/**
+	 * Description of Message.
+	 */
+	public class Message extends AbstractElement implements TagElement
+	{
+		/**
+		 * Constructs the Message.
+		 *
+		 * @param attrs
+		 */
+		public Message( Map<QName, String> attrs )
+		{
+			type = attrs.get( new QName( null, "t" ) );
+		}
+		
+		private final String type;
+
+		public boolean matches( String qualifier, String name )
+		{
+			return QName.matches( qualifier, MESSAGE_QUALIFIER, name, MESSAGE_NAME );
+		}
+
+		public void addCdata( String cdata )
+		{
+			if (cdata.trim().length() != 0)
+				throw new RuntimeException( "cdata not allowed in message body" );
+		}
+
+		public TagElement addTag( QName childQName, Map<QName, String> childAttrs )
+		{
+			// only allow parameter tags
+			if (!childQName.matches( PARAMETER_QUALIFIER, PARAMETER_NAME ))
+				throw new RuntimeException( "tag "+childQName+" not allowed in message body" );
+			
+			Parameter p = new Parameter( childAttrs );
+			params.add( p );
+			return p;
+		}
+
+		public void finish()
+		{
+			// nothing to do.
+			//System.out.println( "message finished: "+this );
+		}
+		
+		private List<Parameter> params = new Vector<Parameter>();
+
+		public Iterator<Element> getChildren()
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public String getCdataValue()
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public Iterator<QName> getAttrNames()
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public String getAttr( String qualifier, String name )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public QName getQName()
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public boolean matches( QName qName )
+		{
+			// Auto-generated method stub
+			return false;
+		}
+
+		public boolean remove( Element e )
+		{
+			// Auto-generated method stub
+			return false;
+		}
+
+		public void clear()
+		{
+			// Auto-generated method stub
+			
+		}
+
+		public Integer getIntAttr( String qualifier, String name )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public Long getLongAttr( String qualifier, String name )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public TagElement find( String path )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public TagElement find( String oqualifier, String oname )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public TagElement find( QName subQName )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public Iterator<Element> iterator()
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public boolean hasChildren()
+		{
+			// Auto-generated method stub
+			return false;
+		}
+
+		public boolean hasAttrs()
+		{
+			// Auto-generated method stub
+			return false;
+		}
+
+		public TagElement addTag( QName childQName )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public TagElement addTag( String childName, Map<QName, String> childAttrs )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public TagElement addTag( String childName )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public int countChildren()
+		{
+			// Auto-generated method stub
+			return 0;
+		}
+
+		public Element getChild( int index )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public boolean hasCdataValue()
+		{
+			// Auto-generated method stub
+			return false;
+		}
+
+		public void toString( Writer wtr, boolean newlineBetweenTags,
+			boolean collapseEmptyTags ) throws IOException
+		{
+			wtr.write( type );
+			wtr.write( ": " );
+			wtr.write( params.toString() );
+		}
+
+		public TagElement setAttr( String qualifier, String name, String value )
+		{
+			return this;
+		}
+
+		public TagElement setAttr( String qualifier, String name, int value )
+		{
+			return this;
+		}
+
+		public TagElement setAttr( String qualifier, String name, long value )
+		{
+			return this;
+		}
+	}
+	
+	/**
+	 * Description of Parameter.
+	 */
+	public static class Parameter extends AbstractElement implements TagElement
+	{
+		/**
+		 * Constructs the Parameter.
+		 *
+		 * @param attrs
+		 */
+		public Parameter( Map<QName, String> attrs )
+		{
+			n = attrs.get( new QName( null, "n" ) );
+			if (n == null)
+				throw new RuntimeException( "n attribute not specified" );
+			
+			t = attrs.get( new QName( null, "t" ) );
+			if (t == null)
+				throw new RuntimeException( "t attribute not specified" );
+			
+			setValue( attrs.get( new QName( null, "v" ) ) );
+		}
+		
+		private final String n;
+		
+		private final String t;
+
+		public boolean matches( String qualifier, String name )
+		{
+			return QName.matches( qualifier, PARAMETER_QUALIFIER, name, PARAMETER_NAME );
+		}
+
+		public void addCdata( String cdata )
+		{
+			setValue( cdata );
+		}
+
+		public TagElement addTag( QName childQName, Map<QName, String> childAttrs )
+		{
+			throw new RuntimeException( "subordinate elements are not yet supported" );
+		}
+
+		public void finish()
+		{
+			if (v == null)
+				throw new RuntimeException( "parameter "+n+" was not given a value" );
+		}
+		
+		/**
+		 * @param name
+		 * @return true if name matches this parameter's name
+		 */
+		public boolean matchesName( String name )
+		{
+			return n.equals( name );
+		}
+		
+		/**
+		 * @return the name of this parameter
+		 */
+		public String getName()
+		{
+			return n;
+		}
+		
+		/**
+		 * @return the value of this parameter.
+		 */
+		public Object getValue()
+		{
+			return v;
+		}
+		
+		private void setValue( String s )
+		{
+			if (s == null)
+				return;
+			
+			//System.out.println( "setValue: name '"+n+"' type '"+t+"' value '"+s+"'" );
+			
+			if (v != null)
+				throw new RuntimeException( "parameter "+n+" already has a value" );
+			
+			if (t.equals( "s" ))
+				v = s;
+			else if (t.equals( "i" ))
+				v = Integer.parseInt( s );
+			else if (t.equals( "d" ))
+				v = Double.parseDouble( s );
+			else
+				throw new RuntimeException( "parameter "+n+" type "+t+" not supported" );
+		}
+		
+		private Object v;
+
+		public Iterator<Element> getChildren()
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public String getCdataValue()
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public Iterator<QName> getAttrNames()
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public String getAttr( String qualifier, String name )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public QName getQName()
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public boolean matches( QName qName )
+		{
+			// Auto-generated method stub
+			return false;
+		}
+
+		public boolean remove( Element e )
+		{
+			// Auto-generated method stub
+			return false;
+		}
+
+		public void clear()
+		{
+			// Auto-generated method stub
+			
+		}
+
+		public Integer getIntAttr( String qualifier, String name )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public Long getLongAttr( String qualifier, String name )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public TagElement find( String path )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public TagElement find( String oqualifier, String oname )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public TagElement find( QName subQName )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public Iterator<Element> iterator()
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public boolean hasChildren()
+		{
+			// Auto-generated method stub
+			return false;
+		}
+
+		public boolean hasAttrs()
+		{
+			// Auto-generated method stub
+			return false;
+		}
+
+		public TagElement addTag( QName childQName )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public TagElement addTag( String childName, Map<QName, String> childAttrs )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public TagElement addTag( String childName )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public int countChildren()
+		{
+			// Auto-generated method stub
+			return 0;
+		}
+
+		public Element getChild( int index )
+		{
+			// Auto-generated method stub
+			return null;
+		}
+
+		public boolean hasCdataValue()
+		{
+			// Auto-generated method stub
+			return false;
+		}
+
+		public void toString( Writer wtr, boolean newlineBetweenTags,
+			boolean collapseEmptyTags ) throws IOException
+		{
+			wtr.write( n );
+			wtr.write( " =(" );
+			wtr.write( t );
+			wtr.write( ") " );
+			wtr.write( v.toString() );
+		}
+
+		public TagElement setAttr( String qualifier, String name, String value )
+		{
+			return this;
+		}
+
+		public TagElement setAttr( String qualifier, String name, int value )
+		{
+			return this;
+		}
+
+		public TagElement setAttr( String qualifier, String name, long value )
+		{
+			return this;
+		}
+	}
+	
+	/**
+	 * Description of MESSAGE_QUALIFIER.
+	 */
+	public final static String MESSAGE_QUALIFIER = null;
+	
+	/**
+	 * Description of MESSAGE_NAME.
+	 */
+	public final static String MESSAGE_NAME = "m";
+	
+	/**
+	 * Description of PARAMETER_QUALIFIER.
+	 */
+	public final static String PARAMETER_QUALIFIER = null;
+	
+	/**
+	 * Description of PARAMETER_NAME.
+	 */
+	public final static String PARAMETER_NAME = "p";
+}