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 > 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>
+<DEFAULT> SKIP : {
+" "
+| "\t"
+| "\r"
+| "\n"
+| "\f"
+| <SINGLE1: "//" (~["\r","\n"])* ["\r","\n"]>
+| <SINGLE2: "#" (~["\r","\n"])* ["\r","\n"]>
+}
+
+ </PRE>
+ </TD>
+ </TR>
+ <!-- Token -->
+ <TR>
+ <TD>
+ <PRE>
+<DEFAULT> SPECIAL : {
+<FORMAL: "/**" (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/">
+| <BLOCK: "/*" (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/">
+}
+
+ </PRE>
+ </TD>
+ </TR>
+ <!-- Token -->
+ <TR>
+ <TD>
+ <PRE>
+<DEFAULT> 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,-1})* "\"">
+| <AT: "@">
+| <COMMA: ",">
+| <EQ: "=">
+| <SEMI: ";">
+| <LPAREN: "(">
+| <RPAREN: ")">
+| <LBRACE: "{">
+| <RBRACE: "}">
+| <LBRACKET: "[">
+| <RBRACKET: "]">
+}
+
+ </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><MODULE> <A HREF="#prod4">xid</A> ( <SEMI> )?</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> <SERVICE> <A HREF="#prod6">def</A> <LBRACE> <A HREF="#prod7">stmts</A> <RBRACE></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><AT> <A HREF="#prod9">id</A> ( <LPAREN> <A HREF="#prod10">args</A> <RPAREN> )?</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> ( <COMMA> <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> | <NULL> )</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>( <TRUE> | <FALSE> | <INTEGER> | <OCTAL> | <HEX> | <BINARY> | <DECIMAL> | <STR> )</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><MIXIN> <A HREF="#prod21">ref</A> ( <SEMI> )?</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><INCLUDE> <STR> ( <SEMI> )?</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><CONST> <A HREF="#prod22">ctype</A> <A HREF="#prod6">def</A> <EQ> <A HREF="#prod12">cvalue</A> ( <SEMI> )?</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><ENUM> <A HREF="#prod6">def</A> <LPAREN> <A HREF="#prod23">item_list</A> <RPAREN> ( <SEMI> )?</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> ( <COMMA> <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><STRUCT> <A HREF="#prod6">def</A> <A HREF="#prod24">params</A> ( <EXTENDS> <A HREF="#prod21">ref</A> )? ( <SEMI> )?</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><EXTERN> <A HREF="#prod6">def</A> ( <SEMI> )?</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><EXCEPTION> <A HREF="#prod6">def</A> <A HREF="#prod24">params</A> ( <EXTENDS> <A HREF="#prod21">ref</A> )? ( <SEMI> )?</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> ( <THROWS> <A HREF="#prod26">throws_list</A> )? ( <SEMI> )?</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> ( <COMMA> <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><ID></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><QID></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>( <BOOLEAN> | <BYTE> | <SHORT> | <INT> | <LONG> | <FLOAT> | <DOUBLE> | <STRING> )</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> | <OBJECT> | <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> ) | <VOID> )</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>( <LBRACKET> <RBRACKET> )*</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><LPAREN> ( <A HREF="#prod30">param</A> ( <COMMA> <A HREF="#prod30">param</A> )* )? <RPAREN></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 -b csharp -w all,force -n -d ../../../target/generated-sources/main/etch/csharp ${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 -b csharp -w all -n -d ../../../target/generated-sources/main/etch/csharp ${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 -b csharp -n -d ../../../target/generated-sources/main/etch/csharp ${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 -b java -w all,client -n -d ../../../target/generated-sources/main/etch/java ${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 -b java -w all,force -n -d ../../../target/generated-sources/main/etch/java ${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 -b java -w all,server -n -d ../../../target/generated-sources/main/etch/java ${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 -b java -w all -n -d ../../../target/generated-sources/main/etch/java ${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 -b java -n -d ../../../target/generated-sources/main/etch/java ${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 -b xml -n -d ../../../target/generated-sources/main/etch/xml ${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 = "<";
+
+ /**
+ *
+ */
+ public static final String GT = ">";
+
+ /**
+ *
+ */
+ public static final String AMP = "&";
+
+ /**
+ *
+ */
+ public static final String QUOT = """;
+
+ /**
+ *
+ */
+ public static final String TAB = "	";
+
+ /**
+ *
+ */
+ public static final String CR = " ";
+
+ /**
+ *
+ */
+ public static final String LF = " ";
+
+ @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='©123©'/>" );
+ 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";
+}