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"; +}