diff options
Diffstat (limited to 'gentools')
71 files changed, 0 insertions, 22989 deletions
diff --git a/gentools/LICENSE b/gentools/LICENSE deleted file mode 100644 index 43fa6abd19..0000000000 --- a/gentools/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - 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. - diff --git a/gentools/NOTICE b/gentools/NOTICE deleted file mode 100644 index 09e9ae4902..0000000000 --- a/gentools/NOTICE +++ /dev/null @@ -1,2 +0,0 @@ -This product includes software developed by The Apache Software Foundation (http://www.apache.org/). - diff --git a/gentools/README.txt b/gentools/README.txt deleted file mode 100644 index 94f705b064..0000000000 --- a/gentools/README.txt +++ /dev/null @@ -1,61 +0,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. -================================================================================ - -AMQP MULTI_VERSION CODE GENERATOR - -This directory contains the first part of the new multi-AMQP-version code -generator. The Java generation is almost complete, C++ will follow. - -NOTE: The generator has NOT been integrated into the current build, and is -included here to run stand-alone for the purposes of review and comment. As -currently configured, this generator will not interact with any file or -directory outside of this directory. - -To build (from this directory): -rm org/apache/qpid/gentools/*.class -javac org/apache/qpid/gentools/Main.java - -Make sure you are using Sun's JDK1.5.0; Eclipse and gcj do not work. - -To run (from this directory): -java org/apache/qpid/gentools/Main -j [xml_spec_file, ...] - -XML test files are located in the xml-src directory. Pay attention to the -Basic class and Basic.Consume method - these were the primary test vehicles -for this generator. *** NOTE *** These files do not represent any current or -future version of the AMQP specification - do not use in production! - -Folders: --------- -org/apache/qpid/gentools/: Source. -xml-src/: Test AMQP specification files. -templ.java/: Templates for java code generation. -out.java/: Output folder for generated Java files (will be created with use - of -j flag on command-line). -templ.cpp/: (Future:) Templates for C++ code generation. -out.cpp/: Output folder for generated C++ files (will be created with use - of -c flag on command-line). - -For a more detaild description of the generator, see the Qpid Wiki -(http://cwiki.apache.org/qpid/multiple-amqp-version-support.html). - -Please send comments and bugs to me (kim.vdriet [at] redhat.com) or via the -Apache Qpid list (dev [at] qpid.apache.org). - -Kim van der Riet diff --git a/gentools/build b/gentools/build deleted file mode 100755 index a18a984dff..0000000000 --- a/gentools/build +++ /dev/null @@ -1,37 +0,0 @@ -#!/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. -# -# - - -cd src -echo "--------- Building gentools ----------" -echo "Clearing out old build files..." -for f in org/apache/qpid/gentools/*.class; do - if [ -e $f ]; then - rm $f - fi -done -echo "Compiling..." -javac -source=1.5 -target=1.5 org/apache/qpid/gentools/*.java -echo "Done. Try it out..." -java org.apache.qpid.gentools.Main -echo "--------- Building gentools completed ----------" -cd .. diff --git a/gentools/build.xml b/gentools/build.xml deleted file mode 100644 index f6760a215e..0000000000 --- a/gentools/build.xml +++ /dev/null @@ -1,43 +0,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. - - - --> -<project name="gentools" default="compile"> - <property name="src" location="src" /> - - <property name="java.source" value="1.5"/> - <property name="java.target" value="1.5"/> - - <target name="compile"> - <javac srcdir="${src}" source="${java.source}" target="${java.target}" fork="true" debug="on" includeantruntime="false"> - <classpath> - <fileset dir="${src}/../lib"> - <include name="**/*.jar"/> - </fileset> - </classpath> - </javac> - </target> - - <target name="clean"> - <delete> - <fileset dir="${src}/org/apache/qpid/gentools" includes="*.class" /> - </delete> - </target> - -</project> diff --git a/gentools/lib/LICENSE b/gentools/lib/LICENSE deleted file mode 100644 index e69de29bb2..0000000000 --- a/gentools/lib/LICENSE +++ /dev/null diff --git a/gentools/lib/NOTICE b/gentools/lib/NOTICE deleted file mode 100644 index e69de29bb2..0000000000 --- a/gentools/lib/NOTICE +++ /dev/null diff --git a/gentools/lib/README.txt b/gentools/lib/README.txt deleted file mode 100644 index e69de29bb2..0000000000 --- a/gentools/lib/README.txt +++ /dev/null diff --git a/gentools/lib/velocity-1.4.jar b/gentools/lib/velocity-1.4.jar Binary files differdeleted file mode 100644 index 04ec9d2f85..0000000000 --- a/gentools/lib/velocity-1.4.jar +++ /dev/null diff --git a/gentools/lib/velocity-dep-1.4.jar b/gentools/lib/velocity-dep-1.4.jar Binary files differdeleted file mode 100644 index 375712b0e8..0000000000 --- a/gentools/lib/velocity-dep-1.4.jar +++ /dev/null diff --git a/gentools/src/org/apache/qpid/gentools/AmqpClass.java b/gentools/src/org/apache/qpid/gentools/AmqpClass.java deleted file mode 100644 index 26195da2e3..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpClass.java +++ /dev/null @@ -1,197 +0,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. - * - */ -package org.apache.qpid.gentools; - -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.io.PrintStream; -import java.util.Collection; - -public class AmqpClass implements Printable, NodeAware -{ - - private final AmqpVersionSet _versionSet = new AmqpVersionSet(); - private final AmqpFieldMap _fieldMap = new AmqpFieldMap(); - private final AmqpMethodMap _methodMap = new AmqpMethodMap(); - private final AmqpOrdinalVersionMap _indexMap = new AmqpOrdinalVersionMap(); - - - private final String _name; - private final Generator _generator; - - public AmqpClass(String name, Generator generator) - { - _name = name; - _generator = generator; - } - - public boolean addFromNode(Node classNode, int ordinal, AmqpVersion version) - throws AmqpParseException, AmqpTypeMappingException - { - getVersionSet().add(version); - int index = Utils.getNamedIntegerAttribute(classNode, "index"); - AmqpVersionSet indexVersionSet = getIndexMap().get(index); - if (indexVersionSet != null) - { - indexVersionSet.add(version); - } - else - { - indexVersionSet = new AmqpVersionSet(); - indexVersionSet.add(version); - getIndexMap().put(index, indexVersionSet); - } - NodeList nList = classNode.getChildNodes(); - int fieldCntr = getFieldMap().size(); - for (int i = 0; i < nList.getLength(); i++) - { - Node child = nList.item(i); - if (child.getNodeName().compareTo(Utils.ELEMENT_FIELD) == 0) - { - String fieldName = getGenerator().prepareDomainName(Utils.getNamedAttribute(child, - Utils.ATTRIBUTE_NAME)); - AmqpField thisField = getFieldMap().get(fieldName); - if (thisField == null) - { - thisField = new AmqpField(fieldName, getGenerator()); - getFieldMap().add(fieldName, thisField); - } - if (!thisField.addFromNode(child, fieldCntr++, version)) - { - String className = getGenerator().prepareClassName(Utils.getNamedAttribute(classNode, - Utils.ATTRIBUTE_NAME)); - System.out.println("INFO: Generation supression tag found for field " + - className + "." + fieldName + " - removing."); - thisField.removeVersion(version); - getFieldMap().remove(fieldName); - } - } - else if (child.getNodeName().compareTo(Utils.ELEMENT_METHOD) == 0) - { - String methodName = getGenerator().prepareMethodName(Utils.getNamedAttribute(child, - Utils.ATTRIBUTE_NAME)); - AmqpMethod thisMethod = getMethodMap().get(methodName); - if (thisMethod == null) - { - thisMethod = new AmqpMethod(methodName, getGenerator()); - getMethodMap().put(methodName, thisMethod); - } - if (!thisMethod.addFromNode(child, 0, version)) - { - String className = getGenerator().prepareClassName(Utils.getNamedAttribute(classNode, - Utils.ATTRIBUTE_NAME)); - System.out.println("INFO: Generation supression tag found for method " + - className + "." + methodName + " - removing."); - thisMethod.removeVersion(version); - getMethodMap().remove(methodName); - } - } - else if (child.getNodeName().compareTo(Utils.ELEMENT_CODEGEN) == 0) - { - String value = Utils.getNamedAttribute(child, Utils.ATTRIBUTE_VALUE); - if (value.compareTo("no-gen") == 0) - { - return false; - } - } - } - return true; - } - - public void removeVersion(AmqpVersion version) - { - getIndexMap().removeVersion(version); - getFieldMap().removeVersion(version); - getMethodMap().removeVersion(version); - getVersionSet().remove(version); - } - - public void print(PrintStream out, int marginSize, int tabSize) - { - String margin = Utils.createSpaces(marginSize); - String tab = Utils.createSpaces(tabSize); - out.println(margin + "[C] " + getName() + ": " + getVersionSet()); - - for (Integer thisIndex : getIndexMap().keySet()) - { - AmqpVersionSet indexVersionSet = getIndexMap().get(thisIndex); - out.println(margin + tab + "[I] " + thisIndex + indexVersionSet); - } - - for (String thisFieldName : getFieldMap().keySet()) - { - AmqpField thisField = getFieldMap().get(thisFieldName); - thisField.print(out, marginSize + tabSize, tabSize); - } - - for (String thisMethodName : getMethodMap().keySet()) - { - AmqpMethod thisMethod = getMethodMap().get(thisMethodName); - thisMethod.print(out, marginSize + tabSize, tabSize); - } - } - - public AmqpVersionSet getVersionSet() - { - return _versionSet; - } - - public Generator getGenerator() - { - return _generator; - } - - - public AmqpFieldMap getFieldMap() - { - return _fieldMap; - } - - - public AmqpMethodMap getMethodMap() - { - return _methodMap; - } - - public Collection<AmqpMethod> getMethods() - { - return getMethodMap().values(); - } - - - public String getName() - { - return _name; - } - - - public AmqpOrdinalVersionMap getIndexMap() - { - return _indexMap; - } - - public SingleVersionClass asSingleVersionClass(AmqpVersion version) - { - return new SingleVersionClass(this,version, _generator); - } - -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpClassMap.java b/gentools/src/org/apache/qpid/gentools/AmqpClassMap.java deleted file mode 100644 index a27a50d07e..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpClassMap.java +++ /dev/null @@ -1,29 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.util.TreeMap; - -@SuppressWarnings("serial") -public class AmqpClassMap extends TreeMap<String, AmqpClass> -{ - -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpConstant.java b/gentools/src/org/apache/qpid/gentools/AmqpConstant.java deleted file mode 100644 index df5bc6c362..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpConstant.java +++ /dev/null @@ -1,191 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.io.PrintStream; -import java.util.TreeMap; - -/** - * @author kpvdr - * Class to represent the <constant> declaration within the AMQP specification. - * Currently, only integer values exist within the specification, however looking forward - * to other possible types in the future, string and double types are also supported. - * <p/> - * The <constant> declaration in the specification contains only two attributes: - * name and value. - * <p/> - * The value of the constant is mapped against the version(s) for which the name is defined. - * This allows for a change in the value rather than the name only from one version to the next. - */ -@SuppressWarnings("serial") -public class AmqpConstant extends TreeMap<String, AmqpVersionSet> - implements Printable, VersionConsistencyCheck, Comparable<AmqpConstant> -{ - /** - * Constant name as defined by the name attribute of the <constant> declaration. - */ - private final String _name; - - /** - * Set of versions for which this constant name is defined. - */ - private final AmqpVersionSet _versionSet; - - /** - * Constructor - * - * @param name Constant name as defined by the name attribute of the <constant> declaration. - * @param value Constant value as defined by the value attribute of the <constant> declaration. - * @param version AMQP version for which this constant is defined - */ - public AmqpConstant(String name, String value, AmqpVersion version) - { - _name = name; - _versionSet = new AmqpVersionSet(version); - AmqpVersionSet valueVersionSet = new AmqpVersionSet(version); - put(value, valueVersionSet); - } - - - /** - * Get the name of this constant. - * - * @return Name of this constant, being the name attribute of the <constant> declaration - * represented by this class. - */ - public String getName() - { - return _name; - } - - /** - * Get the value of this constant as a String. - * - * @param version AMQP version for which this value is required. - * @return Value of this constant, being the value attribute of the <constant> declaration - * represented by this class. - * @throws AmqpTypeMappingException when a value is requested for a version for which it is not - * defined in the AMQP specifications. - */ - public String getStringValue(AmqpVersion version) - throws AmqpTypeMappingException - { - for (String thisValue : keySet()) - { - AmqpVersionSet versionSet = get(thisValue); - if (versionSet.contains(version)) - { - return thisValue; - } - } - throw new AmqpTypeMappingException("Unable to find value for constant \"" + getName() + - "\" for version " + version.toString() + "."); - } - - /** - * Get the value of this constant as an integer. - * - * @param version AMQP version for which this value is required. - * @return Value of this constant, being the value attribute of the <constant> declaration - * represented by this class. - * @throws AmqpTypeMappingException when a value is requested for a version for which it is not - * defined in the AMQP specifications. - */ - public int getIntegerValue(AmqpVersion version) - throws AmqpTypeMappingException - { - return Integer.parseInt(getStringValue(version)); - } - - /** - * Get the value of this constant as a double. - * - * @param version AMQP version for which this value is required. - * @return Value of this constant, being the value attribute of the <constant> declaration - * represented by this class. - * @throws AmqpTypeMappingException when a value is requested for a version for which it is not - * defined in the AMQP specifications. - */ - public double getDoubleValue(AmqpVersion version) - throws AmqpTypeMappingException - { - return Double.parseDouble(getStringValue(version)); - } - - /** - * Get the version set for this constant. It contains the all the versions for which this - * constant name exists. - * - * @return Set of versions for which this constant exists. - */ - public AmqpVersionSet getVersionSet() - { - return _versionSet; - } - - /* (non-Javadoc) - * @see java.lang.Comparable#compareTo(java.lang.Object) - */ - - public int compareTo(AmqpConstant other) - { - int res = getName().compareTo(other.getName()); - if (res != 0) - { - return res; - } - return getVersionSet().compareTo(other.getVersionSet()); - } - - /* (non-Javadoc) - * @see org.apache.qpid.gentools.VersionConsistencyCheck#isVersionConsistent(org.apache.qpid.gentools.AmqpVersionSet) - */ - public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) - { - if (size() != 1) - { - return false; - } - return get(firstKey()).equals(globalVersionSet); - } - - /* (non-Javadoc) - * @see org.apache.qpid.gentools.Printable#print(java.io.PrintStream, int, int) - */ - public void print(PrintStream out, int marginSize, int tabSize) - { - String margin = Utils.createSpaces(marginSize); - String tab = Utils.createSpaces(tabSize); - if (size() == 1) - { - out.println(margin + tab + "[C] " + getName() + " = \"" + firstKey() + "\" " + getVersionSet()); - } - else - { - out.println(margin + tab + "[C] " + getName() + ": " + getVersionSet()); - for (String thisValue : keySet()) - { - out.println(margin + tab + tab + "= \"" + thisValue + "\" " + get(thisValue)); - } - } - } - -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpConstantSet.java b/gentools/src/org/apache/qpid/gentools/AmqpConstantSet.java deleted file mode 100644 index ab8b8be61e..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpConstantSet.java +++ /dev/null @@ -1,152 +0,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. - * - */ -package org.apache.qpid.gentools; - -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.io.PrintStream; -import java.util.Iterator; -import java.util.TreeSet; - -/** - * @author kpvdr - * This class implements a set collection for {@link AmqpConstant AmqpConstant} objects, being the collection - * of constants accumulated from various AMQP specification files processed. Each name occurs once only in the set. - * The {@link AmqpConstant AmqpConstant} objects (derived from {@link java.util.TreeMap TreeMap}) keep track of - * the value and version(s) assigned to this name. - */ -@SuppressWarnings("serial") -public class AmqpConstantSet implements Printable, NodeAware //, Comparable<AmqpConstantSet> -{ - private final LanguageConverter _converter; - private final TreeSet<AmqpConstant> _constants = new TreeSet<AmqpConstant>(); - private final AmqpVersionSet _versionSet = new AmqpVersionSet(); - - public AmqpConstantSet(LanguageConverter converter) - { - _converter = converter; - - } - - /* (non-Javadoc) - * @see org.apache.qpid.gentools.NodeAware#addFromNode(org.w3c.dom.Node, int, org.apache.qpid.gentools.AmqpVersion) - */ - public boolean addFromNode(Node node, int ordinal, AmqpVersion version) - throws AmqpParseException, AmqpTypeMappingException - { - _versionSet.add(version); - NodeList nodeList = node.getChildNodes(); - for (int i = 0; i < nodeList.getLength(); i++) - { - Node childNode = nodeList.item(i); - if (childNode.getNodeName().compareTo(Utils.ELEMENT_CONSTANT) == 0) - { - String name = getConverter().prepareConstantName(Utils.getNamedAttribute(childNode, Utils.ATTRIBUTE_NAME)); - String value = Utils.getNamedAttribute(childNode, Utils.ATTRIBUTE_VALUE); - // Find this name in the existing set of objects - boolean foundName = false; - Iterator<AmqpConstant> cItr = _constants.iterator(); - while (cItr.hasNext() && !foundName) - { - AmqpConstant thisConstant = cItr.next(); - if (name.compareTo(thisConstant.getName()) == 0) - { - foundName = true; - thisConstant.getVersionSet().add(version); - // Now, find the value in the map - boolean foundValue = false; - for (String thisValue : thisConstant.keySet()) - { - if (value.compareTo(thisValue) == 0) - { - foundValue = true; - // Add this version to existing version set. - AmqpVersionSet versionSet = thisConstant.get(thisValue); - versionSet.add(version); - } - } - // Check that the value was found - if not, add it - if (!foundValue) - { - thisConstant.put(value, new AmqpVersionSet(version)); - } - } - } - // Check that the name was found - if not, add it - if (!foundName) - { - _constants.add(new AmqpConstant(name, value, version)); - } - } - } - return true; - } - - /* (non-Javadoc) - * @see org.apache.qpid.gentools.Printable#print(java.io.PrintStream, int, int) - */ - public void print(PrintStream out, int marginSize, int tabSize) - { - out.println(Utils.createSpaces(marginSize) + "Constants: "); - for (AmqpConstant thisAmqpConstant : _constants) - { - thisAmqpConstant.print(out, marginSize, tabSize); - } - } - - /* (non-Javadoc) - * @see java.lang.Comparable#compareTo(java.lang.Object) - */ -// public int compareTo(AmqpConstantSet other) -// { -// int res = size() - other.size(); -// if (res != 0) -// return res; -// Iterator<AmqpConstant> cItr = iterator(); -// Iterator<AmqpConstant> oItr = other.iterator(); -// while (cItr.hasNext() && oItr.hasNext()) -// { -// AmqpConstant constant = cItr.next(); -// AmqpConstant oConstant = oItr.next(); -// res = constant.compareTo(oConstant); -// if (res != 0) -// return res; -// } -// return 0; -// } - - public Iterable<? extends AmqpConstant> getContstants() - { - return _constants; - } - - public AmqpVersionSet getVersionSet() - { - return _versionSet; - } - - public LanguageConverter getConverter() - { - return _converter; - } - -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpDomain.java b/gentools/src/org/apache/qpid/gentools/AmqpDomain.java deleted file mode 100644 index ba8552a6a6..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpDomain.java +++ /dev/null @@ -1,89 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.io.PrintStream; -import java.util.TreeMap; - -@SuppressWarnings("serial") -public class AmqpDomain extends TreeMap<String, AmqpVersionSet> implements Printable -{ - private final String _domainName; - - public AmqpDomain(String domainName) - { - _domainName = domainName; - } - - public void addDomain(String domainType, AmqpVersion version) throws AmqpParseException - { - AmqpVersionSet versionSet = get(domainType); - if (versionSet == null) // First time, create new entry - { - versionSet = new AmqpVersionSet(); - put(domainType, versionSet); - } - versionSet.add(version); - } - - public String getDomainType(AmqpVersion version) - throws AmqpTypeMappingException - { - for (String thisDomainType : keySet()) - { - AmqpVersionSet versionSet = get(thisDomainType); - if (versionSet.contains(version)) - { - return thisDomainType; - } - } - throw new AmqpTypeMappingException("Unable to find version " + version + "."); - } - - public boolean hasVersion(String type, AmqpVersion v) - { - AmqpVersionSet vs = get(type); - if (vs == null) - { - return false; - } - return vs.contains(v); - } - - public void print(PrintStream out, int marginSize, int tabSize) - { - String margin = Utils.createSpaces(marginSize); - String tab = Utils.createSpaces(tabSize); - out.println(margin + getDomainName() + ":"); - - for (String thisDomainType : keySet()) - { - AmqpVersionSet vs = get(thisDomainType); - out.println(margin + tab + thisDomainType + " : " + vs.toString()); - } - } - - public String getDomainName() - { - return _domainName; - } - -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpDomainMap.java b/gentools/src/org/apache/qpid/gentools/AmqpDomainMap.java deleted file mode 100644 index 0cd9d214bd..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpDomainMap.java +++ /dev/null @@ -1,128 +0,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. - * - */ -package org.apache.qpid.gentools; - -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.io.PrintStream; -import java.util.TreeMap; - -@SuppressWarnings("serial") -public class AmqpDomainMap extends TreeMap<String, AmqpDomain> implements Printable, NodeAware -{ - private final LanguageConverter _converter; - - public AmqpDomainMap(LanguageConverter converter) - { - _converter = converter; - - } - - public boolean addFromNode(Node n, int o, AmqpVersion v) - throws AmqpParseException, AmqpTypeMappingException - { - NodeList nl = n.getChildNodes(); - for (int i = 0; i < nl.getLength(); i++) - { - Node c = nl.item(i); - // All versions 0.9 and greater use <domain> for all domains - if (c.getNodeName().compareTo(Utils.ELEMENT_DOMAIN) == 0) - { - String domainName = getConverter().prepareDomainName(Utils.getNamedAttribute(c, Utils.ATTRIBUTE_NAME)); - String type = Utils.getNamedAttribute(c, Utils.ATTRIBUTE_TYPE); - AmqpDomain thisDomain = get(domainName); - if (thisDomain == null) - { - thisDomain = new AmqpDomain(domainName); - put(domainName, thisDomain); - } - thisDomain.addDomain(type, v); - } - // Version(s) 0.8 and earlier use <domain> for all complex domains and use - // attribute <field type=""...> for simple types. Add these simple types to - // domain list - but beware of duplicates! - else if (c.getNodeName().compareTo(Utils.ELEMENT_FIELD) == 0) - { - try - { - String type = getConverter().prepareDomainName(Utils.getNamedAttribute(c, Utils.ATTRIBUTE_TYPE)); - AmqpDomain thisDomain = get(type); - if (thisDomain == null) - { - thisDomain = new AmqpDomain(type); - put(type, thisDomain); - } - if (!thisDomain.hasVersion(type, v)) - { - thisDomain.addDomain(type, v); - } - } - catch (AmqpParseException e) - { - } // Ignore fields without type attribute - } - else if (c.getNodeName().compareTo(Utils.ELEMENT_CLASS) == 0 || - c.getNodeName().compareTo(Utils.ELEMENT_METHOD) == 0) - { - addFromNode(c, 0, v); - } - } - return true; - } - - public String getDomainType(String domainName, AmqpVersion version) - { - AmqpDomain domainType = get(domainName); - // For AMQP 8.0, primitive types were not described as domains, so - // return itself as the type. - if (domainType == null) - { - return domainName; - } - try - { - return domainType.getDomainType(version); - } - catch (AmqpTypeMappingException e) - { - throw new AmqpTypeMappingException("Unable to find domain type for domain \"" + domainName + - "\" version " + version + "."); - } - } - - - public void print(PrintStream out, int marginSize, int tabSize) - { - out.println(Utils.createSpaces(marginSize) + "Domain Map:"); - for (String thisDomainName : keySet()) - { - AmqpDomain domain = get(thisDomainName); - domain.print(out, marginSize + tabSize, tabSize); - } - } - - public LanguageConverter getConverter() - { - return _converter; - } - -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpDomainVersionMap.java b/gentools/src/org/apache/qpid/gentools/AmqpDomainVersionMap.java deleted file mode 100644 index e39550b96f..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpDomainVersionMap.java +++ /dev/null @@ -1,62 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.util.ArrayList; -import java.util.TreeMap; - -@SuppressWarnings("serial") -public class AmqpDomainVersionMap extends TreeMap<String, AmqpVersionSet> implements VersionConsistencyCheck -{ - public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) - { - if (size() != 1) - { - return false; - } - return get(firstKey()).equals(globalVersionSet); - } - - public boolean removeVersion(AmqpVersion version) - { - Boolean res = false; - ArrayList<String> removeList = new ArrayList<String>(); - for (String domainName : keySet()) - { - AmqpVersionSet versionSet = get(domainName); - if (versionSet.contains(version)) - { - versionSet.remove(version); - if (versionSet.isEmpty()) - { - removeList.add(domainName); - } - res = true; - } - } - // Get rid of domains no longer in use - for (String domainName : removeList) - { - remove(domainName); - } - return res; - } -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpField.java b/gentools/src/org/apache/qpid/gentools/AmqpField.java deleted file mode 100644 index 7c721cf913..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpField.java +++ /dev/null @@ -1,269 +0,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. - * - */ -package org.apache.qpid.gentools; - -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -public class AmqpField implements Printable, NodeAware, VersionConsistencyCheck -{ - - private final AmqpVersionSet _versionSet = new AmqpVersionSet(); - private final AmqpDomainVersionMap _domainMap = new AmqpDomainVersionMap(); - private final AmqpOrdinalVersionMap _ordinalMap = new AmqpOrdinalVersionMap(); - - private final String _name; - private final Generator _generator; - - private final Map<AmqpVersion, String> _versionToDomainMap = new HashMap<AmqpVersion, String>(); - private final Map<AmqpVersion, Integer> _versionToOrdinalMap = new HashMap<AmqpVersion, Integer>(); - - - public AmqpField(String name, Generator generator) - { - _name = name; - _generator = generator; - - } - - public boolean addFromNode(Node fieldNode, int ordinal, AmqpVersion version) - throws AmqpParseException, AmqpTypeMappingException - { - _versionSet.add(version); - String domainType; - // Early versions of the spec (8.0) used the "type" attribute instead of "domain" for some fields. - try - { - domainType = _generator.prepareDomainName(Utils.getNamedAttribute(fieldNode, Utils.ATTRIBUTE_DOMAIN)); - } - catch (AmqpParseException e) - { - domainType = _generator.prepareDomainName(Utils.getNamedAttribute(fieldNode, Utils.ATTRIBUTE_TYPE)); - } - AmqpVersionSet thisVersionList = _domainMap.get(domainType); - if (thisVersionList == null) // First time, create new entry - { - thisVersionList = new AmqpVersionSet(); - _domainMap.put(domainType, thisVersionList); - } - - _versionToDomainMap.put(version, domainType); - _versionToOrdinalMap.put(version, ordinal); - - thisVersionList.add(version); - thisVersionList = _ordinalMap.get(ordinal); - if (thisVersionList == null) // First time, create new entry - { - thisVersionList = new AmqpVersionSet(); - _ordinalMap.put(ordinal, thisVersionList); - } - thisVersionList.add(version); - NodeList nList = fieldNode.getChildNodes(); - for (int i = 0; i < nList.getLength(); i++) - { - Node child = nList.item(i); - if (child.getNodeName().compareTo(Utils.ELEMENT_CODEGEN) == 0) - { - String value = Utils.getNamedAttribute(child, Utils.ATTRIBUTE_VALUE); - if (value.compareTo("no-gen") == 0) - { - return false; - } - } - } - return true; - } - - public void removeVersion(AmqpVersion version) - { - _domainMap.removeVersion(version); - _ordinalMap.removeVersion(version); - _versionSet.remove(version); - } - - public boolean isCodeTypeConsistent(LanguageConverter converter) - throws AmqpTypeMappingException - { - if (_domainMap.size() == 1) - { - return true; // By definition - } - ArrayList<String> codeTypeList = new ArrayList<String>(); - for (String thisDomainName : _domainMap.keySet()) - { - AmqpVersionSet versionSet = _domainMap.get(thisDomainName); - String codeType = converter.getGeneratedType(thisDomainName, versionSet.first()); - if (!codeTypeList.contains(codeType)) - { - codeTypeList.add(codeType); - } - } - return codeTypeList.size() == 1; - } - - public boolean isConsistent(Generator generator) - throws AmqpTypeMappingException - { - if (!isCodeTypeConsistent(generator)) - { - return false; - } - if (_ordinalMap.size() != 1) - { - return false; - } - // Since the various doamin names map to the same code type, add the version occurrences - // across all domains to see we have all possible versions covered - int vCntr = 0; - for (String thisDomainName : _domainMap.keySet()) - { - vCntr += _domainMap.get(thisDomainName).size(); - } - return vCntr == generator.getVersionSet().size(); - } - - public boolean isTypeAndNameConsistent(Generator generator) - throws AmqpTypeMappingException - { - if (!isCodeTypeConsistent(generator)) - { - return false; - } - // Since the various doamin names map to the same code type, add the version occurrences - // across all domains to see we have all possible versions covered - int vCntr = 0; - for (String thisDomainName : _domainMap.keySet()) - { - vCntr += _domainMap.get(thisDomainName).size(); - } - return vCntr == getVersionSet().size(); - } - - - public void print(PrintStream out, int marginSize, int tabSize) - { - String margin = Utils.createSpaces(marginSize); - out.println(margin + "[F] " + _name + ": " + _versionSet); - - for (Integer thisOrdinal : _ordinalMap.keySet()) - { - AmqpVersionSet versionList = _ordinalMap.get(thisOrdinal); - out.println(margin + " [O] " + thisOrdinal + " : " + versionList.toString()); - } - - for (String thisDomainName : _domainMap.keySet()) - { - AmqpVersionSet versionList = _domainMap.get(thisDomainName); - out.println(margin + " [D] " + thisDomainName + " : " + versionList.toString()); - } - } - - public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) - { - if (!_versionSet.equals(globalVersionSet)) - { - return false; - } - if (!_domainMap.isVersionConsistent(globalVersionSet)) - { - return false; - } - if (!_ordinalMap.isVersionConsistent(globalVersionSet)) - { - return false; - } - return true; - } - - - public boolean isVersionInterfaceConsistent(AmqpVersionSet globalVersionSet) - { - if (!_versionSet.equals(globalVersionSet)) - { - return false; - } - if (!_domainMap.isVersionConsistent(globalVersionSet)) - { - return false; - } - if (!_ordinalMap.isVersionConsistent(globalVersionSet)) - { - return false; - } - return true; - } - - public String getDomain(AmqpVersion version) - { - return _versionToDomainMap.get(version); - } - - public String getConsistentNativeType() - { - return _generator.getNativeType(_generator.getDomainType(getDomain(_versionSet.first()),_versionSet.first())); - } - - public int getOrdinal(AmqpVersion version) - { - return _versionToOrdinalMap.get(version); - } - - public AmqpVersionSet getVersionSet() - { - return _versionSet; - } - - public AmqpDomainVersionMap getDomainMap() - { - return _domainMap; - } - - public AmqpOrdinalVersionMap getOrdinalMap() - { - return _ordinalMap; - } - - public String getName() - { - return _name; - } - - public LanguageConverter getGenerator() - { - return _generator; - } - - public Map<AmqpVersion, String> getVersionToDomainMap() - { - return _versionToDomainMap; - } - - public Map<AmqpVersion, Integer> getVersionToOrdinalMap() - { - return _versionToOrdinalMap; - } - -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpFieldMap.java b/gentools/src/org/apache/qpid/gentools/AmqpFieldMap.java deleted file mode 100644 index 0bb5e03a61..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpFieldMap.java +++ /dev/null @@ -1,452 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeMap; - -@SuppressWarnings("serial") -public class AmqpFieldMap implements VersionConsistencyCheck -{ - - private final TreeMap<String, AmqpField> _map = new TreeMap<String, AmqpField>(); - - private final AmqpVersionSet _versionSet = new AmqpVersionSet(); - - public void removeVersion(AmqpVersion version) - { - String[] fieldNameArray = new String[size()]; - _map.keySet().toArray(fieldNameArray); - Iterator<Entry<String, AmqpField>> iter = _map.entrySet().iterator(); - - while (iter.hasNext()) - { - Entry<String, AmqpField> entry = iter.next(); - entry.getValue().removeVersion(version); - iter.remove(); - } - } - - public int size() - { - return _map.size(); - - } - - public AmqpFieldMap getFieldMapForOrdinal(int ordinal) - { - AmqpFieldMap newMap = new AmqpFieldMap(); - for (AmqpField field : _map.values()) - { - - TreeMap<Integer, AmqpVersionSet> ordinalMap = field.getOrdinalMap(); - AmqpVersionSet ordinalVersions = ordinalMap.get(ordinal); - if (ordinalVersions != null) - { - newMap.add(field.getName(), field); - } - } - return newMap; - } - - public void add(String name, AmqpField field) - { - _versionSet.addAll(field.getVersionSet()); - _map.put(name, field); - } - - public AmqpOrdinalFieldMap getMapForVersion(AmqpVersion version, boolean codeTypeFlag, - LanguageConverter converter) - { - // TODO: REVIEW THIS! There may be a bug here that affects C++ generation (only with >1 version)... - // If version == null (a common scenario) then the version map is built up on the - // basis of first found item, and ignores other version variations. - // This should probably be disallowed by throwing an NPE, as AmqpOrdinalFieldMap cannot - // represent these possibilities. - // *OR* - // Change the structure of AmqpOrdianlFieldMap to allow for the various combinations that - // will result from version variation - but that is what AmqpFieldMap is... :-$ - AmqpOrdinalFieldMap ordinalFieldMap = new AmqpOrdinalFieldMap(); - for (AmqpField field : _map.values()) - { - - if (version == null || field.getVersionSet().contains(version)) - { - // 1. Search for domain name in field domain map with version that matches - String domain = ""; - boolean dFound = false; - for (String thisDomainName : field.getDomainMap().keySet()) - { - domain = thisDomainName; - AmqpVersionSet versionSet = field.getDomainMap().get(domain); - if (version == null || versionSet.contains(version)) - { - if (codeTypeFlag) - { - domain = converter.getGeneratedType(domain, version); - } - dFound = true; - } - } - - // 2. Search for ordinal in field ordianl map with version that matches - int ordinal = -1; - boolean oFound = false; - for (Integer thisOrdinal : field.getOrdinalMap().keySet()) - { - ordinal = thisOrdinal; - AmqpVersionSet versionSet = field.getOrdinalMap().get(ordinal); - if (version == null || versionSet.contains(version)) - { - oFound = true; - } - } - - if (dFound && oFound) - { - String[] fieldDomainPair = {field.getName(), domain}; - ordinalFieldMap.put(ordinal, fieldDomainPair); - } - } - } - return ordinalFieldMap; - } - - public boolean isDomainConsistent(Generator generator, AmqpVersionSet versionSet) - throws AmqpTypeMappingException - { - if (size() != 1) // Only one field for this ordinal - { - return false; - } - return _map.get(_map.firstKey()).isConsistent(generator); - } - - public int getNumFields(AmqpVersion version) - { - int fCntr = 0; - for (AmqpField field : _map.values()) - { - - if (field.getVersionSet().contains(version)) - { - fCntr++; - } - } - return fCntr; - } - - public String parseFieldMap(CommandGenerateMethod commonGenerateMethod, MangledGenerateMethod mangledGenerateMethod, - int indentSize, int tabSize, LanguageConverter converter) - { - String indent = Utils.createSpaces(indentSize); - String cr = Utils.LINE_SEPARATOR; - StringBuffer sb = new StringBuffer(); - - if (commonGenerateMethod == null) - { - // Generate warnings in code if required methods are null. - sb.append(indent + "/*********************************************************" + cr); - sb.append(indent + " * WARNING: Generated code could be missing." + cr); - sb.append(indent + " * In call to parseFieldMap(), generation method was null." + cr); - sb.append(indent + " * Check for NoSuchMethodException on startup." + cr); - sb.append(indent + " *********************************************************/" + cr); - } - - Iterator<Entry<String, AmqpField>> itr = _map.entrySet().iterator(); - while (itr.hasNext()) - { - Entry<String, AmqpField> entry = itr.next(); - String fieldName = entry.getKey(); - AmqpField field = entry.getValue(); - if (field.isCodeTypeConsistent(converter)) - { - // All versions identical - Common declaration - String domainName = field.getDomainMap().firstKey(); - AmqpVersionSet versionSet = field.getDomainMap().get(domainName); - String codeType = converter.getGeneratedType(domainName, versionSet.first()); - if (commonGenerateMethod != null) - { - sb.append(commonGenerateMethod.generate(codeType, field, versionSet, - indentSize, tabSize, itr.hasNext())); - } - } - else if (mangledGenerateMethod != null) // Version-mangled - { - sb.append(mangledGenerateMethod.generate(field, indentSize, tabSize, - itr.hasNext())); - } - } - return sb.toString(); - } - - public String parseFieldMapOrdinally(GenerateMethod generateMethod, BitFieldGenerateMethod bitGenerateMethod, - int indentSize, int tabSize, Generator codeGenerator) - { - String indent = Utils.createSpaces(indentSize); - String cr = Utils.LINE_SEPARATOR; - StringBuffer sb = new StringBuffer(); - - // Generate warnings in code if required methods are null. - if (generateMethod == null || bitGenerateMethod == null) - { - sb.append(indent + "/***********************************************" + cr); - sb.append(indent + " * WARNING: In call to parseFieldMapOrdinally():" + cr); - if (generateMethod == null) - { - sb.append(indent + " * => generateMethod is null." + cr); - } - if (bitGenerateMethod == null) - { - sb.append(indent + " * => bitGenerateMethod is null." + cr); - } - sb.append(indent + " * Generated code could be missing." + cr); - sb.append(indent + " * Check for NoSuchMethodException on startup." + cr); - sb.append(indent + " ***********************************************/" + cr); - } - - /* We must process elements in ordinal order because adjacent booleans (bits) - * must be combined into a single byte (in groups of up to 8). Start with shared - * declarations until an ordinal divergence is found. (For most methods where - * there is no difference between versions, this will simplify the generated - * code. */ - - ArrayList<String> bitFieldList = new ArrayList<String>(); - boolean ordinalDivergenceFlag = false; - int ordinal = 0; - while (ordinal < size() && !ordinalDivergenceFlag) - { - /* Since the getFieldMapOrdinal() function may map more than one Field to - * an ordinal, the number of ordinals may be less than the total number of - * fields in the fieldMap. Check for empty fieldmaps... */ - AmqpFieldMap ordinalFieldMap = getFieldMapForOrdinal(ordinal); - if (ordinalFieldMap.size() > 0) - { - if (ordinalFieldMap.isDomainConsistent(codeGenerator, getVersionSet())) - { - String fieldName = ordinalFieldMap.getFirstFieldName(); - String domain = ordinalFieldMap._map.get(fieldName).getDomainMap().firstKey(); - - String domainType = codeGenerator.getDomainType(domain, - codeGenerator.getVersionSet().first()); - - if (domainType.compareTo("bit") == 0) - { - bitFieldList.add(fieldName); - } - else if (bitFieldList.size() > 0) - { - // End of bit types - handle deferred bit type generation - if (bitGenerateMethod != null) - { - sb.append(bitGenerateMethod.generate(bitFieldList, ordinal, - indentSize, tabSize)); - } - bitFieldList.clear(); - } - if (!ordinalDivergenceFlag) - { - // Defer generation of bit types until all adjacent bits have been - // accounted for. - if (bitFieldList.size() == 0 && generateMethod != null) - { - sb.append(generateMethod.generate(domainType, fieldName, ordinal, - indentSize, tabSize)); - } - } - ordinal++; - } - else - { - ordinalDivergenceFlag = true; - } - } - } - - // Check if there is still more to do under a version-specific breakout - if (ordinalDivergenceFlag && ordinal < size()) - { - // 1. Cycle through all versions in order, create outer if(version) structure - AmqpVersion[] versionArray = new AmqpVersion[getVersionSet().size()]; - getVersionSet().toArray(versionArray); - for (int v = 0; v < versionArray.length; v++) - { - sb.append(indent); - if (v > 0) - { - sb.append("else "); - } - sb.append("if (major == " + versionArray[v].getMajor() + " && minor == " + - versionArray[v].getMinor() + ")" + cr); - sb.append(indent + "{" + cr); - - // 2. Cycle though each ordinal from where we left off in the loop above. - ArrayList<String> bitFieldList2 = new ArrayList<String>(bitFieldList); - for (int o = ordinal; o < size(); o++) - { - AmqpFieldMap ordinalFieldMap = getFieldMapForOrdinal(o); - if (ordinalFieldMap.size() > 0) - { - // 3. Cycle through each of the fields that have this ordinal. - Iterator<Map.Entry<String, AmqpField>> i = ordinalFieldMap._map.entrySet().iterator(); - while (i.hasNext()) - { - - Map.Entry<String, AmqpField> entry = i.next(); - AmqpField field = entry.getValue(); - String fieldName = entry.getKey(); - - // 4. Some fields may have more than one ordinal - match by both - // ordinal and version. - Iterator<Integer> j = field.getOrdinalMap().keySet().iterator(); - while (j.hasNext()) - { - int thisOrdinal = j.next(); - AmqpVersionSet v1 = field.getOrdinalMap().get(thisOrdinal); - if (thisOrdinal == o && v1.contains(versionArray[v])) - { - // 5. Now get the domain for this version - int domainCntr = 0; - Iterator<String> k = field.getDomainMap().keySet().iterator(); - while (k.hasNext()) - { - // Mangle domain-divergent field names - String mangledFieldName = fieldName; - if (field.getDomainMap().size() > 1) - { - mangledFieldName += "_" + (domainCntr++); - } - String domainName = k.next(); - AmqpVersionSet v2 = field.getDomainMap().get(domainName); - if (v2.contains(versionArray[v])) - { - // 6. (Finally!!) write the declaration - String domainType = codeGenerator.getDomainType(domainName, - versionArray[v]); - if (domainType.compareTo("bit") == 0) - { - bitFieldList2.add(mangledFieldName); - } - else if (bitFieldList2.size() > 0) - { - // End of bit types - handle deferred bit type generation - if (bitGenerateMethod != null) - { - sb.append(bitGenerateMethod.generate( - bitFieldList2, o, indentSize + tabSize, - tabSize)); - } - bitFieldList2.clear(); - } - // Defer generation of bit types until all adjacent bits have - // been accounted for. - if (bitFieldList2.size() == 0 && generateMethod != null) - { - sb.append(generateMethod.generate(domainType, - mangledFieldName, o, indentSize + tabSize, tabSize)); - } - } - } - } - } - } - } - } - // Check for remaining deferred bits - if (bitFieldList2.size() > 0 && bitGenerateMethod != null) - { - sb.append(bitGenerateMethod.generate(bitFieldList2, size(), - indentSize + tabSize, tabSize)); - } - sb.append(indent + "}" + cr); - } - } - // Check for remaining deferred bits - else if (bitFieldList.size() > 0 && bitGenerateMethod != null) - { - sb.append(bitGenerateMethod.generate(bitFieldList, size(), - indentSize, tabSize)); - } - return sb.toString(); - } - - private String getFirstFieldName() - { - return _map.firstKey(); - } - - public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) - { - for (String thisFieldName : _map.keySet()) - { - AmqpField field = _map.get(thisFieldName); - if (!field.isVersionConsistent(globalVersionSet)) - { - return false; - } - } - return true; - } - - public boolean isVersionInterfaceConsistent(AmqpVersionSet globalVersionSet) - { - for (String thisFieldName : _map.keySet()) - { - AmqpField field = _map.get(thisFieldName); - if (!field.isVersionInterfaceConsistent(globalVersionSet)) - { - return false; - } - } - return true; - } - - - public AmqpVersionSet getVersionSet() - { - return _versionSet; - } - - public Collection<AmqpField> values() - { - return _map.values(); - } - - public AmqpField get(String fieldName) - { - return _map.get(fieldName); - } - - public void remove(String fieldName) - { - _map.remove(fieldName); - } - - public Set<String> keySet() - { - return _map.keySet(); - } -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpFlagMap.java b/gentools/src/org/apache/qpid/gentools/AmqpFlagMap.java deleted file mode 100644 index 5993a1b715..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpFlagMap.java +++ /dev/null @@ -1,77 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.util.ArrayList; -import java.util.TreeMap; - -@SuppressWarnings("serial") -public class AmqpFlagMap extends TreeMap<Boolean, AmqpVersionSet> implements VersionConsistencyCheck -{ - public boolean isSet() - { - return containsKey(true); - } - - public String toString() - { - AmqpVersionSet versionSet = get(true); - if (versionSet != null) - { - return versionSet.toString(); - } - return ""; - } - - public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) - { - if (size() != 1) - { - return false; - } - return get(firstKey()).equals(globalVersionSet); - } - - public boolean removeVersion(AmqpVersion version) - { - Boolean res = false; - ArrayList<Boolean> removeList = new ArrayList<Boolean>(); - for (Boolean flag : keySet()) - { - AmqpVersionSet versionSet = get(flag); - if (versionSet.contains(version)) - { - versionSet.remove(version); - if (versionSet.isEmpty()) - { - removeList.add(flag); - } - res = true; - } - } - // Get rid of flags no longer in use - for (Boolean flag : removeList) - { - remove(flag); - } - return res; - } -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpMethod.java b/gentools/src/org/apache/qpid/gentools/AmqpMethod.java deleted file mode 100644 index 4ec39b209e..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpMethod.java +++ /dev/null @@ -1,351 +0,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. - * - */ -package org.apache.qpid.gentools; - -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.io.PrintStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Collection; -import java.util.concurrent.atomic.AtomicInteger; - -public class AmqpMethod implements Printable, NodeAware, VersionConsistencyCheck -{ - private final AmqpVersionSet _versionSet = new AmqpVersionSet(); - private final AmqpFieldMap _fieldMap = new AmqpFieldMap(); - - private final AmqpOrdinalVersionMap _indexMap = new AmqpOrdinalVersionMap(); - private final AmqpFlagMap _clientMethodFlagMap = new AmqpFlagMap(); // Method called on client (<chassis name="server"> in XML) - private final AmqpFlagMap _serverMethodFlagMap = new AmqpFlagMap(); // Method called on server (<chassis name="client"> in XML) - - private final Map<AmqpVersion, AmqpFieldMap> _versionToFieldsMap = new HashMap<AmqpVersion, AmqpFieldMap>(); - - private final Map<AmqpVersion, AtomicInteger> _versionToFieldCount = new HashMap<AmqpVersion, AtomicInteger>(); - - private final String _name; - private final Generator _generator; - - - public AmqpMethod(String name, Generator generator) - { - _name = name; - _generator = generator; - } - - public boolean addFromNode(Node methodNode, int ordinal, AmqpVersion version) - throws AmqpParseException, AmqpTypeMappingException - { - _versionSet.add(version); - boolean serverChassisFlag = false; - boolean clientChassisFlag = false; - int index = Utils.getNamedIntegerAttribute(methodNode, "index"); - AmqpVersionSet indexVersionSet = _indexMap.get(index); - if (indexVersionSet != null) - { - indexVersionSet.add(version); - } - else - { - indexVersionSet = new AmqpVersionSet(); - indexVersionSet.add(version); - _indexMap.put(index, indexVersionSet); - } - NodeList nList = methodNode.getChildNodes(); - AtomicInteger fieldCntr = _versionToFieldCount.get(version); - if(fieldCntr == null) - { - fieldCntr = new AtomicInteger(0); - _versionToFieldCount.put(version, fieldCntr); - } - for (int i = 0; i < nList.getLength(); i++) - { - Node child = nList.item(i); - if (child.getNodeName().compareTo(Utils.ELEMENT_FIELD) == 0) - { - String fieldName = _generator.prepareDomainName(Utils.getNamedAttribute(child, - Utils.ATTRIBUTE_NAME)); - AmqpField thisField = _fieldMap.get(fieldName); - AmqpFieldMap versionSpecificFieldMap = _versionToFieldsMap.get(version); - if (versionSpecificFieldMap == null) - { - versionSpecificFieldMap = new AmqpFieldMap(); - _versionToFieldsMap.put(version, versionSpecificFieldMap); - } - - - if (thisField == null) - { - thisField = new AmqpField(fieldName, _generator); - _fieldMap.add(fieldName, thisField); - } - - AmqpField versionSpecificField = new AmqpField(fieldName, _generator); - versionSpecificFieldMap.add(fieldName, versionSpecificField); - - versionSpecificField.addFromNode(child, fieldCntr.intValue(), version); - - if (!thisField.addFromNode(child, fieldCntr.getAndIncrement(), version)) - { - String className = _generator.prepareClassName(Utils.getNamedAttribute(methodNode.getParentNode(), - Utils.ATTRIBUTE_NAME)); - String methodName = _generator.prepareMethodName(Utils.getNamedAttribute(methodNode, - Utils.ATTRIBUTE_NAME)); - System.out.println("INFO: Generation supression tag found for field " + - className + "." + methodName + "." + fieldName + " - removing."); - thisField.removeVersion(version); - _fieldMap.remove(fieldName); - } - } - else if (child.getNodeName().compareTo(Utils.ELEMENT_CHASSIS) == 0) - { - String chassisName = Utils.getNamedAttribute(child, Utils.ATTRIBUTE_NAME); - if (chassisName.compareTo("server") == 0) - { - serverChassisFlag = true; - } - else if (chassisName.compareTo("client") == 0) - { - clientChassisFlag = true; - } - } - else if (child.getNodeName().compareTo(Utils.ELEMENT_CODEGEN) == 0) - { - String value = Utils.getNamedAttribute(child, Utils.ATTRIBUTE_VALUE); - if (value.compareTo("no-gen") == 0) - { - return false; - } - } - } - processChassisFlags(serverChassisFlag, clientChassisFlag, version); - return true; - } - - public void removeVersion(AmqpVersion version) - { - _clientMethodFlagMap.removeVersion(version); - _serverMethodFlagMap.removeVersion(version); - _indexMap.removeVersion(version); - _fieldMap.removeVersion(version); - _versionSet.remove(version); - } - - public void print(PrintStream out, int marginSize, int tabSize) - { - String margin = Utils.createSpaces(marginSize); - String tab = Utils.createSpaces(tabSize); - out.println(margin + "[M] " + _name + " {" + (_serverMethodFlagMap.isSet() ? "S " + - _serverMethodFlagMap + ( - _clientMethodFlagMap.isSet() ? ", " : "") : "") + - (_clientMethodFlagMap.isSet() - ? "C " + _clientMethodFlagMap : "") + "}" + ": " + - _versionSet); - - for (Integer thisIndex : _indexMap.keySet()) - { - AmqpVersionSet indexVersionSet = _indexMap.get(thisIndex); - out.println(margin + tab + "[I] " + thisIndex + indexVersionSet); - } - - for (String thisFieldName : _fieldMap.keySet()) - { - AmqpField thisField = _fieldMap.get(thisFieldName); - thisField.print(out, marginSize + tabSize, tabSize); - } - } - - protected void processChassisFlags(boolean serverFlag, boolean clientFlag, AmqpVersion version) - { - AmqpVersionSet versionSet = _serverMethodFlagMap.get(serverFlag); - if (versionSet != null) - { - versionSet.add(version); - } - else - { - versionSet = new AmqpVersionSet(); - versionSet.add(version); - _serverMethodFlagMap.put(serverFlag, versionSet); - } - - versionSet = _clientMethodFlagMap.get(clientFlag); - if (versionSet != null) - { - versionSet.add(version); - } - else - { - versionSet = new AmqpVersionSet(); - versionSet.add(version); - _clientMethodFlagMap.put(clientFlag, versionSet); - } - } - - public AmqpOverloadedParameterMap getOverloadedParameterLists(AmqpVersionSet globalVersionSet, - Generator generator) - throws AmqpTypeMappingException - { - AmqpOverloadedParameterMap parameterVersionMap = new AmqpOverloadedParameterMap(); - for (AmqpVersion thisVersion : globalVersionSet) - { - AmqpOrdinalFieldMap ordinalFieldMap = _fieldMap.getMapForVersion(thisVersion, true, generator); - AmqpVersionSet methodVersionSet = parameterVersionMap.get(ordinalFieldMap); - if (methodVersionSet == null) - { - methodVersionSet = new AmqpVersionSet(); - methodVersionSet.add(thisVersion); - parameterVersionMap.put(ordinalFieldMap, methodVersionSet); - } - else - { - methodVersionSet.add(thisVersion); - } - } - return parameterVersionMap; - } - - public boolean isVersionInterfaceConsistent() - { - return isVersionInterfaceConsistent(_generator.getVersionSet()); - } - - public boolean isVersionInterfaceConsistent(AmqpVersionSet globalVersionSet) - { - if (!_versionSet.equals(globalVersionSet)) - { - return false; - } - if (!_clientMethodFlagMap.isVersionConsistent(globalVersionSet)) - { - return false; - } - if (!_serverMethodFlagMap.isVersionConsistent(globalVersionSet)) - { - return false; - } - if (!_fieldMap.isVersionInterfaceConsistent(globalVersionSet)) - { - return false; - } - return true; - } - - public boolean isVersionConsistent() - { - return isVersionConsistent(_generator.getVersionSet()); - } - - - public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) - { - return isVersionInterfaceConsistent(globalVersionSet) - && _indexMap.isVersionConsistent(globalVersionSet) - && _fieldMap.isVersionConsistent(globalVersionSet); - } - - public AmqpVersionSet getVersionSet() - { - return _versionSet; - } - - public AmqpFieldMap getFieldMap() - { - return _fieldMap; - } - - public AmqpOrdinalVersionMap getIndexMap() - { - return _indexMap; - } - - public AmqpFlagMap getClientMethodFlagMap() - { - return _clientMethodFlagMap; - } - - public AmqpFlagMap getServerMethodFlagMap() - { - return _serverMethodFlagMap; - } - - public Map<AmqpVersion, AmqpFieldMap> getVersionToFieldsMap() - { - return _versionToFieldsMap; - } - - public String getName() - { - return _name; - } - - public LanguageConverter getGenerator() - { - return _generator; - } - - public SingleVersionMethod asSingleVersionMethod(AmqpVersion version) - { - return new SingleVersionMethod(this, version, _generator); - } - - public Collection<AmqpField> getFields() - { - return _fieldMap.values(); - } - - public boolean isCommon(AmqpField field) - { - return field.getVersionSet().equals(getVersionSet()) && field.isTypeAndNameConsistent(_generator); - } - - public boolean isConsistentServerMethod() - { - AmqpVersionSet serverVersions = _serverMethodFlagMap.get(true); - return (serverVersions != null) && serverVersions.containsAll(_generator.getVersionSet()); - } - - - public boolean isConsistentClientMethod() - { - AmqpVersionSet clientVersions = _clientMethodFlagMap.get(true); - return (clientVersions != null) && clientVersions.containsAll(_generator.getVersionSet()); - } - - public boolean isServerMethod(AmqpVersion version) - { - AmqpVersionSet serverVersions = _serverMethodFlagMap.get(true); - return (serverVersions != null) && serverVersions.contains(version); - } - - - public boolean isClientMethod(AmqpVersion version) - { - AmqpVersionSet clientVersions = _clientMethodFlagMap.get(true); - return (clientVersions != null) && clientVersions.contains(version); - } - - public boolean inAllVersions() - { - return _versionSet.containsAll(_generator.getVersionSet()); - } -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpMethodMap.java b/gentools/src/org/apache/qpid/gentools/AmqpMethodMap.java deleted file mode 100644 index d98dab4a39..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpMethodMap.java +++ /dev/null @@ -1,36 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.util.TreeMap; - -@SuppressWarnings("serial") -public class AmqpMethodMap extends TreeMap<String, AmqpMethod> -{ - public void removeVersion(AmqpVersion version) - { - for (String methodName : keySet()) - { - get(methodName).removeVersion(version); - } - } - -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpModel.java b/gentools/src/org/apache/qpid/gentools/AmqpModel.java deleted file mode 100644 index 45f0adb18d..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpModel.java +++ /dev/null @@ -1,132 +0,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. - * - */ -package org.apache.qpid.gentools; - -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.io.PrintStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Collection; - -public class AmqpModel implements Printable, NodeAware -{ - private final Generator _generator; - private final AmqpClassMap classMap = new AmqpClassMap(); - private final AmqpVersionSet _versionSet = new AmqpVersionSet(); - - private final Map<AmqpVersion, AmqpClassMap> _versionToClassMapMap = new HashMap<AmqpVersion, AmqpClassMap>(); - - public AmqpModel(Generator generator) - { - _generator = generator; - } - - public AmqpClassMap getAmqpClassMap(AmqpVersion version) - { - return _versionToClassMapMap.get(version); - } - - - public AmqpVersionSet getVersionSet() - { - return _versionSet; - } - - public boolean addFromNode(Node n, int o, AmqpVersion version) - throws AmqpParseException, AmqpTypeMappingException - { - _versionSet.add(version); - NodeList nList = n.getChildNodes(); - - AmqpClassMap versionSpecificClassMap = _versionToClassMapMap.get(version); - - if (versionSpecificClassMap == null) - { - versionSpecificClassMap = new AmqpClassMap(); - _versionToClassMapMap.put(version, versionSpecificClassMap); - } - - int eCntr = 0; - for (int i = 0; i < nList.getLength(); i++) - { - Node c = nList.item(i); - if (c.getNodeName().compareTo(Utils.ELEMENT_CLASS) == 0) - { - String className = _generator.prepareClassName(Utils.getNamedAttribute(c, Utils.ATTRIBUTE_NAME)); - AmqpClass thisClass = classMap.get(className); - if (thisClass == null) - { - thisClass = new AmqpClass(className, _generator); - classMap.put(className, thisClass); - } - - AmqpClass versionSpecificClass = new AmqpClass(className, _generator); - versionSpecificClassMap.put(className, versionSpecificClass); - - versionSpecificClass.addFromNode(c, eCntr, version); - - if (!thisClass.addFromNode(c, eCntr++, version)) - { - System.out.println("INFO: Generation supression tag found for class " + className + " - removing."); - thisClass.removeVersion(version); - classMap.remove(className); - } - } - } - return true; - } - - public void print(PrintStream out, int marginSize, int tabSize) - { - out.println(Utils.createSpaces(marginSize) + - "[C]=class; [M]=method; [F]=field; [D]=domain; [I]=index; [O]=ordinal" + Utils.LINE_SEPARATOR); - out.println(Utils.createSpaces(marginSize) + "Model:"); - - for (String thisClassName : classMap.keySet()) - { - AmqpClass thisClass = classMap.get(thisClassName); - thisClass.print(out, marginSize + tabSize, tabSize); - } - } - - public LanguageConverter getGenerator() - { - return _generator; - } - - public AmqpClassMap getClassMap() - { - return classMap; - } - - - public Collection<AmqpClass> getClasses() - { - return classMap.values(); - } - - public SingleVersionModel asSingleVersionModel() - { - return new SingleVersionModel(this, getVersionSet().first(), _generator); - } -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpOrdinalFieldMap.java b/gentools/src/org/apache/qpid/gentools/AmqpOrdinalFieldMap.java deleted file mode 100644 index 0633eff1e1..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpOrdinalFieldMap.java +++ /dev/null @@ -1,96 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.util.Iterator; -import java.util.Set; -import java.util.TreeMap; - -@SuppressWarnings("serial") -public class AmqpOrdinalFieldMap extends TreeMap<Integer, String[]> implements Comparable -{ - - - public int compareTo(Object obj) - { - AmqpOrdinalFieldMap o = (AmqpOrdinalFieldMap) obj; - Set<Integer> thisKeySet = keySet(); - Set<Integer> oKeySet = o.keySet(); - if (!thisKeySet.equals(oKeySet)) // Not equal, but why? - { - // Size difference - int sizeDiff = thisKeySet.size() - oKeySet.size(); // -ve if this < other - if (sizeDiff != 0) - { - return sizeDiff; - } - // Conetent difference - Iterator<Integer> itr = thisKeySet.iterator(); - Iterator<Integer> oItr = oKeySet.iterator(); - while (itr.hasNext() && oItr.hasNext()) - { - int diff = itr.next() - oItr.next(); // -ve if this < other - if (diff != 0) - { - return diff; - } - } - // We should never get here... - System.err.println("AmqpOrdinalFieldMap.compareTo(): " + - "WARNING - unable to find cause of keySet difference."); - } - // Keys are equal, now check the String[]s - Iterator<Integer> itr = thisKeySet.iterator(); - Iterator<Integer> oItr = oKeySet.iterator(); - while (itr.hasNext() && oItr.hasNext()) - { - String[] thisPair = get(itr.next()); - String[] oPair = o.get(oItr.next()); - // Size difference - int sizeDiff = thisPair.length - oPair.length; // -ve if this < other - if (sizeDiff != 0) - { - return sizeDiff; - } - // Conetent difference - for (int i = 0; i < thisPair.length; i++) - { - int diff = thisPair[i].compareTo(oPair[i]); - if (diff != 0) - { - return diff; - } - } - } - return 0; - } - - public String toString() - { - StringBuffer sb = new StringBuffer(); - for (Integer thisOrdinal : keySet()) - { - String[] pair = get(thisOrdinal); - sb.append("[" + thisOrdinal + "] " + pair[0] + " : " + pair[1] + Utils.LINE_SEPARATOR); - } - return sb.toString(); - } -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpOrdinalVersionMap.java b/gentools/src/org/apache/qpid/gentools/AmqpOrdinalVersionMap.java deleted file mode 100644 index fede88631a..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpOrdinalVersionMap.java +++ /dev/null @@ -1,76 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.util.ArrayList; -import java.util.TreeMap; - -@SuppressWarnings("serial") -public class AmqpOrdinalVersionMap extends TreeMap<Integer, AmqpVersionSet> implements VersionConsistencyCheck -{ - public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) - { - if (size() != 1) - { - return false; - } - return get(firstKey()).equals(globalVersionSet); - } - - public int getOrdinal(AmqpVersion version) - throws AmqpTypeMappingException - { - for (Integer thisOrdinal : keySet()) - { - AmqpVersionSet versionSet = get(thisOrdinal); - if (versionSet.contains(version)) - { - return thisOrdinal; - } - } - throw new AmqpTypeMappingException("Unable to locate version " + version + " in ordianl version map."); - } - - public boolean removeVersion(AmqpVersion version) - { - Boolean res = false; - ArrayList<Integer> removeList = new ArrayList<Integer>(); - for (Integer ordinal : keySet()) - { - AmqpVersionSet versionSet = get(ordinal); - if (versionSet.contains(version)) - { - versionSet.remove(version); - if (versionSet.isEmpty()) - { - removeList.add(ordinal); - } - res = true; - } - } - // Get rid of ordinals no longer in use - for (Integer ordinal : removeList) - { - remove(ordinal); - } - return res; - } -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpOverloadedParameterMap.java b/gentools/src/org/apache/qpid/gentools/AmqpOverloadedParameterMap.java deleted file mode 100644 index 10978d0e4a..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpOverloadedParameterMap.java +++ /dev/null @@ -1,29 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.util.TreeMap; - -@SuppressWarnings("serial") -public class AmqpOverloadedParameterMap extends TreeMap<AmqpOrdinalFieldMap, AmqpVersionSet> -{ - -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpParseException.java b/gentools/src/org/apache/qpid/gentools/AmqpParseException.java deleted file mode 100644 index 3f3d4611fc..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpParseException.java +++ /dev/null @@ -1,30 +0,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. - * - */ -package org.apache.qpid.gentools; - -@SuppressWarnings("serial") -public class AmqpParseException extends RuntimeException -{ - public AmqpParseException(String msg) - { - super(msg); - } -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpTemplateException.java b/gentools/src/org/apache/qpid/gentools/AmqpTemplateException.java deleted file mode 100644 index 1ac09ea453..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpTemplateException.java +++ /dev/null @@ -1,30 +0,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. - * - */ -package org.apache.qpid.gentools; - -@SuppressWarnings("serial") -public class AmqpTemplateException extends RuntimeException -{ - public AmqpTemplateException(String msg) - { - super(msg); - } -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpTypeMappingException.java b/gentools/src/org/apache/qpid/gentools/AmqpTypeMappingException.java deleted file mode 100644 index 127a8835b0..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpTypeMappingException.java +++ /dev/null @@ -1,30 +0,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. - * - */ -package org.apache.qpid.gentools; - -@SuppressWarnings("serial") -public class AmqpTypeMappingException extends RuntimeException -{ - public AmqpTypeMappingException(String msg) - { - super(msg); - } -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpVersion.java b/gentools/src/org/apache/qpid/gentools/AmqpVersion.java deleted file mode 100644 index dbeef1b895..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpVersion.java +++ /dev/null @@ -1,72 +0,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. - * - */ -package org.apache.qpid.gentools; - -public class AmqpVersion implements Comparable<AmqpVersion> -{ - private final int _major; - private final int _minor; - - public AmqpVersion(int major, int minor) - { - _major = major; - _minor = minor; - } - - public AmqpVersion(AmqpVersion version) - { - _major = version.getMajor(); - _minor = version.getMinor(); - } - - public int getMajor() - { - return _major; - } - - public int getMinor() - { - return _minor; - } - - public int compareTo(AmqpVersion v) - { - if (_major != v.getMajor()) - { - return _major - v.getMajor(); - } - if (_minor != v.getMinor()) - { - return _minor - v.getMinor(); - } - return 0; - } - - public String namespace() - { - return "ver_" + _major + "_" + _minor; - } - - public String toString() - { - return _major + "-" + _minor; - } -} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpVersionSet.java b/gentools/src/org/apache/qpid/gentools/AmqpVersionSet.java deleted file mode 100644 index 6419e23a1e..0000000000 --- a/gentools/src/org/apache/qpid/gentools/AmqpVersionSet.java +++ /dev/null @@ -1,79 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.io.PrintStream; -import java.util.Iterator; -import java.util.TreeSet; - -@SuppressWarnings("serial") -public class AmqpVersionSet extends TreeSet<AmqpVersion> implements Printable, Comparable<AmqpVersionSet> -{ - public AmqpVersionSet() - { - super(); - } - - public AmqpVersionSet(AmqpVersion version) - { - super(); - add(version); - } - - public AmqpVersion find(AmqpVersion version) - { - for (AmqpVersion v : this) - { - if (v.compareTo(version) == 0) - { - return v; - } - } - return null; - } - - public void print(PrintStream out, int marginSize, int tabSize) - { - out.print(Utils.createSpaces(marginSize) + "Version Set: " + toString() + Utils.LINE_SEPARATOR); - } - - public int compareTo(AmqpVersionSet other) - { - int res = size() - other.size(); - if (res != 0) - { - return res; - } - Iterator<AmqpVersion> vItr = iterator(); - Iterator<AmqpVersion> oItr = other.iterator(); - while (vItr.hasNext() && oItr.hasNext()) - { - AmqpVersion version = vItr.next(); - AmqpVersion oVersion = oItr.next(); - res = version.compareTo(oVersion); - if (res != 0) - { - return res; - } - } - return 0; - } -} diff --git a/gentools/src/org/apache/qpid/gentools/BitFieldGenerateMethod.java b/gentools/src/org/apache/qpid/gentools/BitFieldGenerateMethod.java deleted file mode 100644 index d85510ee98..0000000000 --- a/gentools/src/org/apache/qpid/gentools/BitFieldGenerateMethod.java +++ /dev/null @@ -1,29 +0,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. - * - */ -package org.apache.qpid.gentools; - - -import java.util.List; - -public interface BitFieldGenerateMethod -{ - String generate(List<String> bitFieldList, int ordinal, int indentSize, int tabSize); -} diff --git a/gentools/src/org/apache/qpid/gentools/CommandGenerateMethod.java b/gentools/src/org/apache/qpid/gentools/CommandGenerateMethod.java deleted file mode 100644 index 641f50c3f8..0000000000 --- a/gentools/src/org/apache/qpid/gentools/CommandGenerateMethod.java +++ /dev/null @@ -1,26 +0,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. - * - */ -package org.apache.qpid.gentools; - -public interface CommandGenerateMethod -{ - String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast); -} diff --git a/gentools/src/org/apache/qpid/gentools/ConsolidatedField.java b/gentools/src/org/apache/qpid/gentools/ConsolidatedField.java deleted file mode 100644 index 9ab7eb178b..0000000000 --- a/gentools/src/org/apache/qpid/gentools/ConsolidatedField.java +++ /dev/null @@ -1,120 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.util.List; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; - -/** - * Created by IntelliJ IDEA. - * User: U146758 - * Date: 06-Mar-2007 - * Time: 09:22:21 - * To change this template use File | Settings | File Templates. - */ -public class ConsolidatedField -{ - private final String _name; - private final String _type; - private final List<String> _underlyingFields = new ArrayList<String>(); - private final Generator _generator; - private boolean _isConsolidated; - - public ConsolidatedField(Generator generator, String name, String type) - { - this(generator,name,type,name,false); - } - - public ConsolidatedField(Generator generator, String name, String type, String firstField) - { - this(generator,name,type,firstField,true); - } - - public ConsolidatedField(Generator generator, String name, String type, String firstField, boolean consolidated) - { - - _generator = generator; - _name = name; - _type = type; - _isConsolidated = consolidated; - _underlyingFields.add(firstField); - - } - - - public void setConsolidated(boolean consolidated) - { - _isConsolidated = consolidated; - } - - public String getName() - { - return _name; - } - - public String getType() - { - return _type; - } - - public String getNativeType() - { - return _generator.getNativeType(_type); - } - - public String getEncodingType() - { - return _generator.getEncodingType(_type); - } - - public void add(String name) - { - _underlyingFields.add(name); - } - - public Collection<String> getUnderlyingFields() - { - return Collections.unmodifiableCollection(_underlyingFields); - } - - public int getPosition(String fieldName) - { - return _underlyingFields.indexOf(fieldName); - } - - public boolean isConsolidated() - { - return _isConsolidated; - } - - public boolean isFixedSize() - { - return _generator.isFixedSizeType( getType() ); - } - - public int getSize() - { - return _generator.getTypeSize( getType() ); - } - -} diff --git a/gentools/src/org/apache/qpid/gentools/CppGenerator.java b/gentools/src/org/apache/qpid/gentools/CppGenerator.java deleted file mode 100644 index 4f58cba34e..0000000000 --- a/gentools/src/org/apache/qpid/gentools/CppGenerator.java +++ /dev/null @@ -1,1716 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.io.File; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.TreeMap; - -public class CppGenerator extends Generator -{ - protected static final String versionNamespaceStartToken = "${version_namespace_start}"; - protected static final String versionNamespaceEndToken = "${version_namespace_end}"; - - // TODO: Move this to parent class - protected static final int FIELD_NAME = 0; - protected static final int FIELD_CODE_TYPE = 1; - - /** - * A complete list of C++ reserved words. The names of varous XML elements within the AMQP - * specification file are used for C++ identifier names in the generated code. Each proposed - * name is checked against this list and is modified (by adding an '_' to the end of the - * name - see function parseForReservedWords()) if found to be present. - */ - protected static final String[] cppReservedWords = {"and", "and_eq", "asm", "auto", "bitand", - "bitor", "bool", "break", "case", "catch", "char", "class", "compl", "const", "const_cast", - "continue", "default", "delete", "do", "DomainInfo", "double", "dynamic_cast", "else", - "enum", "explicit", "extern", "false", "float", "for", "friend", "goto", "if", "inline", - "int", "long", "mutable", "namespace", "new", "not", "not_eq", "operator", "or", "or_eq", - "private", "protected", "public", "register", "reinterpret_cast", "return", "short", - "signed", "sizeof", "static", "static_cast", "struct", "switch", "template", "this", - "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned", "using", - "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq"}; - - /** - * Although not reserved words, the following list of variable names that may cause compile - * problems within a C++ environment because they clash with common #includes. The names of - * varous XML elements within the AMQP specification file are used for C++ identifier names - * in the generated code. Each proposed name is checked against this list and is modified - * (by adding an '_' to the end of the name - see function parseForReservedWords()) if found - * to be present. This list is best added to on an as-needed basis. - */ - protected static final String[] cppCommonDefines = {"string"}; - - // TODO: Move this to the Generator superclass? - protected boolean quietFlag; // Supress warning messages to the console - - private class DomainInfo - { - public String type; - public String size; - public String encodeExpression; - public String decodeExpression; - - public DomainInfo(String domain, String size, String encodeExpression, - String decodeExpression) - { - this.type = domain; - this.size = size; - this.encodeExpression = encodeExpression; - this.decodeExpression = decodeExpression; - } - } - - private static TreeMap<String, DomainInfo> typeMap = new TreeMap<String, DomainInfo>(); - - public CppGenerator() - { - super(); - quietFlag = true; - // Load C++ type and size maps. - // Adjust or add to these lists as new types are added/defined. - // The char '#' will be replaced by the field variable name (any type). - // The char '~' will be replaced by the compacted bit array size (type bit only). - typeMap.put("bit", new DomainInfo( - "bool", // type - "~", // size - "", // encodeExpression - "")); // decodeExpression - typeMap.put("content", new DomainInfo( - "Content", // type - "#.size()", // size - "buffer.putContent(#)", // encodeExpression - "buffer.getContent(#)")); // decodeExpression - typeMap.put("long", new DomainInfo( - "u_int32_t", // type - "4", // size - "buffer.putLong(#)", // encodeExpression - "# = buffer.getLong()")); // decodeExpression - typeMap.put("longlong", new DomainInfo( - "u_int64_t", // type - "8", // size - "buffer.putLongLong(#)", // encodeExpression - "# = buffer.getLongLong()")); // decodeExpression - typeMap.put("longstr", new DomainInfo( - "string", // type - "4 + #.length()", // size - "buffer.putLongString(#)", // encodeExpression - "buffer.getLongString(#)")); // decodeExpression - typeMap.put("octet", new DomainInfo( - "u_int8_t", // type - "1", // size - "buffer.putOctet(#)", // encodeExpression - "# = buffer.getOctet()")); // decodeExpression - typeMap.put("short", new DomainInfo( - "u_int16_t", // type - "2", // size - "buffer.putShort(#)", // encodeExpression - "# = buffer.getShort()")); // decodeExpression - typeMap.put("shortstr", new DomainInfo( - "string", // type - "1 + #.length()", // size - "buffer.putShortString(#)", // encodeExpression - "buffer.getShortString(#)")); // decodeExpression - typeMap.put("table", new DomainInfo( - "FieldTable", // type - "#.size()", // size - "buffer.putFieldTable(#)", // encodeExpression - "buffer.getFieldTable(#)")); // decodeExpression - typeMap.put("timestamp", new DomainInfo( - "u_int64_t", // type - "8", // size - "buffer.putLongLong(#)", // encodeExpression - "buffer.getLongLong(#)")); // decodeExpression - } - - - public boolean isQuietFlag() - { - return quietFlag; - } - - public void setQuietFlag(boolean quietFlag) - { - this.quietFlag = quietFlag; - } - - // === Start of methods for Interface LanguageConverter === - - public String prepareClassName(String className) - { - return camelCaseName(className, true); - } - - public String prepareMethodName(String methodName) - { - return camelCaseName(methodName, false); - } - - public String prepareDomainName(String domainName) - { - return camelCaseName(domainName, false); - } - - - public String getGeneratedType(String domainName, AmqpVersion version) - throws AmqpTypeMappingException - { - String domainType = getDomainType(domainName, version); - if (domainType == null) - { - throw new AmqpTypeMappingException("Domain type \"" + domainName + - "\" not found in C++ typemap."); - } - DomainInfo info = typeMap.get(domainType); - if (info == null) - { - throw new AmqpTypeMappingException("Unknown domain: \"" + domainType + "\""); - } - return info.type; - } - - // === Abstract methods from class Generator - C++-specific implementation === - - @Override - protected String prepareFilename(String filenameTemplate, AmqpClass thisClass, AmqpMethod method, - AmqpField field, AmqpVersion version) - { - StringBuffer sb = new StringBuffer(filenameTemplate); - if (thisClass != null) - { - replaceToken(sb, "${CLASS}", thisClass.getName()); - } - if (method != null) - { - replaceToken(sb, "${METHOD}", method.getName()); - } - if (field != null) - { - replaceToken(sb, "${FIELD}", field.getName()); - } - return sb.toString(); - } - - @Override - protected void processModelTemplate(NamedTemplate template) - { - processTemplate(template, null, null, null, null); - } - - @Override - protected void processClassTemplate(NamedTemplate template, AmqpClass thisClass) - { - processTemplate(template, thisClass, null, null, null); - } - - @Override - protected void processMethodTemplate(NamedTemplate template, AmqpClass thisClass, - AmqpMethod method) - { - StringBuffer sb = new StringBuffer(template.getTemplate()); - String filename = prepareFilename(getTemplateFileName(sb), thisClass, method, null, null); - boolean templateProcessedFlag = false; - - // If method is not version consistent, create a namespace for each version - // i.e. copy the bit between the versionNamespaceStartToken and versionNamespaceEndToken - // once for each namespace. - if (method != null) - { - if (!method.isVersionConsistent(getVersionSet())) - { - int namespaceStartIndex = sb.indexOf(versionNamespaceStartToken); - int namespaceEndIndex = sb.indexOf(versionNamespaceEndToken) + - versionNamespaceEndToken.length(); - if (namespaceStartIndex >= 0 && namespaceEndIndex >= 0 && - namespaceStartIndex <= namespaceEndIndex) - { - String namespaceSpan = sb.substring(namespaceStartIndex, namespaceEndIndex) + CR; - sb.delete(namespaceStartIndex, namespaceEndIndex); - for (AmqpVersion v : method.getVersionSet()) - { - StringBuffer nssb = new StringBuffer(namespaceSpan); - processTemplate(nssb, thisClass, method, null, template.getName(), v); - sb.insert(namespaceStartIndex, nssb); - } - // Process all tokens *not* within the namespace span prior to inserting namespaces - processTemplate(sb, thisClass, method, null, template.getName(), null); - } - templateProcessedFlag = true; - } - } - // Remove any remaining namespace tags - int nsTokenIndex = sb.indexOf(versionNamespaceStartToken); - while (nsTokenIndex > 0) - { - sb.delete(nsTokenIndex, nsTokenIndex + versionNamespaceStartToken.length()); - nsTokenIndex = sb.indexOf(versionNamespaceStartToken); - } - nsTokenIndex = sb.indexOf(versionNamespaceEndToken); - while (nsTokenIndex > 0) - { - sb.delete(nsTokenIndex, nsTokenIndex + versionNamespaceEndToken.length()); - nsTokenIndex = sb.indexOf(versionNamespaceEndToken); - } - - if (!templateProcessedFlag) - { - processTemplate(sb, thisClass, method, null, template.getName(), null); - } - writeTargetFile(sb, new File(getOutputDirectory() + Utils.FILE_SEPARATOR + filename)); - generatedFileCounter++; - } - - @Override - protected void processTemplate(NamedTemplate template, AmqpClass thisClass, AmqpMethod method, - AmqpField field, AmqpVersion version) - { - StringBuffer sb = new StringBuffer(template.getTemplate()); - String filename = prepareFilename(getTemplateFileName(sb), thisClass, method, field, version); - processTemplate(sb, thisClass, method, field, template.getName(), null); - writeTargetFile(sb, new File(getOutputDirectory() + Utils.FILE_SEPARATOR + filename)); - generatedFileCounter++; - } - - protected void processTemplate(StringBuffer sb, AmqpClass thisClass, AmqpMethod method, - AmqpField field, String templateFileName, AmqpVersion version) - { - try - { - processAllLists(sb, thisClass, method, version); - } - catch (AmqpTemplateException e) - { - System.out.println("ERROR: " + templateFileName + ": " + e.getMessage()); - } - try - { - processAllTokens(sb, thisClass, method, field, version); - } - catch (AmqpTemplateException e) - { - System.out.println("ERROR: " + templateFileName + ": " + e.getMessage()); - } - } - - @Override - protected String processToken(String token, AmqpClass thisClass, AmqpMethod method, AmqpField field, - AmqpVersion version) - { - if (token.compareTo("${GENERATOR}") == 0) - { - return GENERATOR_INFO; - } - if (token.compareTo("${CLASS}") == 0 && thisClass != null) - { - return thisClass.getName(); - } - if (token.compareTo("${CLASS_ID_INIT}") == 0 && thisClass != null) - { - if (version == null) - { - return String.valueOf(thisClass.getIndexMap().firstKey()); - } - return getIndex(thisClass.getIndexMap(), version); - } - if (token.compareTo("${METHOD}") == 0 && method != null) - { - return method.getName(); - } - if (token.compareTo("${METHOD_ID_INIT}") == 0 && method != null) - { - if (version == null) - { - return String.valueOf(method.getIndexMap().firstKey()); - } - return getIndex(method.getIndexMap(), version); - } - if (token.compareTo("${FIELD}") == 0 && field != null) - { - return field.getName(); - } - if (token.compareTo(versionNamespaceStartToken) == 0 && version != null) - { - return "namespace " + version.namespace() + CR + "{"; - } - if (token.compareTo(versionNamespaceEndToken) == 0 && version != null) - { - return "} // namespace " + version.namespace(); - } - if (token.compareTo("${mb_constructor_with_initializers}") == 0) - { - return generateConstructor(thisClass, method, version, 4, 4); - } - if (token.compareTo("${mb_server_operation_invoke}") == 0) - { - return generateServerOperationsInvoke(thisClass, method, version, 4, 4); - } - if (token.compareTo("${mb_buffer_param}") == 0) - { - return method.getFieldMap().size() > 0 ? " buffer" : ""; - } - if (token.compareTo("${hv_latest_major}") == 0) - { - return String.valueOf(getVersionSet().last().getMajor()); - } - if (token.compareTo("${hv_latest_minor}") == 0) - { - return String.valueOf(getVersionSet().last().getMinor()); - } - - throw new AmqpTemplateException("Template token " + token + " unknown."); - } - - @Override - protected void processClassList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, - AmqpModel model, AmqpVersion version) - { - String codeSnippet; - int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line - String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr - int tokxStart = tline.indexOf('$'); - String token = tline.substring(tokxStart).trim(); - sb.delete(listMarkerStartIndex, lend); - - // ClientOperations.h - if (token.compareTo("${coh_method_handler_get_method}") == 0) - { - codeSnippet = generateOpsMethodHandlerGetMethods(model, false, 4); - } - else if (token.compareTo("${coh_inner_class}") == 0) - { - codeSnippet = generateOpsInnerClasses(model, false, 4, 4); - } - - // ServerOperations.h - else if (token.compareTo("${soh_method_handler_get_method}") == 0) - { - codeSnippet = generateOpsMethodHandlerGetMethods(model, true, 4); - } - else if (token.compareTo("${soh_inner_class}") == 0) - { - codeSnippet = generateOpsInnerClasses(model, true, 4, 4); - } - - // ClientProxy.h/cpp - else if (token.compareTo("${cph_inner_class_instance}") == 0) - { - codeSnippet = generateProxyInnerClassInstances(model, false, 4); - } - else if (token.compareTo("${cph_inner_class_get_method}") == 0) - { - codeSnippet = generateProxyInnerClassGetMethodDecls(model, false, 4); - } - else if (token.compareTo("${cph_inner_class_defn}") == 0) - { - codeSnippet = generateProxyInnerClassDefinitions(model, false, 4, 4); - } - else if (token.compareTo("${cpc_constructor_initializer}") == 0) - { - codeSnippet = generateProxyConstructorInitializers(model, false, 4); - } - else if (token.compareTo("${cpc_inner_class_get_method}") == 0) - { - codeSnippet = generateProxyInnerClassGetMethodImpls(model, false, 0, 4); - } - else if (token.compareTo("${cpc_inner_class_impl}") == 0) - { - codeSnippet = generateProxyInnerClassImpl(model, false, 0, 4); - } - else if (token.compareTo("${cph_handler_pointer_defn}") == 0) - { - codeSnippet = generateHandlerPointerDefinitions(model, false, 4); - } - else if (token.compareTo("${cph_handler_pointer_get_method}") == 0) - { - codeSnippet = generateHandlerPointerGetMethods(model, false, 4); - } - - // SerrverProxy.h/cpp - else if (token.compareTo("${sph_inner_class_instance}") == 0) - { - codeSnippet = generateProxyInnerClassInstances(model, true, 4); - } - else if (token.compareTo("${sph_inner_class_get_method}") == 0) - { - codeSnippet = generateProxyInnerClassGetMethodDecls(model, true, 4); - } - else if (token.compareTo("${sph_inner_class_defn}") == 0) - { - codeSnippet = generateProxyInnerClassDefinitions(model, true, 4, 4); - } - else if (token.compareTo("${spc_constructor_initializer}") == 0) - { - codeSnippet = generateProxyConstructorInitializers(model, true, 4); - } - else if (token.compareTo("${spc_inner_class_get_method}") == 0) - { - codeSnippet = generateProxyInnerClassGetMethodImpls(model, true, 0, 4); - } - else if (token.compareTo("${spc_inner_class_impl}") == 0) - { - codeSnippet = generateProxyInnerClassImpl(model, true, 0, 4); - } - else if (token.compareTo("${sph_handler_pointer_defn}") == 0) - { - codeSnippet = generateHandlerPointerDefinitions(model, true, 4); - } - else if (token.compareTo("${sph_handler_pointer_get_method}") == 0) - { - codeSnippet = generateHandlerPointerGetMethods(model, true, 4); - } - - // amqp_methods.h/cpp - else if (token.compareTo("${mh_method_body_class_indlude}") == 0) - { - codeSnippet = generateMethodBodyIncludeList(model, 0); - } - else if (token.compareTo("${mh_method_body_class_instance}") == 0) - { - codeSnippet = generateMethodBodyInstances(model, 0); - } - else if (token.compareTo("${mc_create_method_body_map_entry}") == 0) - { - codeSnippet = generateMethodBodyMapEntry(model, 4); - } - - else // Oops! - { - throw new AmqpTemplateException("Template token \"" + token + "\" unknown."); - } - sb.insert(listMarkerStartIndex, codeSnippet); - } - - @Override - protected void processMethodList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, - AmqpClass thisClass) - { - String codeSnippet; - int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line - String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr - int tokxStart = tline.indexOf('$'); - String token = tline.substring(tokxStart).trim(); - sb.delete(listMarkerStartIndex, lend); - - if (token.compareTo("${cpc_method_body_include}") == 0) - { - codeSnippet = generateMethodBodyIncludes(thisClass, 0); - } - else if (token.compareTo("${spc_method_body_include}") == 0) - { - codeSnippet = generateMethodBodyIncludes(thisClass, 0); - } - else if (token.compareTo("${mc_method_body_include}") == 0) - { - codeSnippet = generateMethodBodyIncludes(thisClass, 0); - } - - else // Oops! - { - throw new AmqpTemplateException("Template token " + token + " unknown."); - } - sb.insert(listMarkerStartIndex, codeSnippet); - } - - @Override - protected void processFieldList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, - AmqpFieldMap fieldMap, AmqpVersion version) - { - String codeSnippet; - int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line - String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr - int tokxStart = tline.indexOf('$'); - String token = tline.substring(tokxStart).trim(); - sb.delete(listMarkerStartIndex, lend); - - if (token.compareTo("${mb_field_declaration}") == 0) - { - codeSnippet = generateFieldDeclarations(fieldMap, version, 4); - } - else if (token.compareTo("${mb_field_get_method}") == 0) - { - codeSnippet = generateFieldGetMethods(fieldMap, version, 4); - } - else if (token.compareTo("${mb_field_print}") == 0) - { - codeSnippet = generatePrintMethodContents(fieldMap, version, 8); - } - else if (token.compareTo("${mb_body_size}") == 0) - { - codeSnippet = generateBodySizeMethodContents(fieldMap, version, 8); - } - else if (token.compareTo("${mb_encode}") == 0) - { - codeSnippet = generateEncodeMethodContents(fieldMap, version, 8); - } - else if (token.compareTo("${mb_decode}") == 0) - { - codeSnippet = generateDecodeMethodContents(fieldMap, version, 8); - } - - else // Oops! - { - throw new AmqpTemplateException("Template token " + token + " unknown."); - } - sb.insert(listMarkerStartIndex, codeSnippet); - } - - @Override - protected void processConstantList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, - AmqpConstantSet constantSet) - { - String codeSnippet; - int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line - String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr - int tokxStart = tline.indexOf('$'); - String token = tline.substring(tokxStart).trim(); - sb.delete(listMarkerStartIndex, lend); - - if (token.compareTo("${ch_get_value_method}") == 0) - { - codeSnippet = generateConstantGetMethods(constantSet, 4, 4); - } - - else // Oops! - { - throw new AmqpTemplateException("Template token " + token + " unknown."); - } - sb.insert(listMarkerStartIndex, codeSnippet); - } - - // === Protected and private helper functions unique to C++ implementation === - - // Methods for generation of code snippets for AMQP_Constants.h file - - protected String generateConstantGetMethods(AmqpConstantSet constantSet, - int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - for (AmqpConstant thisConstant : constantSet.getContstants()) - { - if (thisConstant.isVersionConsistent(getVersionSet())) - { - // return a constant - String value = thisConstant.firstKey(); - sb.append(indent + "static const char* " + thisConstant.getName() + "() { return \"" + - thisConstant.firstKey() + "\"; }" + CR); - if (Utils.containsOnlyDigits(value)) - { - sb.append(indent + "static int " + thisConstant.getName() + "AsInt() { return " + - thisConstant.firstKey() + "; }" + CR); - } - if (Utils.containsOnlyDigitsAndDecimal(value)) - { - sb.append(indent + "static double " + thisConstant.getName() + "AsDouble() { return (double)" + - thisConstant.firstKey() + "; }" + CR); - } - sb.append(CR); - } - else - { - // Return version-specific constant - sb.append(generateVersionDependentGet(thisConstant, "const char*", "", "\"", "\"", indentSize, tabSize)); - sb.append(generateVersionDependentGet(thisConstant, "int", "AsInt", "", "", indentSize, tabSize)); - sb.append(generateVersionDependentGet(thisConstant, "double", "AsDouble", "(double)", "", indentSize, tabSize)); - sb.append(CR); - } - } - return sb.toString(); - } - - protected String generateVersionDependentGet(AmqpConstant constant, String methodReturnType, - String methodNameSuffix, String returnPrefix, String returnPostfix, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - sb.append(indent + methodReturnType + " " + constant.getName() + methodNameSuffix + - "() const" + CR); - sb.append(indent + "{" + CR); - boolean first = true; - for (String thisValue : constant.keySet()) - { - AmqpVersionSet versionSet = constant.get(thisValue); - sb.append(indent + tab + (first ? "" : "else ") + "if (" + generateVersionCheck(versionSet) + - ")" + CR); - sb.append(indent + tab + "{" + CR); - if (methodReturnType.compareTo("int") == 0 && !Utils.containsOnlyDigits(thisValue)) - { - sb.append(generateConstantDeclarationException(constant.getName(), methodReturnType, - indentSize + (2 * tabSize), tabSize)); - } - else if (methodReturnType.compareTo("double") == 0 && !Utils.containsOnlyDigitsAndDecimal(thisValue)) - { - sb.append(generateConstantDeclarationException(constant.getName(), methodReturnType, - indentSize + (2 * tabSize), tabSize)); - } - else - { - sb.append(indent + tab + tab + "return " + returnPrefix + thisValue + returnPostfix + ";" + CR); - } - sb.append(indent + tab + "}" + CR); - first = false; - } - sb.append(indent + tab + "else" + CR); - sb.append(indent + tab + "{" + CR); - sb.append(indent + tab + tab + "std::stringstream ss;" + CR); - sb.append(indent + tab + tab + "ss << \"Constant \\\"" + constant.getName() + - "\\\" is undefined for AMQP version \" <<" + CR); - sb.append(indent + tab + tab + tab + "version.toString() << \".\";" + CR); - sb.append(indent + tab + tab + "throw ProtocolVersionException(ss.str());" + CR); - sb.append(indent + tab + "}" + CR); - sb.append(indent + "}" + CR); - return sb.toString(); - } - - protected String generateConstantDeclarationException(String name, String methodReturnType, - int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - sb.append(indent + "std::stringstream ss;" + CR); - sb.append(indent + "ss << \"Constant \\\"" + name + "\\\" cannot be converted to type " + - methodReturnType + " for AMQP version \" <<" + CR); - sb.append(indent + tab + "version.toString() << \".\";" + CR); - sb.append(indent + "throw ProtocolVersionException(ss.str());" + CR); - return sb.toString(); - } - - // Methods used for generation of code snippets for Server/ClientOperations class generation - - protected String generateOpsMethodHandlerGetMethods(AmqpModel model, boolean serverFlag, int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - for (String thisClassName : model.getClassMap().keySet()) - { - AmqpClass thisClass = model.getClassMap().get(thisClassName); - // Only generate for this class if there is at least one method of the - // required chassis (server/client flag). - boolean chassisFoundFlag = false; - for (String thisMethodName : thisClass.getMethodMap().keySet()) - { - AmqpMethod method = thisClass.getMethodMap().get(thisMethodName); - boolean clientChassisFlag = method.getClientMethodFlagMap().isSet(); - boolean serverChassisFlag = method.getServerMethodFlagMap().isSet(); - if ((serverFlag && serverChassisFlag) || (!serverFlag && clientChassisFlag)) - { - chassisFoundFlag = true; - } - } - if (chassisFoundFlag) - { - sb.append(indent + "virtual AMQP_" + (serverFlag ? "Server" : "Client") + "Operations::" + - thisClass.getName() + "Handler* get" + thisClass.getName() + "Handler() = 0;" + CR); - } - } - return sb.toString(); - } - - protected String generateOpsInnerClasses(AmqpModel model, boolean serverFlag, int indentSize, int tabSize) - { - - String proxyClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - boolean first = true; - for (String thisClassName : model.getClassMap().keySet()) - { - AmqpClass thisClass = model.getClassMap().get(thisClassName); - String handlerClassName = thisClass.getName() + "Handler"; - if (!first) - { - sb.append(CR); - } - sb.append(indent + "// ==================== class " + handlerClassName + - " ====================" + CR); - sb.append(indent + "class " + handlerClassName); - if (thisClass.getVersionSet().size() != getVersionSet().size()) - { - sb.append(" // AMQP Version(s) " + thisClass.getVersionSet() + CR); - } - else - { - sb.append(CR); - } - sb.append(indent + "{" + CR); - sb.append(indent + "private:" + CR); - sb.append(indent + tab + proxyClassName + "* parent;" + CR); - sb.append(CR); - sb.append(indent + tab + "// Constructors and destructors" + CR); - sb.append(CR); - sb.append(indent + "protected:" + CR); - sb.append(indent + tab + handlerClassName + "() {}" + CR); - sb.append(indent + "public:" + CR); - sb.append(indent + tab + handlerClassName + - "(" + proxyClassName + "* _parent) {parent = _parent;}" + CR); - sb.append(indent + tab + "virtual ~" + handlerClassName + "() {}" + CR); - sb.append(CR); - sb.append(indent + tab + "// Protocol methods" + CR); - sb.append(CR); - sb.append(generateInnerClassMethods(thisClass, serverFlag, true, indentSize + tabSize, tabSize)); - sb.append(indent + "}; // class " + handlerClassName + CR); - first = false; - } - return sb.toString(); - } - - protected String generateInnerClassMethods(AmqpClass thisClass, boolean serverFlag, - boolean abstractMethodFlag, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + (abstractMethodFlag ? "Operations" - : "Proxy"); - boolean first = true; - for (String thisMethodName : thisClass.getMethodMap().keySet()) - { - AmqpMethod method = thisClass.getMethodMap().get(thisMethodName); - boolean clientChassisFlag = method.getClientMethodFlagMap().isSet(); - boolean serverChassisFlag = method.getServerMethodFlagMap().isSet(); - if ((serverFlag && serverChassisFlag) || (!serverFlag && clientChassisFlag)) - { - String methodName = parseForReservedWords(method.getName(), outerClassName + "." + thisClass.getName()); - AmqpOverloadedParameterMap overloadededParameterMap = - method.getOverloadedParameterLists(thisClass.getVersionSet(), this); - for (AmqpOrdinalFieldMap thisFieldMap : overloadededParameterMap.keySet()) - { - AmqpVersionSet versionSet = overloadededParameterMap.get(thisFieldMap); - if (!first) - { - sb.append(CR); - } - sb.append(indent + "virtual void " + methodName + "( u_int16_t channel"); - sb.append(generateMethodParameterList(thisFieldMap, indentSize + (5 * tabSize), true, true, true)); - sb.append(" )"); - if (abstractMethodFlag) - { - sb.append(" = 0"); - } - sb.append(";"); - if (versionSet.size() != getVersionSet().size()) - { - sb.append(" // AMQP Version(s) " + versionSet); - } - sb.append(CR); - first = false; - } - } - } - return sb.toString(); - } - - // Methods used for generation of code snippets for Server/ClientProxy class generation - - protected String generateHandlerPointerDefinitions(AmqpModel model, boolean serverFlag, - int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Operations"; - for (String thisClassName : model.getClassMap().keySet()) - { - AmqpClass thisClass = model.getClassMap().get(thisClassName); - sb.append(indent + outerClassName + "::" + thisClass.getName() + "Handler* " + - thisClass.getName() + "HandlerPtr;" + CR); - } - return sb.toString(); - } - - protected String generateHandlerPointerGetMethods(AmqpModel model, boolean serverFlag, - int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Operations"; - for (String thisClassName : model.getClassMap().keySet()) - { - AmqpClass thisClass = model.getClassMap().get(thisClassName); - sb.append(indent + "virtual inline " + outerClassName + "::" + thisClass.getName() + "Handler* get" + - thisClass.getName() + "Handler() { return &" + Utils.firstLower(thisClass.getName()) + ";}" + CR); - } - return sb.toString(); - } - - protected String generateProxyInnerClassInstances(AmqpModel model, boolean serverFlag, - int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; - for (String thisClassName : model.getClassMap().keySet()) - { - AmqpClass thisClass = model.getClassMap().get(thisClassName); - String instanceName = parseForReservedWords(Utils.firstLower(thisClass.getName()), outerClassName); - String className = parseForReservedWords(thisClass.getName(), null); - sb.append(indent + className + " " + instanceName + ";"); - if (thisClass.getVersionSet().size() != getVersionSet().size()) - { - sb.append(" // AMQP Version(s) " + thisClass.getVersionSet() + CR); - } - else - { - sb.append(CR); - } - } - return sb.toString(); - } - - protected String generateProxyInnerClassGetMethodDecls(AmqpModel model, boolean serverFlag, - int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; - for (String thisClassName : model.getClassMap().keySet()) - { - AmqpClass thisClass = model.getClassMap().get(thisClassName); - String className = parseForReservedWords(thisClass.getName(), outerClassName); - sb.append(indent + className + "& get" + className + "();"); - if (thisClass.getVersionSet().size() != getVersionSet().size()) - { - sb.append(" // AMQP Version(s) " + thisClass.getVersionSet() + CR); - } - else - { - sb.append(CR); - } - } - return sb.toString(); - } - - protected String generateProxyInnerClassDefinitions(AmqpModel model, boolean serverFlag, - int indentSize, int tabSize) - { - String proxyClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - boolean first = true; - for (String thisClassName : model.getClassMap().keySet()) - { - AmqpClass thisClass = model.getClassMap().get(thisClassName); - String className = thisClass.getName(); - String superclassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Operations::" + - thisClass.getName() + "Handler"; - if (!first) - { - sb.append(CR); - } - sb.append(indent + "// ==================== class " + className + - " ====================" + CR); - sb.append(indent + "class " + className + " : virtual public " + superclassName); - if (thisClass.getVersionSet().size() != getVersionSet().size()) - { - sb.append(" // AMQP Version(s) " + thisClass.getVersionSet() + CR); - } - else - { - sb.append(CR); - } - sb.append(indent + "{" + CR); - sb.append(indent + "private:" + CR); - sb.append(indent + tab + "OutputHandler* out;" + CR); - sb.append(indent + tab + proxyClassName + "* parent;" + CR); - sb.append(CR); - sb.append(indent + "public:" + CR); - sb.append(indent + tab + "// Constructors and destructors" + CR); - sb.append(CR); - sb.append(indent + tab + className + "(OutputHandler* out, " + proxyClassName + "* _parent) : " + CR); - sb.append(indent + tab + tab + "out(out) {parent = _parent;}" + CR); - sb.append(indent + tab + "virtual ~" + className + "() {}" + CR); - sb.append(CR); - sb.append(indent + tab + "// Protocol methods" + CR); - sb.append(CR); - sb.append(generateInnerClassMethods(thisClass, serverFlag, false, indentSize + tabSize, tabSize)); - sb.append(indent + "}; // class " + className + CR); - first = false; - } - return sb.toString(); - } - - protected String generateProxyConstructorInitializers(AmqpModel model, boolean serverFlag, - int indentSize) - { - String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; - String superclassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Operations"; - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(indent + superclassName + "(major, minor)," + CR); - sb.append(indent + "version(major, minor)," + CR); - sb.append(indent + "out(out)"); - Iterator<String> cItr = model.getClassMap().keySet().iterator(); - while (cItr.hasNext()) - { - AmqpClass thisClass = model.getClassMap().get(cItr.next()); - String instanceName = parseForReservedWords(Utils.firstLower(thisClass.getName()), outerClassName); - sb.append("," + CR); - sb.append(indent + instanceName + "(out, this)"); - if (!cItr.hasNext()) - { - sb.append(CR); - } - } - return sb.toString(); - } - - protected String generateProxyInnerClassGetMethodImpls(AmqpModel model, boolean serverFlag, - int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; - Iterator<String> cItr = model.getClassMap().keySet().iterator(); - while (cItr.hasNext()) - { - AmqpClass thisClass = model.getClassMap().get(cItr.next()); - String className = thisClass.getName(); - String instanceName = parseForReservedWords(Utils.firstLower(thisClass.getName()), outerClassName); - sb.append(indent + outerClassName + "::" + className + "& " + - outerClassName + "::get" + className + "()" + CR); - sb.append(indent + "{" + CR); - if (thisClass.getVersionSet().size() != getVersionSet().size()) - { - sb.append(indent + tab + "if (!" + generateVersionCheck(thisClass.getVersionSet()) + ")" + CR); - sb.append(indent + tab + tab + "throw new ProtocolVersionException();" + CR); - } - sb.append(indent + tab + "return " + instanceName + ";" + CR); - sb.append(indent + "}" + CR); - if (cItr.hasNext()) - { - sb.append(CR); - } - } - return sb.toString(); - } - - protected String generateProxyInnerClassImpl(AmqpModel model, boolean serverFlag, - int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - boolean firstClassFlag = true; - for (String thisClassName : model.getClassMap().keySet()) - { - AmqpClass thisClass = model.getClassMap().get(thisClassName); - String className = thisClass.getName(); - if (!firstClassFlag) - { - sb.append(CR); - } - sb.append(indent + "// ==================== class " + className + - " ====================" + CR); - sb.append(generateInnerClassMethodImpls(thisClass, serverFlag, indentSize, tabSize)); - firstClassFlag = false; - } - return sb.toString(); - } - - protected String generateInnerClassMethodImpls(AmqpClass thisClass, boolean serverFlag, - int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - String outerclassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; - boolean first = true; - for (String thisMethodName : thisClass.getMethodMap().keySet()) - { - AmqpMethod method = thisClass.getMethodMap().get(thisMethodName); - String methodBodyClassName = thisClass.getName() + Utils.firstUpper(method.getName()) + "Body"; - boolean clientChassisFlag = method.getClientMethodFlagMap().isSet(); - boolean serverChassisFlag = method.getServerMethodFlagMap().isSet(); - boolean versionConsistentFlag = method.isVersionConsistent(getVersionSet()); - if ((serverFlag && serverChassisFlag) || (!serverFlag && clientChassisFlag)) - { - String methodName = parseForReservedWords(method.getName(), outerclassName + "." + thisClass.getName()); - AmqpOverloadedParameterMap overloadededParameterMap = - method.getOverloadedParameterLists(thisClass.getVersionSet(), this); - for (AmqpOrdinalFieldMap thisFieldMap : overloadededParameterMap.keySet()) - { - AmqpVersionSet versionSet = overloadededParameterMap.get(thisFieldMap); - if (!first) - { - sb.append(CR); - } - sb.append(indent + "void " + outerclassName + "::" + thisClass.getName() + "::" + - methodName + "( u_int16_t channel"); - sb.append(generateMethodParameterList(thisFieldMap, indentSize + (5 * tabSize), true, true, true)); - sb.append(" )"); - if (versionSet.size() != getVersionSet().size()) - { - sb.append(" // AMQP Version(s) " + versionSet); - } - sb.append(CR); - sb.append(indent + "{" + CR); - sb.append(generateMethodBodyCallContext(thisFieldMap, outerclassName, methodBodyClassName, - versionConsistentFlag, versionSet, indentSize + tabSize, tabSize)); - sb.append(indent + "}" + CR); - sb.append(CR); - first = false; - } - } - } - return sb.toString(); - } - - protected String generateMethodBodyCallContext(AmqpOrdinalFieldMap fieldMap, String outerclassName, - String methodBodyClassName, boolean versionConsistentFlag, AmqpVersionSet versionSet, - int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - if (versionConsistentFlag) - { - sb.append(generateMethodBodyCall(fieldMap, methodBodyClassName, null, indentSize, tabSize)); - } - else - { - boolean firstOverloadedMethodFlag = true; - for (AmqpVersion thisVersion : versionSet) - { - sb.append(indent); - if (!firstOverloadedMethodFlag) - { - sb.append("else "); - } - sb.append("if (" + generateVersionCheck(thisVersion) + ")" + CR); - sb.append(indent + "{" + CR); - sb.append(generateMethodBodyCall(fieldMap, methodBodyClassName, thisVersion, - indentSize + tabSize, tabSize)); - sb.append(indent + "}" + CR); - firstOverloadedMethodFlag = false; - } - sb.append(indent + "else" + CR); - sb.append(indent + "{" + CR); - sb.append(indent + tab + "std::stringstream ss;" + CR); - sb.append(indent + tab + "ss << \"Call to " + outerclassName + "::" + methodBodyClassName + - "(u_int16_t" + generateMethodParameterList(fieldMap, 0, true, true, false) + ")\"" + CR); - sb.append(indent + tab + tab + "<< \" is invalid for AMQP version \" << version.toString() << \".\";" + CR); - sb.append(indent + tab + "throw new ProtocolVersionException(ss.str());" + CR); - sb.append(indent + "}" + CR); - } - return sb.toString(); - } - - protected String generateMethodBodyCall(AmqpOrdinalFieldMap fieldMap, String methodBodyClassName, - AmqpVersion version, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - String namespace = version != null ? version.namespace() + "::" : ""; - StringBuffer sb = new StringBuffer(indent + "out->send( new AMQFrame(parent->getProtocolVersion(), channel," + CR); - sb.append(indent + tab + "new " + namespace + methodBodyClassName + "( parent->getProtocolVersion()"); - sb.append(generateMethodParameterList(fieldMap, indentSize + (5 * tabSize), true, false, true)); - sb.append(" )));" + CR); - return sb.toString(); - } - - protected String generateMethodBodyIncludes(AmqpClass thisClass, int indentSize) - { - StringBuffer sb = new StringBuffer(); - if (thisClass != null) - { - sb.append(generateClassMethodBodyInclude(thisClass, indentSize)); - } - else - { - for (String thisClassName : getModel().getClassMap().keySet()) - { - thisClass = getModel().getClassMap().get(thisClassName); - sb.append(generateClassMethodBodyInclude(thisClass, indentSize)); - } - } - return sb.toString(); - } - - protected String generateClassMethodBodyInclude(AmqpClass thisClass, int indentSize) - { - StringBuffer sb = new StringBuffer(); - String indent = Utils.createSpaces(indentSize); - for (String thisMethodName : thisClass.getMethodMap().keySet()) - { - AmqpMethod method = thisClass.getMethodMap().get(thisMethodName); - sb.append(indent + "#include <" + thisClass.getName() + - Utils.firstUpper(method.getName()) + "Body.h>" + CR); - } - return sb.toString(); - } - - // Methods used for generation of code snippets for MethodBody class generation - - protected String getIndex(AmqpOrdinalVersionMap indexMap, AmqpVersion version) - { - for (Integer thisIndex : indexMap.keySet()) - { - AmqpVersionSet versionSet = indexMap.get(thisIndex); - if (versionSet.contains(version)) - { - return String.valueOf(thisIndex); - } - } - throw new AmqpTemplateException("Unable to find index for version " + version); - } - - protected String generateFieldDeclarations(AmqpFieldMap fieldMap, AmqpVersion version, int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - - if (version == null) - { - version = getVersionSet().first(); - } - AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, true, this); - for (Integer thisOrdinal : ordinalFieldMap.keySet()) - { - String[] fieldDomainPair = ordinalFieldMap.get(thisOrdinal); - sb.append(indent + fieldDomainPair[FIELD_CODE_TYPE] + " " + fieldDomainPair[FIELD_NAME] + ";" + CR); - } - return sb.toString(); - } - - protected String generateFieldGetMethods(AmqpFieldMap fieldMap, AmqpVersion version, int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - - if (version == null) - { - version = getVersionSet().first(); - } - AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, true, this); - for (Integer thisOrdinal : ordinalFieldMap.keySet()) - { - String[] fieldDomainPair = ordinalFieldMap.get(thisOrdinal); - sb.append(indent + "inline " + setRef(fieldDomainPair[FIELD_CODE_TYPE]) + " get" + - Utils.firstUpper(fieldDomainPair[FIELD_NAME]) + "() { return " + - fieldDomainPair[FIELD_NAME] + "; }" + CR); - } - return sb.toString(); - } - - protected String generatePrintMethodContents(AmqpFieldMap fieldMap, AmqpVersion version, int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - - if (version == null) - { - version = getVersionSet().first(); - } - AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, true, this); - boolean firstFlag = true; - for (Integer thisOrdinal : ordinalFieldMap.keySet()) - { - String[] fieldDomainPair = ordinalFieldMap.get(thisOrdinal); - String cast = fieldDomainPair[FIELD_CODE_TYPE].compareTo("u_int8_t") == 0 ? "(int)" : ""; - sb.append(indent + "out << \""); - if (!firstFlag) - { - sb.append("; "); - } - sb.append(fieldDomainPair[FIELD_NAME] + "=\" << " + cast + fieldDomainPair[FIELD_NAME] + ";" + CR); - firstFlag = false; - } - return sb.toString(); - } - - protected String generateBodySizeMethodContents(AmqpFieldMap fieldMap, AmqpVersion version, - int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - ArrayList<String> bitFieldList = new ArrayList<String>(); - AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, false, this); - Iterator<Integer> oItr = ordinalFieldMap.keySet().iterator(); - int ordinal = 0; - while (oItr.hasNext()) - { - ordinal = oItr.next(); - String[] fieldDomainPair = ordinalFieldMap.get(ordinal); - AmqpVersion thisVersion = version == null ? getVersionSet().first() : version; - String domainType = getDomainType(fieldDomainPair[FIELD_CODE_TYPE], thisVersion); - - // Defer bit types by adding them to an array. When the first subsequent non-bit - // type is encountered, then handle the bits. This allows consecutive bits to be - // placed into the same byte(s) - 8 bits to the byte. - if (domainType.compareTo("bit") == 0) - { - bitFieldList.add(fieldDomainPair[FIELD_NAME]); - } - else - { - if (bitFieldList.size() > 0) // Handle accumulated bit types (if any) - { - sb.append(generateBitArrayBodySizeMethodContents(bitFieldList, ordinal, indentSize)); - } - sb.append(indent + "size += " + - typeMap.get(domainType).size.replaceAll("#", fieldDomainPair[FIELD_NAME]) + - "; /* " + fieldDomainPair[FIELD_NAME] + ": " + - domainType + " */" + CR); - } - } - if (bitFieldList.size() > 0) // Handle any remaining accumulated bit types - { - sb.append(generateBitArrayBodySizeMethodContents(bitFieldList, ordinal, indentSize)); - } - return sb.toString(); - } - - protected String generateBitArrayBodySizeMethodContents(ArrayList<String> bitFieldList, - int ordinal, int indentSize) - { - int numBytes = ((bitFieldList.size() - 1) / 8) + 1; - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - String comment = bitFieldList.size() == 1 ? - bitFieldList.get(0) + ": bit" : - "Combinded bits: " + bitFieldList; - sb.append(indent + "size += " + - typeMap.get("bit").size.replaceAll("~", String.valueOf(numBytes)) + - "; /* " + comment + " */" + CR); - bitFieldList.clear(); - return sb.toString(); - } - - protected String generateEncodeMethodContents(AmqpFieldMap fieldMap, AmqpVersion version, - int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - ArrayList<String> bitFieldList = new ArrayList<String>(); - AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, false, this); - Iterator<Integer> oItr = ordinalFieldMap.keySet().iterator(); - int ordinal = 0; - while (oItr.hasNext()) - { - ordinal = oItr.next(); - String[] fieldDomainPair = ordinalFieldMap.get(ordinal); - AmqpVersion thisVersion = version == null ? getVersionSet().first() : version; - String domainType = getDomainType(fieldDomainPair[FIELD_CODE_TYPE], thisVersion); - - // Defer bit types by adding them to an array. When the first subsequent non-bit - // type is encountered, then handle the bits. This allows consecutive bits to be - // placed into the same byte(s) - 8 bits to the byte. - if (domainType.compareTo("bit") == 0) - { - bitFieldList.add(fieldDomainPair[FIELD_NAME]); - } - else - { - if (bitFieldList.size() > 0) // Handle accumulated bit types (if any) - { - sb.append(generateBitEncodeMethodContents(bitFieldList, ordinal, indentSize)); - } - sb.append(indent + - typeMap.get(domainType).encodeExpression.replaceAll("#", fieldDomainPair[FIELD_NAME]) + - "; /* " + fieldDomainPair[FIELD_NAME] + ": " + domainType + " */" + CR); - } - } - if (bitFieldList.size() > 0) // Handle any remaining accumulated bit types - { - sb.append(generateBitEncodeMethodContents(bitFieldList, ordinal, indentSize)); - } - - return sb.toString(); - } - - protected String generateBitEncodeMethodContents(ArrayList<String> bitFieldList, int ordinal, - int indentSize) - { - int numBytes = ((bitFieldList.size() - 1) / 8) + 1; - String indent = Utils.createSpaces(indentSize); - String bitArrayName = "flags_" + ordinal; - StringBuffer sb = new StringBuffer(indent + "u_int8_t " + bitArrayName + - "[" + numBytes + "] = {0};" + - (numBytes != 1 ? " /* All array elements will be initialized to 0 */" : "") + - CR); - for (int i = 0; i < bitFieldList.size(); i++) - { - int bitIndex = i % 8; - int byteIndex = i / 8; - sb.append(indent + bitArrayName + "[" + byteIndex + "] |= " + bitFieldList.get(i) + - " << " + bitIndex + "; /* " + bitFieldList.get(i) + ": bit */" + CR); - } - for (int i = 0; i < numBytes; i++) - { - sb.append(indent + "buffer.putOctet(" + bitArrayName + "[" + i + "]);" + CR); - } - bitFieldList.clear(); - return sb.toString(); - } - - protected String generateDecodeMethodContents(AmqpFieldMap fieldMap, AmqpVersion version, - int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - ArrayList<String> bitFieldList = new ArrayList<String>(); - AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, false, this); - Iterator<Integer> oItr = ordinalFieldMap.keySet().iterator(); - int ordinal = 0; - while (oItr.hasNext()) - { - ordinal = oItr.next(); - String[] fieldDomainPair = ordinalFieldMap.get(ordinal); - AmqpVersion thisVersion = version == null ? getVersionSet().first() : version; - String domainType = getDomainType(fieldDomainPair[FIELD_CODE_TYPE], thisVersion); - - // Defer bit types by adding them to an array. When the first subsequent non-bit - // type is encountered, then handle the bits. This allows consecutive bits to be - // placed into the same byte(s) - 8 bits to the byte. - if (domainType.compareTo("bit") == 0) - { - bitFieldList.add(fieldDomainPair[FIELD_NAME]); - } - else - { - if (bitFieldList.size() > 0) // Handle accumulated bit types (if any) - { - sb.append(generateBitDecodeMethodContents(bitFieldList, ordinal, indentSize)); - } - sb.append(indent + - typeMap.get(domainType).decodeExpression.replaceAll("#", fieldDomainPair[FIELD_NAME]) + - "; /* " + fieldDomainPair[FIELD_NAME] + ": " + domainType + " */" + CR); - } - } - if (bitFieldList.size() > 0) // Handle any remaining accumulated bit types - { - sb.append(generateBitDecodeMethodContents(bitFieldList, ordinal, indentSize)); - } - - return sb.toString(); - } - - protected String generateBitDecodeMethodContents(ArrayList<String> bitFieldList, int ordinal, - int indentSize) - { - int numBytes = ((bitFieldList.size() - 1) / 8) + 1; - String indent = Utils.createSpaces(indentSize); - String bitArrayName = "flags_" + ordinal; - StringBuffer sb = new StringBuffer(indent + "u_int8_t " + bitArrayName + - "[" + numBytes + "];" + CR); - for (int i = 0; i < numBytes; i++) - { - sb.append(indent + bitArrayName + "[" + i + "] = buffer.getOctet();" + CR); - } - for (int i = 0; i < bitFieldList.size(); i++) - { - int bitIndex = i % 8; - int byteIndex = i / 8; - sb.append(indent + bitFieldList.get(i) + " = (1 << " + bitIndex + ") & " + - bitArrayName + "[" + byteIndex + "]; /* " + bitFieldList.get(i) + - ": bit */" + CR); - } - bitFieldList.clear(); - return sb.toString(); - } - - protected String generateFieldList(AmqpFieldMap fieldMap, AmqpVersion version, boolean defineFlag, - boolean initializerFlag, int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, true, this); - Iterator<Integer> oItr = ordinalFieldMap.keySet().iterator(); - while (oItr.hasNext()) - { - int ordinal = oItr.next(); - String[] fieldDomainPair = ordinalFieldMap.get(ordinal); - sb.append(indent + (defineFlag ? setRef(fieldDomainPair[FIELD_CODE_TYPE]) + " " : "") + - fieldDomainPair[FIELD_NAME] + (initializerFlag ? "(" + fieldDomainPair[FIELD_NAME] + ")" : "") + - (oItr.hasNext() ? "," : "") + CR); - } - return sb.toString(); - } - - protected String generateMethodParameterList(AmqpOrdinalFieldMap fieldMap, int indentSize, - boolean leadingCommaFlag, boolean fieldTypeFlag, boolean fieldNameFlag) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - boolean first = true; - Iterator<Integer> pItr = fieldMap.keySet().iterator(); - while (pItr.hasNext()) - { - String[] field = fieldMap.get(pItr.next()); - if (first && leadingCommaFlag) - { - sb.append("," + (fieldNameFlag ? CR : " ")); - } - if (!first || leadingCommaFlag) - { - sb.append(indent); - } - sb.append( - (fieldTypeFlag ? setRef(field[FIELD_CODE_TYPE]) : "") + - (fieldNameFlag ? " " + field[FIELD_NAME] : "") + - (pItr.hasNext() ? "," + (fieldNameFlag ? CR : " ") : "")); - first = false; - } - return sb.toString(); - } - - protected String generateConstructor(AmqpClass thisClass, AmqpMethod method, - AmqpVersion version, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - if (method.getFieldMap().size() > 0) - { - sb.append(indent + thisClass.getName() + Utils.firstUpper(method.getName()) + "Body(ProtocolVersion& version," + CR); - sb.append(generateFieldList(method.getFieldMap(), version, true, false, 8)); - sb.append(indent + tab + ") :" + CR); - sb.append(indent + tab + "AMQMethodBody(version)," + CR); - sb.append(generateFieldList(method.getFieldMap(), version, false, true, 8)); - sb.append(indent + "{ }" + CR); - } - return sb.toString(); - } - - protected String generateServerOperationsInvoke(AmqpClass thisClass, AmqpMethod method, - AmqpVersion version, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - - if (method.getServerMethodFlagMap().size() > 0) // At least one AMQP version defines this method as a server method - { - Iterator<Boolean> bItr = method.getServerMethodFlagMap().keySet().iterator(); - while (bItr.hasNext()) - { - if (bItr.next()) // This is a server operation - { - boolean fieldMapNotEmptyFlag = method.getFieldMap().size() > 0; - sb.append(indent + "inline void invoke(AMQP_ServerOperations& target, u_int16_t channel)" + CR); - sb.append(indent + "{" + CR); - sb.append(indent + tab + "target.get" + thisClass.getName() + "Handler()->" + - parseForReservedWords(Utils.firstLower(method.getName()), - thisClass.getName() + Utils.firstUpper(method.getName()) + "Body.invoke()") + "(channel"); - if (fieldMapNotEmptyFlag) - { - sb.append("," + CR); - sb.append(generateFieldList(method.getFieldMap(), version, false, false, indentSize + 4 * tabSize)); - sb.append(indent + tab + tab + tab + tab); - } - sb.append(");" + CR); - sb.append(indent + "}" + CR); - } - } - } - return sb.toString(); - } - - // Methods for generation of code snippets for amqp_methods.h/cpp files - - protected String generateMethodBodyIncludeList(AmqpModel model, int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - - for (String thisClassName : model.getClassMap().keySet()) - { - AmqpClass thisClass = model.getClassMap().get(thisClassName); - for (String thisMethodName : thisClass.getMethodMap().keySet()) - { - AmqpMethod method = thisClass.getMethodMap().get(thisMethodName); - sb.append(indent + "#include \"" + thisClass.getName() + Utils.firstUpper(method.getName()) + "Body.h\"" + CR); - } - } - - return sb.toString(); - } - - protected String generateMethodBodyInstances(AmqpModel model, int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - - for (String thisClassName : model.getClassMap().keySet()) - { - AmqpClass thisClass = model.getClassMap().get(thisClassName); - for (String thisMethodName : thisClass.getMethodMap().keySet()) - { - AmqpMethod method = thisClass.getMethodMap().get(thisMethodName); - sb.append(indent + "const " + thisClass.getName() + Utils.firstUpper(method.getName()) + "Body " + - Utils.firstLower(thisClass.getName()) + "_" + method.getName() + ";" + CR); - } - } - - return sb.toString(); - } - - protected String generateMethodBodyMapEntry(AmqpModel model, int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - - for (AmqpVersion version : getVersionSet()) - { - for (String thisClassName : model.getClassMap().keySet()) - { - AmqpClass thisClass = model.getClassMap().get(thisClassName); - for (String thisMethodName : thisClass.getMethodMap().keySet()) - { - AmqpMethod method = thisClass.getMethodMap().get(thisMethodName); - String namespace = method.isVersionConsistent(getVersionSet()) ? "" : version.namespace() + "::"; - try - { - int classOrdinal = thisClass.getIndexMap().getOrdinal(version); - int methodOrdinal = method.getIndexMap().getOrdinal(version); - String methodModyClassName = namespace + thisClass.getName() + Utils.firstUpper(method.getName()) + "Body"; - sb.append(indent + "insert(std::make_pair(createMapKey(" + classOrdinal + ", " + - methodOrdinal + ", " + version.getMajor() + ", " + version.getMinor() + - "), &createMethodBodyFn<" + methodModyClassName + ">));" + CR); - } - catch (AmqpTypeMappingException e) - { - } // ignore - } - } - } - - return sb.toString(); - } - - // Helper functions - - private String generateVersionCheck(AmqpVersion version) - { - return "version.equals(" + version.getMajor() + ", " + version.getMinor() + ")"; - } - - private String generateVersionCheck(AmqpVersionSet versionSet) - { - StringBuffer sb = new StringBuffer(); - for (AmqpVersion v : versionSet) - { - if (!v.equals(versionSet.first())) - { - sb.append(" || "); - } - if (versionSet.size() > 1) - { - sb.append("("); - } - sb.append("version.equals(" + v.getMajor() + ", " + v.getMinor() + ")"); - if (versionSet.size() > 1) - { - sb.append(")"); - } - } - return sb.toString(); - } - - private String parseForReservedWords(String name, String context) - { - for (String cppReservedWord : cppReservedWords) - { - if (name.compareTo(cppReservedWord) == 0) - { - if (!quietFlag) - { - System.out.println("WARNING: " + (context == null ? "" : context + ": ") + - "Found XML method \"" + name + "\", which is a C++ reserved word. " + - "Changing generated name to \"" + name + "_\"."); - } - return name + "_"; - } - } - - for (String cppCommonDefine : cppCommonDefines) - { - if (name.compareTo(cppCommonDefine) == 0) - { - if (!quietFlag) - { - System.out.println("WARNING: " + (context == null ? "" : context + ": ") + - "Found XML method \"" + name + "\", which may clash with commonly used defines within C++. " + - "Changing generated name to \"" + name + "_\"."); - } - return name + "_"; - } - } - - return name; - } - - private String setRef(String codeType) - { - if (codeType.compareTo("string") == 0 || - codeType.compareTo("FieldTable") == 0) - { - return "const " + codeType + "&"; - } - return codeType; - } - - private String camelCaseName(String name, boolean upperFirstFlag) - { - StringBuffer ccn = new StringBuffer(); - String[] toks = name.split("[-_.\\ ]"); - for (int i = 0; i < toks.length; i++) - { - StringBuffer b = new StringBuffer(toks[i]); - if (upperFirstFlag || i > 0) - { - b.setCharAt(0, Character.toUpperCase(toks[i].charAt(0))); - } - ccn.append(b); - } - return ccn.toString(); - } - - public static Factory<CppGenerator> _factoryInstance = new Factory<CppGenerator>() - { - - public CppGenerator newInstance() - { - return new CppGenerator(); - } - }; - - public static Factory<CppGenerator> getFactory() - { - return _factoryInstance; - } - - void processModelTemplate(NamedTemplate template, AmqpVersion version) - { - //To change body of implemented methods use File | Settings | File Templates. - } - public String getNativeType(String type) - { - throw new UnsupportedOperationException(); - } - - public String getEncodingType(String type) - { - throw new UnsupportedOperationException(); - } - -} diff --git a/gentools/src/org/apache/qpid/gentools/DotnetGenerator.java b/gentools/src/org/apache/qpid/gentools/DotnetGenerator.java deleted file mode 100644 index 9fc81dd428..0000000000 --- a/gentools/src/org/apache/qpid/gentools/DotnetGenerator.java +++ /dev/null @@ -1,382 +0,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. - * - */ - -package org.apache.qpid.gentools; - -import java.io.File; -import java.util.TreeMap; - -public class DotnetGenerator extends Generator -{ - private class DomainInfo - { - public String type; - public String size; - public String encodeExpression; - public String decodeExpression; - - public DomainInfo(String domain, String size, String encodeExpression, String decodeExpression) - { - this.type = domain; - this.size = size; - this.encodeExpression = encodeExpression; - this.decodeExpression = decodeExpression; - } - } - - private static TreeMap<String, DomainInfo> typeMap = new TreeMap<String, DomainInfo>(); - - public String getNativeType(String type) - { - throw new UnsupportedOperationException(); - } - - public String getEncodingType(String type) - { - throw new UnsupportedOperationException(); - } - - public DotnetGenerator() - { - super(); - // Load .NET type and size maps. - // Adjust or add to these lists as new types are added/defined. - // The char '#' will be replaced by the field variable name (any type). - // The char '~' will be replaced by the compacted bit array size (type bit only). - // TODO: I have left a copy of the Java typeMap here - replace with appropriate .NET values. - typeMap.put("bit", new DomainInfo( - "boolean", // .NET code type - "~", // size - "EncodingUtils.writeBooleans(buffer, #)", // encode expression - "# = EncodingUtils.readBooleans(buffer)")); // decode expression - typeMap.put("content", new DomainInfo( - "Content", // .NET code type - "EncodingUtils.encodedContentLength(#)", // size - "EncodingUtils.writeContentBytes(buffer, #)", // encode expression - "# = EncodingUtils.readContent(buffer)")); // decode expression - typeMap.put("long", new DomainInfo( - "long", // .NET code type - "4", // size - "EncodingUtils.writeUnsignedInteger(buffer, #)", // encode expression - "# = buffer.getUnsignedInt()")); // decode expression - typeMap.put("longlong", new DomainInfo( - "long", // .NET code type - "8", // size - "buffer.putLong(#)", // encode expression - "# = buffer.getLong()")); // decode expression - typeMap.put("longstr", new DomainInfo( - "byte[]", // .NET code type - "EncodingUtils.encodedLongstrLength(#)", // size - "EncodingUtils.writeLongStringBytes(buffer, #)", // encode expression - "# = EncodingUtils.readLongstr(buffer)")); // decode expression - typeMap.put("octet", new DomainInfo( - "short", // .NET code type - "1", // size - "EncodingUtils.writeUnsignedByte(buffer, #)", // encode expression - "# = buffer.getUnsigned()")); // decode expression - typeMap.put("short", new DomainInfo( - "int", // .NET code type - "2", // size - "EncodingUtils.writeUnsignedShort(buffer, #)", // encode expression - "# = buffer.getUnsignedShort()")); // decode expression - typeMap.put("shortstr", new DomainInfo( - "AMQShortString", // .NET code type - "EncodingUtils.encodedShortStringLength(#)", // size - "EncodingUtils.writeShortStringBytes(buffer, #)", // encode expression - "# = EncodingUtils.readAMQShortString(buffer)")); // decode expression - typeMap.put("table", new DomainInfo( - "FieldTable", // .NET code type - "EncodingUtils.encodedFieldTableLength(#)", // size - "EncodingUtils.writeFieldTableBytes(buffer, #)", // encode expression - "# = EncodingUtils.readFieldTable(buffer)")); // decode expression - typeMap.put("timestamp", new DomainInfo( - "long", // .NET code type - "8", // size - "EncodingUtils.writeTimestamp(buffer, #)", // encode expression - "# = EncodingUtils.readTimestamp(buffer)")); // decode expression - } - - void processModelTemplate(NamedTemplate template, AmqpVersion version) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - void processClassTemplate(NamedTemplate template, AmqpClass amqpClass, AmqpVersion version) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - void processMethodTemplate(NamedTemplate template, AmqpClass amqpClass, AmqpMethod amqpMethod, AmqpVersion version) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - void processFieldTemplate(NamedTemplate template, AmqpClass amqpClass, AmqpMethod amqpMethod, AmqpField amqpField, AmqpVersion version) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - protected String prepareFilename(String filenameTemplate, - AmqpClass thisClass, AmqpMethod method, AmqpField field, AmqpVersion version) - { - StringBuffer sb = new StringBuffer(filenameTemplate); - if (thisClass != null) - { - replaceToken(sb, "${CLASS}", thisClass.getName()); - } - if (method != null) - { - replaceToken(sb, "${METHOD}", method.getName()); - } - if (field != null) - { - replaceToken(sb, "${FIELD}", field.getName()); - } - return sb.toString(); - } - - @Override - protected void processClassList(StringBuffer sb, int listMarkerStartIndex, - int listMarkerEndIndex, AmqpModel model, AmqpVersion version) - throws AmqpTemplateException, AmqpTypeMappingException - { - String codeSnippet; - int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line - String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr - int tokStart = tline.indexOf('$'); - String token = tline.substring(tokStart).trim(); - sb.delete(listMarkerStartIndex, lend); - - // TODO: Add in tokens and calls to their corresponding generator methods here... - if (token.compareTo("${??????????}") == 0) - { - codeSnippet = token; // This is a stub to get the compile working - remove when gen method is present. -// codeSnippet = generateRegistry(model, 8, 4); - } - - else // Oops! - { - throw new AmqpTemplateException("Template token " + token + " unknown."); - } - sb.insert(listMarkerStartIndex, codeSnippet); - } - - @Override - protected void processConstantList(StringBuffer sb, - int listMarkerStartIndex, int listMarkerEndIndex, - AmqpConstantSet constantSet) throws AmqpTemplateException, - AmqpTypeMappingException - { - String codeSnippet; - int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line - String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr - int tokStart = tline.indexOf('$'); - String token = tline.substring(tokStart).trim(); - sb.delete(listMarkerStartIndex, lend); - - // TODO: Add in tokens and calls to their corresponding generator methods here... - if (token.compareTo("${??????????}") == 0) - { - codeSnippet = token; // This is a stub to get the compile working - remove when gen method is present. -// codeSnippet = generateConstantGetMethods(constantSet, 4, 4); - } - - else // Oops! - { - throw new AmqpTemplateException("Template token " + token + " unknown."); - } - sb.insert(listMarkerStartIndex, codeSnippet); - } - - @Override - protected void processFieldList(StringBuffer sb, int listMarkerStartIndex, - int listMarkerEndIndex, AmqpFieldMap fieldMap, AmqpVersion version) - { - String codeSnippet; - int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line - String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr - int tokStart = tline.indexOf('$'); - String token = tline.substring(tokStart).trim(); - sb.delete(listMarkerStartIndex, lend); - - // TODO: Add in tokens and calls to their corresponding generator methods here... - if (token.compareTo("${??????????}") == 0) - { - codeSnippet = token; // This is a stub to get the compile working - remove when gen method is present. -// codeSnippet = fieldMap.parseFieldMap(declarationGenerateMethod, -// mangledDeclarationGenerateMethod, 4, 4, this); - } - - else // Oops! - { - throw new AmqpTemplateException("Template token " + token + " unknown."); - } - sb.insert(listMarkerStartIndex, codeSnippet); - } - - @Override - protected void processMethodList(StringBuffer sb, int listMarkerStartIndex, - int listMarkerEndIndex, AmqpClass thisClass) - throws AmqpTemplateException, AmqpTypeMappingException - { - String codeSnippet; - int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line - String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr - int tokStart = tline.indexOf('$'); - String token = tline.substring(tokStart).trim(); - sb.delete(listMarkerStartIndex, lend); - - // TODO: Add in tokens and calls to their corresponding generator methods here... - if (token.compareTo("${??????????}") == 0) - { - codeSnippet = token; // This is a stub to get the compile working - remove when gen method is present. - } - - else // Oops! - { - throw new AmqpTemplateException("Template token " + token + " unknown."); - } - sb.insert(listMarkerStartIndex, codeSnippet); - } - - @Override - protected void processModelTemplate(NamedTemplate template) - { - // I've put in the Java model here - this can be changed if a different pattern is required. - processTemplate(template, null, null, null, null); - } - - @Override - protected void processClassTemplate(NamedTemplate template, AmqpClass thisClass) - { - // I've put in the Java model here - this can be changed if a different pattern is required. - processTemplate(template, thisClass, null, null, null); - } - - @Override - protected void processMethodTemplate(NamedTemplate template, AmqpClass thisClass, - AmqpMethod method) - { - // I've put in the Java model here - this can be changed if a different pattern is required. - processTemplate(template, thisClass, method, null, null); - } - - @Override - protected void processTemplate(NamedTemplate template, AmqpClass thisClass, - AmqpMethod method, AmqpField field, AmqpVersion version) - { - // I've put in the Java model here - this can be changed if a different pattern is required. - StringBuffer sb = new StringBuffer(template.getTemplate()); - String filename = prepareFilename(getTemplateFileName(sb), thisClass, method, field, version); - try - { - processAllLists(sb, thisClass, method, null); - } - catch (AmqpTemplateException e) - { - System.out.println("WARNING: " + template.getName() + ": " + e.getMessage()); - } - try - { - processAllTokens(sb, thisClass, method, field, null); - } - catch (AmqpTemplateException e) - { - System.out.println("WARNING: " + template.getName() + ": " + e.getMessage()); - } - writeTargetFile(sb, new File(getOutputDirectory() + Utils.FILE_SEPARATOR + filename)); - generatedFileCounter++; - } - - @Override - protected String processToken(String token, AmqpClass thisClass, - AmqpMethod method, AmqpField field, AmqpVersion version) - throws AmqpTemplateException, AmqpTypeMappingException - { - // TODO Auto-generated method stub - return null; - } - - public String getGeneratedType(String domainName, AmqpVersion version) - throws AmqpTypeMappingException - { - String domainType = getDomainType(domainName, version); - if (domainType == null) - { - throw new AmqpTypeMappingException("Domain type \"" + domainName + - "\" not found in Java typemap."); - } - DomainInfo info = typeMap.get(domainType); - if (info == null) - { - throw new AmqpTypeMappingException("Unknown domain: \"" + domainType + "\""); - } - return info.type; - } - - public String prepareClassName(String className) - { - return camelCaseName(className, true); - } - - public String prepareDomainName(String domainName) - { - return camelCaseName(domainName, false); - } - - public String prepareMethodName(String methodName) - { - return camelCaseName(methodName, false); - } - - private String camelCaseName(String name, boolean upperFirstFlag) - { - StringBuffer ccn = new StringBuffer(); - String[] toks = name.split("[-_.\\ ]"); - for (int i = 0; i < toks.length; i++) - { - StringBuffer b = new StringBuffer(toks[i]); - if (upperFirstFlag || i > 0) - { - b.setCharAt(0, Character.toUpperCase(toks[i].charAt(0))); - } - ccn.append(b); - } - return ccn.toString(); - } - - - public static Factory<DotnetGenerator> _factoryInstance = new Factory<DotnetGenerator>() - { - - public DotnetGenerator newInstance() - { - return new DotnetGenerator(); - } - }; - - public static Factory<DotnetGenerator> getFactory() - { - return _factoryInstance; - } - -} diff --git a/gentools/src/org/apache/qpid/gentools/GenerateMethod.java b/gentools/src/org/apache/qpid/gentools/GenerateMethod.java deleted file mode 100644 index 8b0bb99b41..0000000000 --- a/gentools/src/org/apache/qpid/gentools/GenerateMethod.java +++ /dev/null @@ -1,27 +0,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. - * - */ -package org.apache.qpid.gentools; - - -public interface GenerateMethod -{ - String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize); -} diff --git a/gentools/src/org/apache/qpid/gentools/Generator.java b/gentools/src/org/apache/qpid/gentools/Generator.java deleted file mode 100644 index 5d6e7be527..0000000000 --- a/gentools/src/org/apache/qpid/gentools/Generator.java +++ /dev/null @@ -1,857 +0,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. - * - */ -package org.apache.qpid.gentools; - -import org.apache.velocity.Template; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.Velocity; -import org.w3c.dom.Node; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.LineNumberReader; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.EnumMap; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -public abstract class Generator implements LanguageConverter -{ - protected static String CR = Utils.LINE_SEPARATOR; - - - private static final Map<String, Integer> FIXED_SIZE_TYPES = new HashMap<String, Integer>(); - - static - { - FIXED_SIZE_TYPES.put("bit", 1); - FIXED_SIZE_TYPES.put("bitfield", 1); - FIXED_SIZE_TYPES.put("long", 4); - FIXED_SIZE_TYPES.put("longlong", 8); - FIXED_SIZE_TYPES.put("octet", 1); - FIXED_SIZE_TYPES.put("short", 2); - FIXED_SIZE_TYPES.put("timestamp", 8); - - } - - private String _templateDirectory; - private String _outputDirectory; - - public AmqpDomainMap getDomainMap() - { - return _domainMap; - } - - public AmqpConstantSet getConstantSet() - { - return _constantSet; - } - - public AmqpModel getModel() - { - return _model; - } - - abstract public String getNativeType(String type); - - abstract public String getEncodingType(String type); - - - - protected static enum EnumConstOutputTypes - { - OUTPUT_STRING, - OUTPUT_INTEGER, - OUTPUT_DOUBLE; - } - - ; - - public static enum TemplateType - { - model("model"), - clazz("class"), - method("method"), - field("field"); - - private final String _name; - - private TemplateType(String name) - { - _name = name; - } - - public String getName() - { - return _name; - } - } - - ; - - - public static interface Factory<X extends Generator> - { - public X newInstance(); - } - - - protected static final class NamedTemplate - { - private final String _name; - private final String _template; - private final File _file; - - - public NamedTemplate(String relativePath, File templateFile) - { - _file = templateFile; - _name = relativePath + Utils.FILE_SEPARATOR + templateFile.getName(); - - _template = loadTemplate(templateFile); - } - - - public String getName() - { - return _name; - } - - public String getTemplate() - { - return _template; - } - - - public File getFile() - { - return _file; - } - - } - - - private static final String VELOCITY_TEMPLATE_SUFFIX = ".vm"; - private static final String STANDARD_TEMPLATE_SUFFIX = ".tmpl"; - private static FilenameFilter _tmplFileFilter = new FilenameFilter() - { - - public boolean accept(File dir, String name) - { - return name.endsWith(STANDARD_TEMPLATE_SUFFIX) || name.endsWith(VELOCITY_TEMPLATE_SUFFIX); - } - }; - - - // This string is reproduced in every generated file as a comment - // TODO: Tie the version info into the build system. - protected static final String GENERATOR_INFO = "Qpid Gentools v.0.1"; - - - private final Map<TemplateType, Collection<NamedTemplate>> _templates = - new EnumMap<TemplateType, Collection<NamedTemplate>>(TemplateType.class); - - private final Map<TemplateType, Collection<NamedTemplate>> _versionSpecificTemplates = - new EnumMap<TemplateType, Collection<NamedTemplate>>(TemplateType.class); - - - private final AmqpVersionSet _versionSet; - - private final AmqpDomainMap _domainMap; - private final Map<AmqpVersion, AmqpDomainMap> _versionToDomainMapMap = new HashMap<AmqpVersion, AmqpDomainMap>(); - - private final AmqpConstantSet _constantSet; - private final Map<AmqpVersion, AmqpConstantSet> _versionToConstantSetMap = new HashMap<AmqpVersion, AmqpConstantSet>(); - - - public AmqpVersionSet getVersionSet() - { - return _versionSet; - } - - private final AmqpModel _model; - private final Map<AmqpVersion, AmqpModel> _versionToModelMap = new HashMap<AmqpVersion, AmqpModel>(); - - protected int generatedFileCounter; - - public Generator() - { - _versionSet = new AmqpVersionSet(); - _model = new AmqpModel(this); - _constantSet = new AmqpConstantSet(this); - _domainMap = new AmqpDomainMap(this); - - generatedFileCounter = 0; - } - -// public final AmqpVersionSet getVersionSet() -// { -// return _versionSet; -// } - - - public void addVersion(AmqpVersion version) - { - _versionSet.add(version); - if (!_versionToModelMap.containsKey(version)) - { - _versionToModelMap.put(version, new AmqpModel(this)); - } - if (!_versionToDomainMapMap.containsKey(version)) - { - _versionToDomainMapMap.put(version, new AmqpDomainMap(this)); - } - if (!_versionToConstantSetMap.containsKey(version)) - { - _versionToConstantSetMap.put(version, new AmqpConstantSet(this)); - } - } - - public int getNumberGeneratedFiles() - { - return generatedFileCounter; - } - -// public AmqpDomainMap getDomainMap() -// { -// return _domainMap; -// } -// -// public AmqpConstantSet getConstantSet() -// { -// return _constantSet; -// } -// -// -// public AmqpModel getModel() -// { -// return _model; -// } - - public void initializeTemplates() throws IOException - { - - for (TemplateType type : EnumSet.allOf(TemplateType.class)) - { - ArrayList<NamedTemplate> typeTemplates = new ArrayList<NamedTemplate>(); - _templates.put(type, typeTemplates); - ArrayList<NamedTemplate> versionSpecificTypeTemplates = new ArrayList<NamedTemplate>(); - _versionSpecificTemplates.put(type, versionSpecificTypeTemplates); - - File templateDirectory = new File(getTemplateDirectory() + Utils.FILE_SEPARATOR + type.getName()); - File versionTemplateDirectory = new File(getTemplateDirectory() + Utils.FILE_SEPARATOR + type.getName() + Utils.FILE_SEPARATOR + "version"); - - System.out.println("Looking for template files in directory: " + templateDirectory.getAbsoluteFile()); - - File[] templateFiles = templateDirectory.listFiles(_tmplFileFilter); - - File[] versionTemplateFiles = new File[0]; - - System.out.println("Looking for version specific template files in directory: " + versionTemplateDirectory.getAbsoluteFile()); - - if (versionTemplateDirectory.exists()) - { - versionTemplateFiles = versionTemplateDirectory.listFiles(_tmplFileFilter); - } - - if(templateFiles != null) - { - for (File templateFile : templateFiles) - { - System.out.println(type.getName() + " template file(s):"); - System.out.println(" " + templateFile.getCanonicalPath()); - typeTemplates.add(new NamedTemplate(type.getName(), templateFile)); - } - } - - if(versionTemplateFiles != null) - { - for (File versionTemplateFile : versionTemplateFiles) - { - System.out.println(type.getName() + " template file(s):"); - System.out.println(" " + versionTemplateFile.getCanonicalPath()); - versionSpecificTypeTemplates.add(new NamedTemplate(type.getName() + Utils.FILE_SEPARATOR + "version", versionTemplateFile)); - } - } - - } - } - - public String getTemplateDirectory() - { - return _templateDirectory; - } - - - public void setTemplateDirectory(String templateDirectory) - { - _templateDirectory = templateDirectory; - } - - - public void setOutputDirectory(String outputDirectory) - { - _outputDirectory = outputDirectory; - } - - public void generate() - { - prepareTargetDirectory(new File(_outputDirectory), true); - System.out.println("Generation directory: " + _outputDirectory); - - - processModelTemplates(_templates); - - for (AmqpClass amqpClass : _model.getClassMap().values()) - { - processClassTemplates(_templates, amqpClass); - - for (AmqpMethod amqpMethod : amqpClass.getMethodMap().values()) - { - processMethodTemplates(_templates, amqpClass, amqpMethod); - - for (AmqpField amqpField : amqpMethod.getFieldMap().values()) - { - processFieldTemplates(_templates, amqpClass, amqpMethod, amqpField, null); - } - } - } - - - for (AmqpVersion version : _versionSet) - { - AmqpModel model = _versionToModelMap.get(version); - processModelTemplates(_versionSpecificTemplates, version); - - for (AmqpClass amqpClass : model.getClassMap().values()) - { - processClassTemplates(_versionSpecificTemplates, amqpClass, version); - - for (AmqpMethod amqpMethod : amqpClass.getMethodMap().values()) - { - processMethodTemplates(_versionSpecificTemplates, amqpClass, amqpMethod, version); - - for (AmqpField amqpField : amqpMethod.getFieldMap().values()) - { - processFieldTemplates(_versionSpecificTemplates, amqpClass, amqpMethod, amqpField, version); - } - } - } - - } - } - - private void processMethodTemplates(Map<TemplateType, Collection<NamedTemplate>> templates, AmqpClass amqpClass, AmqpMethod amqpMethod, AmqpVersion version) - { - for (NamedTemplate template : templates.get(TemplateType.method)) - { - if(isVelocityTemplate(template)) - { - processVelocityTemplate(template,version,amqpClass,amqpMethod,null); - } - else - { - processMethodTemplate(template, amqpClass, amqpMethod); - } - } - - } - - private void processClassTemplates(Map<TemplateType, Collection<NamedTemplate>> templates, AmqpClass amqpClass, AmqpVersion version) - { - for (NamedTemplate template : templates.get(TemplateType.clazz)) - { - if(isVelocityTemplate(template)) - { - processVelocityTemplate(template,version,amqpClass,null,null); - } - else - { - processClassTemplate(template, amqpClass); - } - } - - } - - - private void processModelTemplates(Map<TemplateType, Collection<NamedTemplate>> templates, AmqpVersion version) - { - for (NamedTemplate template : templates.get(TemplateType.model)) - { - if (isVelocityTemplate(template)) - { - processModelVelocityTemplate(template, version); - } - else - { - processModelTemplate(template, version); - } - } - } - - abstract void processModelTemplate(NamedTemplate template, AmqpVersion version); - - - protected void processModelTemplates(Map<TemplateType, Collection<NamedTemplate>> templates) - { - for (NamedTemplate template : templates.get(TemplateType.model)) - { - if (isVelocityTemplate(template)) - { - processModelVelocityTemplate(template, null); - } - else - { - processModelTemplate(template); - } - } - } - - private boolean isVelocityTemplate(NamedTemplate template) - { - return template.getName().endsWith(VELOCITY_TEMPLATE_SUFFIX); - } - - private void processModelVelocityTemplate(NamedTemplate template, AmqpVersion version) - { - processVelocityTemplate(template,version,null,null,null); - } - - private void processVelocityTemplate(NamedTemplate template, AmqpVersion version, - AmqpClass amqpClass, AmqpMethod amqpMethod, AmqpField amqpField) - { - - VelocityContext context = new VelocityContext(); - - AmqpModel model = _model; - if(version != null) - { - model = _versionToModelMap.get(version); - } - context.put("model", model); - context.put("generator", GENERATOR_INFO); - - if (version != null) - { - context.put("version", version); - } - if(amqpClass != null) - { - context.put("amqpClass", amqpClass); - } - - if(amqpClass != null) - { - context.put("amqpMethod", amqpMethod); - } - - - StringWriter sw = new StringWriter(); - - - try - { - Template velocityTemplate = Velocity.getTemplate(template.getName()); - velocityTemplate.merge(context, sw); - String filename = String.valueOf(context.get("filename")); - - File outputFile = new File(getOutputDirectory() + Utils.FILE_SEPARATOR + filename); - outputFile.getParentFile().mkdirs(); - FileWriter outputFileWriter = new FileWriter(outputFile); - - outputFileWriter.append(sw.toString()); - outputFileWriter.close(); - - } - catch (Exception e) - { - e.printStackTrace(); - } - - - } - - - protected void processClassTemplates(Map<TemplateType, Collection<NamedTemplate>> templates, AmqpClass amqpClass) - { - for (NamedTemplate template : templates.get(TemplateType.clazz)) - { - if(isVelocityTemplate(template)) - { - processVelocityTemplate(template,null,amqpClass,null,null); - } - else - { - processClassTemplate(template, amqpClass); - } - } - } - - protected void processMethodTemplates(Map<TemplateType, Collection<NamedTemplate>> templates, AmqpClass amqpClass, AmqpMethod amqpMethod) - { - for (NamedTemplate template : templates.get(TemplateType.method)) - { - if(isVelocityTemplate(template)) - { - processVelocityTemplate(template,null,amqpClass,amqpMethod,null); - } - else - { - processMethodTemplate(template, amqpClass, amqpMethod); - } - } - } - - - protected void processFieldTemplates(Map<TemplateType, Collection<NamedTemplate>> templates, AmqpClass amqpClass, AmqpMethod amqpMethod, AmqpField amqpField, AmqpVersion amqpVersion) - { - for (NamedTemplate template : templates.get(TemplateType.field)) - { - if(isVelocityTemplate(template)) - { - processVelocityTemplate(template,amqpVersion,amqpClass,amqpMethod,amqpField); - } - else - { - processTemplate(template, amqpClass, amqpMethod, amqpField, amqpVersion); - } - } - } - - - protected void processVersionList(StringBuffer sb, int tokStart, int tokEnd) - { - int lend = sb.indexOf(Utils.LINE_SEPARATOR, tokStart) + 1; // Include cr at end of line - String tline = sb.substring(tokEnd, lend); // Line excluding line marker, including cr - sb.delete(tokStart, lend); - - for (AmqpVersion v : _versionSet) - { - // Insert copy of target line - StringBuffer isb = new StringBuffer(tline); - if (isb.indexOf("${protocol-version-list-entry}") >= 0) - { - String versionListEntry = " { ${major}, ${minor} }" + - (v.equals(_versionSet.last()) ? "" : ","); - replaceToken(isb, "${protocol-version-list-entry}", String.valueOf(versionListEntry)); - } - if (isb.indexOf("${major}") >= 0) - { - replaceToken(isb, "${major}", String.valueOf(v.getMajor())); - } - if (isb.indexOf("${minor}") >= 0) - { - replaceToken(isb, "${minor}", String.valueOf(v.getMinor())); - } - sb.insert(tokStart, isb.toString()); - tokStart += isb.length(); - } - } - - // Helper functions common to all generators - - protected static void prepareTargetDirectory(File dir, boolean createFlag) - { - if (dir.exists()) - { - if (!dir.isDirectory()) - { - throw new TargetDirectoryException("\"" + dir.getAbsolutePath() + - "\" exists, but is not a directory."); - } - } - else if (createFlag) // Create dir - { - if (!dir.mkdirs()) - { - throw new TargetDirectoryException("Unable to create directory \"" + - dir.getAbsolutePath() + "\"."); - } - } - else - { - throw new TargetDirectoryException("Directory \"" + dir.getAbsolutePath() + - "\" not found."); - } - - } - - protected void processAllLists(StringBuffer sb, AmqpClass thisClass, AmqpMethod method, AmqpVersion version) - { - AmqpModel model = (version == null) ? _model : _versionToModelMap.get(version); - - - int lstart = sb.indexOf("%{"); - while (lstart != -1) - { - int lend = sb.indexOf("}", lstart + 2); - if (lend > 0) - { - String listToken = sb.substring(lstart + 2, lend); - if (listToken.compareTo("VLIST") == 0) - { - processVersionList(sb, lstart, lend + 1); - } - else if (listToken.compareTo("CLIST") == 0) - { - processClassList(sb, lstart, lend + 1, model, version); - } - else if (listToken.compareTo("MLIST") == 0) - { - processMethodList(sb, lstart, lend + 1, thisClass); - } - else if (listToken.compareTo("FLIST") == 0) - { - // Pass the FieldMap from either a class or a method. - // If this is called from a class-level template, we assume that the - // class field list is required. In this case, method will be null. - processFieldList(sb, lstart, lend + 1, - (method == null ? thisClass.getFieldMap() : method.getFieldMap()), - version); - } - else if (listToken.compareTo("TLIST") == 0) - { - processConstantList(sb, lstart, lend + 1, _constantSet); - } - else - { - throw new AmqpTemplateException("Unknown list token \"%{" + listToken + - "}\" found in template at index " + lstart + "."); - } - } - lstart = sb.indexOf("%{", lstart + 1); - } - } - - protected void processAllTokens(StringBuffer sb, AmqpClass thisClass, AmqpMethod method, AmqpField field, - AmqpVersion version) - { - int lstart = sb.indexOf("${"); - while (lstart != -1) - { - int lend = sb.indexOf("}", lstart + 2); - if (lend > 0) - { - String token = sb.substring(lstart, lend + 1); - replaceToken(sb, lstart, token, processToken(token, thisClass, method, field, version)); - } - lstart = sb.indexOf("${", lstart); - } - } - - protected static void writeTargetFile(StringBuffer sb, File f) - { - try - { - f.getParentFile().mkdirs(); - FileWriter fw = new FileWriter(f); - fw.write(sb.toString().toCharArray()); - fw.flush(); - fw.close(); - } - catch (IOException e) - { - throw new AmqpTemplateException(e.getMessage()); - } - } - - - protected static String getTemplateFileName(StringBuffer sb) - { - if (sb.charAt(0) != '&') - { - throw new AmqpTemplateException("No filename marker &{filename} found at start of template."); - } - int cr = sb.indexOf(Utils.LINE_SEPARATOR); - if (cr < 0) - { - throw new AmqpTemplateException("Bad template structure - unable to find first line."); - } - String fileName = sb.substring(2, cr - 1); - sb.delete(0, cr + 1); - return fileName; - } - - protected static void replaceToken(StringBuffer sb, String token, String replacement) - { - replaceToken(sb, 0, token, replacement); - } - - protected static void replaceToken(StringBuffer sb, int index, String token, String replacement) - { - if (replacement != null) - { - int start = sb.indexOf(token, index); - if (start != -1) - { - int len = token.length(); - // Find first letter in token and determine if it is capitalized - char firstTokenLetter = getFirstLetter(token); - if (firstTokenLetter != 0 && Character.isUpperCase(firstTokenLetter)) - { - sb.replace(start, start + len, Utils.firstUpper(replacement)); - } - else - { - sb.replace(start, start + len, replacement); - } - } - } - } - - private static char getFirstLetter(String str) - { - int len = str.length(); - int index = 0; - char tokChar = str.charAt(index); - while (!Character.isLetter(tokChar) && index < len - 1) - { - tokChar = str.charAt(++index); - } - if (Character.isLetter(tokChar)) - { - return tokChar; - } - return 0; - } - - private static String loadTemplate(File f) - { - try - { - StringBuffer sb = new StringBuffer(); - FileReader fr = new FileReader(f); - LineNumberReader lnr = new LineNumberReader(fr); - String line = lnr.readLine(); - while (line != null) - { - - sb.append(line); - sb.append(Utils.LINE_SEPARATOR); - - line = lnr.readLine(); - } - lnr.close(); - fr.close(); - return sb.toString(); - } - catch (FileNotFoundException e) - { - throw new AmqpTemplateException("File not found: " + e.getMessage()); - } - catch (IOException e) - { - throw new AmqpTemplateException("IOException: " + e.getMessage()); - } - } - - public String getDomainType(String domainName, AmqpVersion version) - { - if (version == null) - { - version = _versionSet.first(); - } - return getDomainMap().getDomainType(domainName, version); - } - - - public void addFromNode(Node amqpNode, AmqpVersion version) - { - // 1c. Extract domains - getConstantSet().addFromNode(amqpNode, 0, version); - _versionToConstantSetMap.get(version).addFromNode(amqpNode, 0, version); - - // 1d. Extract domains - getDomainMap().addFromNode(amqpNode, 0, version); - _versionToDomainMapMap.get(version).addFromNode(amqpNode, 0, version); - - // 1e. Extract class/method/field heirarchy - getModel().addFromNode(amqpNode, 0, version); - _versionToModelMap.get(version).addFromNode(amqpNode, 0, version); - } - - - public String getOutputDirectory() - { - return _outputDirectory; - } - - public String prepareConstantName(String constantName) - { - return prepareDomainName(constantName); - } - - - public boolean isFixedSizeType(String type) - { - return FIXED_SIZE_TYPES.containsKey(type); - } - - - public int getTypeSize(String type) - { - return FIXED_SIZE_TYPES.get(type); - } - - - - // Model-level template processing - abstract protected void processModelTemplate(NamedTemplate template); - - // Class-level template processing - abstract protected void processClassTemplate(NamedTemplate template, AmqpClass thisClass); - - // Method-level template processing - abstract protected void processMethodTemplate(NamedTemplate template, AmqpClass thisClass, - AmqpMethod method); - - // Field-level template processing - abstract protected void processTemplate(NamedTemplate template, AmqpClass thisClass, - AmqpMethod method, AmqpField field, AmqpVersion version); - - abstract protected String prepareFilename(String filenameTemplate, AmqpClass thisClass, AmqpMethod method, - AmqpField field, AmqpVersion version); - - abstract protected String processToken(String token, AmqpClass thisClass, AmqpMethod method, - AmqpField field, AmqpVersion version); - - abstract protected void processClassList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, - AmqpModel model, AmqpVersion version); - - abstract protected void processMethodList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, - AmqpClass thisClass); - - - abstract protected void processFieldList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, - AmqpFieldMap fieldMap, AmqpVersion version); - - abstract protected void processConstantList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, - AmqpConstantSet constantSet); - - -} diff --git a/gentools/src/org/apache/qpid/gentools/JavaGenerator.java b/gentools/src/org/apache/qpid/gentools/JavaGenerator.java deleted file mode 100644 index 7730fca1bd..0000000000 --- a/gentools/src/org/apache/qpid/gentools/JavaGenerator.java +++ /dev/null @@ -1,1826 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.io.File; -import java.util.Iterator; -import java.util.List; -import java.util.TreeMap; - -public class JavaGenerator extends Generator -{ - // TODO: Move this to parent class - protected static final int FIELD_NAME = 0; - protected static final int FIELD_CODE_TYPE = 1; - - private class DomainInfo - { - final public String type; - final public String size; - final public String encodingType; - final public String encodeExpression; - final public String decodeExpression; - - public DomainInfo(String domain, String size, String encodingType, String encodeExpression, String decodeExpression) - { - this.type = domain; - this.size = size; - this.encodeExpression = encodeExpression; - this.decodeExpression = decodeExpression; - this.encodingType = encodingType; - } - } - - private static TreeMap<String, DomainInfo> typeMap = new TreeMap<String, DomainInfo>(); - - // Methods used for generation of code snippets called from the field map parsers - - // Common methods - private final CommandGenerateMethod declarationGenerateMethod = new CommandGenerateMethod() - { - public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) - { - return generateFieldDeclaration(codeType, field, versionSet, indentSize, tabSize, notLast); - } - }; - - private MangledGenerateMethod mangledDeclarationGenerateMethod = new MangledGenerateMethod() - { - public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) - { - return generateMangledFieldDeclaration(field, indentSize, tabSize, notLast); - } - }; - - // Methods for MessageBody classes - private CommandGenerateMethod mbGetGenerateMethod = new CommandGenerateMethod() - { - public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) - { - return generateMbGetMethod(codeType, field, versionSet, indentSize, tabSize, notLast); //To change body of implemented methods use File | Settings | File Templates. - } - }; - - private MangledGenerateMethod mbMangledGetGenerateMethod = new MangledGenerateMethod() - { - public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) - { - return generateMbMangledGetMethod(field, indentSize, tabSize, notLast); - } - }; - private CommandGenerateMethod mbParamListGenerateMethod = new CommandGenerateMethod() - { - public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) - { - return generateMbParamList(codeType, field, versionSet, indentSize, tabSize, notLast); - } - }; - private CommandGenerateMethod mbPassedParamListGenerateMethod = new CommandGenerateMethod() - { - public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) - { - return generateMbPassedParamList(codeType, field, versionSet, indentSize, tabSize, notLast); - } - }; - private MangledGenerateMethod mbMangledParamListGenerateMethod = new MangledGenerateMethod() - { - public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) - { - return generateMbMangledParamList(field, indentSize, tabSize, notLast); - } - }; - private MangledGenerateMethod mbMangledPassedParamListGenerateMethod = new MangledGenerateMethod() - { - public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) - { - return generateMbMangledPassedParamList(field, indentSize, tabSize, notLast); - } - }; - private CommandGenerateMethod mbBodyInitGenerateMethod = new CommandGenerateMethod() - { - public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) - { - return generateMbBodyInit(codeType, field, versionSet, indentSize, tabSize, notLast); - } - }; - private MangledGenerateMethod mbMangledBodyInitGenerateMethod = new MangledGenerateMethod() - { - public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) - { - return generateMbMangledBodyInit(field, indentSize, tabSize, notLast); - } - }; - private GenerateMethod mbSizeGenerateMethod = new GenerateMethod() - { - public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) - { - return generateMbFieldSize(domainType, fieldName, ordinal, indentSize, tabSize); - } - }; - private BitFieldGenerateMethod mbBitSizeGenerateMethod = new BitFieldGenerateMethod() - { - public String generate(List<String> bitFieldList, int ordinal, int indentSize, int tabSize) - { - return generateMbBitArrayFieldSize(bitFieldList, ordinal, indentSize, tabSize); - } - }; - private GenerateMethod mbEncodeGenerateMethod = new GenerateMethod() - { - public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) - { - return generateMbFieldEncode(domainType, fieldName, ordinal, indentSize, tabSize); - } - }; - private BitFieldGenerateMethod mbBitEncodeGenerateMethod = new BitFieldGenerateMethod() - { - public String generate(List<String> bitFieldList, int ordinal, int indentSize, int tabSize) - { - return generateMbBitFieldEncode(bitFieldList, ordinal, indentSize, tabSize); - } - }; - private GenerateMethod mbDecodeGenerateMethod = new GenerateMethod() - { - public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) - { - return generateMbFieldDecode(domainType, fieldName, ordinal, indentSize, tabSize); - } - }; - private BitFieldGenerateMethod mbBitDecodeGenerateMethod = new BitFieldGenerateMethod() - { - public String generate(List<String> bitFieldList, int ordinal, int indentSize, int tabSize) - { - return generateMbBitFieldDecode(bitFieldList, ordinal, indentSize, tabSize); - } - }; - private GenerateMethod mbToStringGenerateMethod = new GenerateMethod() - { - public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) - { - return generateMbFieldToString(domainType, fieldName, ordinal, indentSize, tabSize); - } - }; - private BitFieldGenerateMethod mbBitToStringGenerateMethod = new BitFieldGenerateMethod() - { - public String generate(List<String> bitFieldList, int ordinal, int indentSize, int tabSize) - { - return generateMbBitFieldToString(bitFieldList, ordinal, indentSize, tabSize); - } - }; - - // Methods for PropertyContentHeader classes - private CommandGenerateMethod pchClearGenerateMethod = new CommandGenerateMethod() - { - public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) - { - return generatePchClearMethod(codeType, field, versionSet, indentSize, tabSize, notLast); - } - }; - private MangledGenerateMethod pchMangledClearGenerateMethod = new MangledGenerateMethod() - { - public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) - { - return generatePchMangledClearMethod(field, indentSize, tabSize, notLast); - } - }; - private CommandGenerateMethod pchGetGenerateMethod = new CommandGenerateMethod() - { - public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) - { - return generatePchGetMethod(codeType, field, versionSet, indentSize, tabSize, notLast); - } - }; - private MangledGenerateMethod pchMangledGetGenerateMethod = new MangledGenerateMethod() - { - public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) - { - return generatePchMangledGetMethod(field, indentSize, tabSize, notLast); - } - }; - private CommandGenerateMethod pchSetGenerateMethod = new CommandGenerateMethod() - { - public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) - { - return generatePchSetMethod(codeType, field, versionSet, indentSize, tabSize, notLast); - } - }; - private MangledGenerateMethod pchMangledSetGenerateMethod = new MangledGenerateMethod() - { - public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) - { - return generatePchMangledSetMethod(field, indentSize, tabSize, notLast); - } - }; - private GenerateMethod pchSizeGenerateMethod = new GenerateMethod() - { - public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) - { - return generatePchFieldSize(domainType, fieldName, ordinal, indentSize, tabSize); - } - }; - private BitFieldGenerateMethod pchBitSizeGenerateMethod = new BitFieldGenerateMethod() - { - public String generate(List<String> bitFieldList, int ordinal, int indentSize, int tabSize) - { - return generatePchBitArrayFieldSize(bitFieldList, ordinal, indentSize, tabSize); - } - }; - private GenerateMethod pchEncodeGenerateMethod = new GenerateMethod() - { - public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) - { - return generatePchFieldEncode(domainType, fieldName, ordinal, indentSize, tabSize); - } - }; - private BitFieldGenerateMethod pchBitEncodeGenerateMethod = new BitFieldGenerateMethod() - { - public String generate(List<String> bitFieldList, int ordinal, int indentSize, int tabSize) - { - return generatePchBitFieldEncode(bitFieldList, ordinal, indentSize, tabSize); - } - }; - private GenerateMethod pchDecodeGenerateMethod = new GenerateMethod() - { - public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) - { - return generatePchFieldDecode(domainType, fieldName, ordinal, indentSize, tabSize); - } - }; - private BitFieldGenerateMethod pchBitDecodeGenerateMethod = new BitFieldGenerateMethod() - { - public String generate(List<String> bitFieldList, int ordinal, int indentSize, int tabSize) - { - return generatePchBitFieldDecode(bitFieldList, ordinal, indentSize, tabSize); - } - }; - private GenerateMethod pchGetPropertyFlagsGenerateMethod = new GenerateMethod() - { - public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) - { - return generatePchGetPropertyFlags(domainType, fieldName, ordinal, indentSize, tabSize); - } - }; - private BitFieldGenerateMethod pchBitGetPropertyFlagsGenerateMethod = new BitFieldGenerateMethod() - { - public String generate(List<String> bitFieldList, int ordinal, int indentSize, int tabSize) - { - return generatePchBitGetPropertyFlags(bitFieldList, ordinal, indentSize, tabSize); - } - }; - private GenerateMethod pchSetPropertyFlagsGenerateMethod = new GenerateMethod() - { - public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) - { - return generatePchSetPropertyFlags(domainType, fieldName, ordinal, indentSize, tabSize); - } - }; - private BitFieldGenerateMethod pchBitSetPropertyFlagsGenerateMethod = new BitFieldGenerateMethod() - { - public String generate(List<String> bitFieldList, int ordinal, int indentSize, int tabSize) - { - return generatePchBitSetPropertyFlags(bitFieldList, ordinal, indentSize, tabSize); - } - }; - - - public String getNativeType(String type) - { - return typeMap.get(type).type; - } - - public String getEncodingType(String type) - { - return typeMap.get(type).encodingType; - } - - - public JavaGenerator() - { - super(); - // Load Java type and size maps. - // Adjust or add to these lists as new types are added/defined. - // The char '#' will be replaced by the field variable name (any type). - // The char '~' will be replaced by the compacted bit array size (type bit only). - typeMap.put("bit", new DomainInfo( - "boolean", // Java code type - "~", // size - "Boolean", // Java code type - "EncodingUtils.writeBooleans(buffer, #)", // encode expression - "# = EncodingUtils.readBooleans(buffer)")); // decode expression - typeMap.put("bitfield", new DomainInfo( - "byte", // Java code type - "~", // size - "Bitfield", - "EncodingUtils.writeBooleans(buffer, #)", // encode expression - "# = EncodingUtils.readBooleans(buffer)")); // decode expression - - typeMap.put("content", new DomainInfo( - "Content", // Java code type - "EncodingUtils.encodedContentLength(#)", // size - "Content", // Java code type - "EncodingUtils.writeContentBytes(buffer, #)", // encode expression - "# = EncodingUtils.readContent(buffer)")); // decode expression - typeMap.put("long", new DomainInfo( - "long", // Java code type - "4", // size - "UnsignedInteger", // Java code type - "EncodingUtils.writeUnsignedInteger(buffer, #)", // encode expression - "# = buffer.getUnsignedInt()")); // decode expression - typeMap.put("longlong", new DomainInfo( - "long", // Java code type - "8", // size - "Long", - "buffer.putLong(#)", // encode expression - "# = buffer.getLong()")); // decode expression - typeMap.put("longstr", new DomainInfo( - "byte[]", // Java code type - "EncodingUtils.encodedLongstrLength(#)", // size - "Bytes", - "EncodingUtils.writeLongStringBytes(buffer, #)", // encode expression - "# = EncodingUtils.readLongstr(buffer)")); // decode expression - typeMap.put("octet", new DomainInfo( - "short", // Java code type - "1", // size - "UnsignedByte", - "EncodingUtils.writeUnsignedByte(buffer, #)", // encode expression - "# = buffer.getUnsigned()")); // decode expression - typeMap.put("short", new DomainInfo( - "int", // Java code type - "2", // size - "UnsignedShort", - "EncodingUtils.writeUnsignedShort(buffer, #)", // encode expression - "# = buffer.getUnsignedShort()")); // decode expression - typeMap.put("shortstr", new DomainInfo( - "AMQShortString", // Java code type - "EncodingUtils.encodedShortStringLength(#)", // size - "AMQShortString", // Java code type - "EncodingUtils.writeShortStringBytes(buffer, #)", // encode expression - "# = EncodingUtils.readAMQShortString(buffer)")); // decode expression - typeMap.put("table", new DomainInfo( - "FieldTable", // Java code type - "EncodingUtils.encodedFieldTableLength(#)", // size - "FieldTable", // Java code type - "EncodingUtils.writeFieldTableBytes(buffer, #)", // encode expression - "# = EncodingUtils.readFieldTable(buffer)")); // decode expression - typeMap.put("timestamp", new DomainInfo( - "long", // Java code type - "8", // size - "Timestamp", - "EncodingUtils.writeTimestamp(buffer, #)", // encode expression - "# = EncodingUtils.readTimestamp(buffer)")); // decode expression - } - - // === Start of methods for Interface LanguageConverter === - - public String prepareClassName(String className) - { - return camelCaseName(className, true); - } - - public String prepareMethodName(String methodName) - { - return camelCaseName(methodName, false); - } - - public String prepareDomainName(String domainName) - { - return camelCaseName(domainName, false); - } - - - public String getGeneratedType(String domainName, AmqpVersion version) - { - String domainType = getDomainType(domainName, version); - if (domainType == null) - { - throw new AmqpTypeMappingException("Domain type \"" + domainName + - "\" not found in Java typemap."); - } - DomainInfo info = typeMap.get(domainType); - if (info == null) - { - throw new AmqpTypeMappingException("Unknown domain: \"" + domainType + "\""); - } - return info.type; - } - - // === Abstract methods from class Generator - Java-specific implementations === - - @Override - protected String prepareFilename(String filenameTemplate, AmqpClass thisClass, AmqpMethod method, - AmqpField field, AmqpVersion version) - { - StringBuffer sb = new StringBuffer(filenameTemplate); - if (thisClass != null) - { - replaceToken(sb, "${CLASS}", thisClass.getName()); - } - if (method != null) - { - replaceToken(sb, "${METHOD}", method.getName()); - } - if (field != null) - { - replaceToken(sb, "${FIELD}", field.getName()); - } - if (version != null) - { - replaceToken(sb, "${MAJOR}", String.valueOf(version.getMajor())); - replaceToken(sb, "${MINOR}", String.valueOf(version.getMinor())); - } - return sb.toString(); - } - - @Override - protected void processModelTemplate(NamedTemplate template) - { - processTemplate(template, null, null, null, null); - } - - @Override - protected void processClassTemplate(NamedTemplate template, AmqpClass thisClass) - { - processTemplate(template, thisClass, null, null, - thisClass.getVersionSet().size() == 1 ? thisClass.getVersionSet().first() : null); - } - - @Override - protected void processMethodTemplate(NamedTemplate template, AmqpClass thisClass, - AmqpMethod method) - { - processTemplate(template, thisClass, method, null, - thisClass.getVersionSet().size() == 1 ? thisClass.getVersionSet().first() : null); - } - - protected void processFieldTemplate(NamedTemplate template, AmqpClass thisClass, - AmqpMethod method, AmqpField field) - { - processTemplate(template, thisClass, method, field, - thisClass.getVersionSet().size() == 1 ? thisClass.getVersionSet().first() : null); - } - - @Override - protected void processTemplate(NamedTemplate template, AmqpClass thisClass, - AmqpMethod method, AmqpField field, AmqpVersion version) - { - StringBuffer sb = new StringBuffer(template.getTemplate()); - String filename = prepareFilename(getTemplateFileName(sb), thisClass, method, field, version); - processTemplate(sb, thisClass, method, field, template.getName(), version); - writeTargetFile(sb, new File(getOutputDirectory() + Utils.FILE_SEPARATOR + filename)); - generatedFileCounter++; - } - - protected void processTemplate(StringBuffer sb, AmqpClass thisClass, AmqpMethod method, - AmqpField field, String templateFileName, AmqpVersion version) - { - try - { - processAllLists(sb, thisClass, method, version); - } - catch (AmqpTemplateException e) - { - System.out.println("WARNING: " + templateFileName + ": " + e.getMessage()); - } - try - { - processAllTokens(sb, thisClass, method, field, version); - } - catch (AmqpTemplateException e) - { - System.out.println("WARNING: " + templateFileName + ": " + e.getMessage()); - } - } - - @Override - protected String processToken(String token, AmqpClass thisClass, AmqpMethod method, AmqpField field, - AmqpVersion version) - { - if (token.compareTo("${GENERATOR}") == 0) - { - return GENERATOR_INFO; - } - if (token.compareTo("${CLASS}") == 0 && thisClass != null) - { - return thisClass.getName(); - } - if (token.compareTo("${CLASS_ID_INIT}") == 0 && thisClass != null) - { - return generateIndexInitializer("registerClassId", thisClass.getIndexMap(), 8); - } - if (token.compareTo("${METHOD}") == 0 && method != null) - { - return method.getName(); - } - if (token.compareTo("${METHOD_ID_INIT}") == 0 && method != null) - { - return generateIndexInitializer("registerMethodId", method.getIndexMap(), 8); - } - if (token.compareTo("${FIELD}") == 0 && field != null) - { - return field.getName(); - } - - // This token is used only with class or method-level templates - if (token.compareTo("${pch_property_flags_declare}") == 0) - { - return generatePchPropertyFlagsDeclare(); - } - else if (token.compareTo("${pch_property_flags_initializer}") == 0) - { - int mapSize = method == null ? thisClass.getFieldMap().size() : method.getFieldMap().size(); - return generatePchPropertyFlagsInitializer(mapSize); - } - else if (token.compareTo("${pch_compact_property_flags_initializer}") == 0) - { - return generatePchCompactPropertyFlagsInitializer(thisClass, 8, 4); - } - else if (token.compareTo("${pch_compact_property_flags_check}") == 0) - { - return generatePchCompactPropertyFlagsCheck(thisClass, 8, 4); - } - - // Oops! - throw new AmqpTemplateException("Template token " + token + " unknown."); - } - - @Override - protected void processClassList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, - AmqpModel model, AmqpVersion version) - { - String codeSnippet; - int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line - String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr - int tokStart = tline.indexOf('$'); - String token = tline.substring(tokStart).trim(); - sb.delete(listMarkerStartIndex, lend); - - if (token.compareTo("${reg_map_put_method}") == 0) - { - codeSnippet = generateRegistry(model, 8, 4); - } - - else // Oops! - { - throw new AmqpTemplateException("Template token " + token + " unknown."); - } - - sb.insert(listMarkerStartIndex, codeSnippet); - } - - @Override - protected void processMethodList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, - AmqpClass thisClass) - { - String codeSnippet; - int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line - String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr - int tokStart = tline.indexOf('$'); - String token = tline.substring(tokStart).trim(); - sb.delete(listMarkerStartIndex, lend); - - //TODO - we don't have any cases of this (yet). - if (token.compareTo("${???}") == 0) - { - codeSnippet = token; - } - else // Oops! - { - throw new AmqpTemplateException("Template token " + token + " unknown."); - } - - sb.insert(listMarkerStartIndex, codeSnippet); - } - - @Override - protected void processFieldList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, - AmqpFieldMap fieldMap, AmqpVersion version) - { - String codeSnippet; - int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line - String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr - int tokStart = tline.indexOf('$'); - String token = tline.substring(tokStart).trim(); - sb.delete(listMarkerStartIndex, lend); - - // Field declarations - common to MethodBody and PropertyContentHeader classes - if (token.compareTo("${field_declaration}") == 0) - { - codeSnippet = fieldMap.parseFieldMap(declarationGenerateMethod, - mangledDeclarationGenerateMethod, 4, 4, this); - } - - // MethodBody classes - else if (token.compareTo("${mb_field_get_method}") == 0) - { - codeSnippet = fieldMap.parseFieldMap(mbGetGenerateMethod, - mbMangledGetGenerateMethod, 4, 4, this); - } - else if (token.compareTo("${mb_field_parameter_list}") == 0) - { - // <cringe> The code generated by this is ugly... It puts a comma on a line by itself! - // TODO: Find a more elegant solution here sometime... - codeSnippet = fieldMap.size() > 0 ? Utils.createSpaces(42) + "," + CR : ""; - // </cringe> - codeSnippet += fieldMap.parseFieldMap(mbParamListGenerateMethod, - mbMangledParamListGenerateMethod, 42, 4, this); - } - - else if (token.compareTo("${mb_field_passed_parameter_list}") == 0) - { - // <cringe> The code generated by this is ugly... It puts a comma on a line by itself! - // TODO: Find a more elegant solution here sometime... - codeSnippet = fieldMap.size() > 0 ? Utils.createSpaces(42) + "," + CR : ""; - // </cringe> - codeSnippet += fieldMap.parseFieldMap(mbPassedParamListGenerateMethod, - mbMangledPassedParamListGenerateMethod, 42, 4, this); - } - else if (token.compareTo("${mb_field_body_initialize}") == 0) - { - codeSnippet = fieldMap.parseFieldMap(mbBodyInitGenerateMethod, - mbMangledBodyInitGenerateMethod, 8, 4, this); - } - else if (token.compareTo("${mb_field_size}") == 0) - { - codeSnippet = fieldMap.parseFieldMapOrdinally(mbSizeGenerateMethod, - mbBitSizeGenerateMethod, 8, 4, this); - } - else if (token.compareTo("${mb_field_encode}") == 0) - { - codeSnippet = fieldMap.parseFieldMapOrdinally(mbEncodeGenerateMethod, - mbBitEncodeGenerateMethod, 8, 4, this); - } - else if (token.compareTo("${mb_field_decode}") == 0) - { - codeSnippet = fieldMap.parseFieldMapOrdinally(mbDecodeGenerateMethod, - mbBitDecodeGenerateMethod, 8, 4, this); - } - else if (token.compareTo("${mb_field_to_string}") == 0) - { - codeSnippet = fieldMap.parseFieldMapOrdinally(mbToStringGenerateMethod, - mbBitToStringGenerateMethod, 8, 4, this); - } - - // PropertyContentHeader classes - else if (token.compareTo("${pch_field_list_size}") == 0) - { - codeSnippet = fieldMap.parseFieldMapOrdinally(pchSizeGenerateMethod, - pchBitSizeGenerateMethod, 12, 4, this); - } - else if (token.compareTo("${pch_field_list_payload}") == 0) - { - codeSnippet = fieldMap.parseFieldMapOrdinally(pchEncodeGenerateMethod, - pchBitEncodeGenerateMethod, 12, 4, this); - } - else if (token.compareTo("${pch_field_list_decode}") == 0) - { - codeSnippet = fieldMap.parseFieldMapOrdinally(pchDecodeGenerateMethod, - pchBitDecodeGenerateMethod, 12, 4, this); - } - else if (token.compareTo("${pch_get_compact_property_flags}") == 0) - { - codeSnippet = fieldMap.parseFieldMapOrdinally(pchGetPropertyFlagsGenerateMethod, - pchBitGetPropertyFlagsGenerateMethod, 8, 4, this); - } - else if (token.compareTo("${pch_set_compact_property_flags}") == 0) - { - codeSnippet = fieldMap.parseFieldMapOrdinally(pchSetPropertyFlagsGenerateMethod, - pchBitSetPropertyFlagsGenerateMethod, 8, 4, this); - } - else if (token.compareTo("${pch_field_clear_methods}") == 0) - { - codeSnippet = fieldMap.parseFieldMap(pchClearGenerateMethod, - pchMangledClearGenerateMethod, 4, 4, this); - } - else if (token.compareTo("${pch_field_get_methods}") == 0) - { - codeSnippet = fieldMap.parseFieldMap(pchGetGenerateMethod, - pchMangledGetGenerateMethod, 4, 4, this); - } - else if (token.compareTo("${pch_field_set_methods}") == 0) - { - codeSnippet = fieldMap.parseFieldMap(pchSetGenerateMethod, - pchMangledSetGenerateMethod, 4, 4, this); - } - - else // Oops! - { - throw new AmqpTemplateException("Template token " + token + " unknown."); - } - sb.insert(listMarkerStartIndex, codeSnippet); - } - - @Override - protected void processConstantList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, - AmqpConstantSet constantSet) - { - String codeSnippet; - int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line - String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr - int tokStart = tline.indexOf('$'); - String token = tline.substring(tokStart).trim(); - sb.delete(listMarkerStartIndex, lend); - - if (token.compareTo("${const_get_method}") == 0) - { - codeSnippet = generateConstantGetMethods(constantSet, 4, 4); - } - - else // Oops! - { - throw new AmqpTemplateException("Template token " + token + " unknown."); - } - - sb.insert(listMarkerStartIndex, codeSnippet); - } - - // === Protected and private helper functions unique to Java implementation === - - // Methods used for generation of code snippets called from the field map parsers - - // Common methods - - protected String generateFieldDeclaration(String codeType, AmqpField field, - AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) - { - return Utils.createSpaces(indentSize) + "public " + codeType + " " + field.getName() + - "; // AMQP version(s): " + versionSet + CR; - } - - protected String generateMangledFieldDeclaration(AmqpField field, int indentSize, - int tabSize, boolean nextFlag) - { - StringBuffer sb = new StringBuffer(); - Iterator<String> dItr = field.getDomainMap().keySet().iterator(); - int domainCntr = 0; - while (dItr.hasNext()) - { - String domainName = dItr.next(); - AmqpVersionSet versionSet = field.getDomainMap().get(domainName); - String codeType = getGeneratedType(domainName, versionSet.first()); - sb.append(Utils.createSpaces(indentSize) + "public " + codeType + " " + - field.getName() + "_" + (domainCntr++) + "; // AMQP Version(s): " + versionSet + - CR); - } - return sb.toString(); - } - - protected String generateIndexInitializer(String mapName, AmqpOrdinalVersionMap indexMap, int indentSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - - Iterator<Integer> iItr = indexMap.keySet().iterator(); - while (iItr.hasNext()) - { - int index = iItr.next(); - AmqpVersionSet versionSet = indexMap.get(index); - Iterator<AmqpVersion> vItr = versionSet.iterator(); - while (vItr.hasNext()) - { - AmqpVersion version = vItr.next(); - sb.append(indent + mapName + "( (byte) " + version.getMajor() + ", (byte) " + version.getMinor() + ", " + index + ");" + CR); - } - } - return sb.toString(); - } - - protected String generateRegistry(AmqpModel model, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - - for (String className : model.getClassMap().keySet()) - { - AmqpClass thisClass = model.getClassMap().get(className); - for (String methodName : thisClass.getMethodMap().keySet()) - { - AmqpMethod method = thisClass.getMethodMap().get(methodName); - for (AmqpVersion version : model.getVersionSet()) - { - // Find class and method index for this version (if it exists) - try - { - int classIndex = findIndex(thisClass.getIndexMap(), version); - int methodIndex = findIndex(method.getIndexMap(), version); - sb.append(indent + "registerMethod(" + CR); - sb.append(indent + tab + "(short)" + classIndex + - ", (short)" + methodIndex + ", (byte)" + version.getMajor() + - ", (byte)" + version.getMinor() + ", " + CR); - sb.append(indent + tab + Utils.firstUpper(thisClass.getName()) + - Utils.firstUpper(method.getName()) + "Body.getFactory());" + CR); - } - catch (Exception e) - { - } // Ignore - } - } - } - return sb.toString(); - } - - protected int findIndex(TreeMap<Integer, AmqpVersionSet> map, AmqpVersion version) - { - Iterator<Integer> iItr = map.keySet().iterator(); - while (iItr.hasNext()) - { - int index = iItr.next(); - AmqpVersionSet versionSet = map.get(index); - if (versionSet.contains(version)) - { - return index; - } - } - throw new IllegalArgumentException("Index not found"); - } - - // Methods for AmqpConstants class - - - public String prepareConstantName(String constantName) - { - return upperCaseName(constantName); - } - - - protected String generateConstantGetMethods(AmqpConstantSet constantSet, - int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - - for (AmqpConstant constant : constantSet.getContstants()) - { - - if (constant.isVersionConsistent(constantSet.getVersionSet())) - { - // return a constant - String value = constant.firstKey(); - if (Utils.containsOnlyDigits(value)) - { - sb.append(indent + "public static final int " + constant.getName() + " = " + - constant.firstKey() + ";" + CR); - } - else if (Utils.containsOnlyDigitsAndDecimal(value)) - { - sb.append(indent + "public static double " + constant.getName() + " = " + - constant.firstKey() + "; " + CR); - } - else - { - sb.append(indent + "public static String " + constant.getName() + " = " + - constant.firstKey() + "\"; " + CR); - - } - sb.append(CR); - } - else - { - // Return version-specific constant - sb.append(generateVersionDependentGet(constant, "String", "", "\"", "\"", indentSize, tabSize)); - sb.append(generateVersionDependentGet(constant, "int", "AsInt", "", "", indentSize, tabSize)); - sb.append(generateVersionDependentGet(constant, "double", "AsDouble", "(double)", "", indentSize, tabSize)); - sb.append(CR); - } - } - return sb.toString(); - } - - protected String generateVersionDependentGet(AmqpConstant constant, - String methodReturnType, String methodNameSuffix, String returnPrefix, String returnPostfix, - int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - sb.append(indent + "public static " + methodReturnType + " " + constant.getName() + - methodNameSuffix + "(byte major, byte minor) throws AMQProtocolVersionException" + CR); - sb.append(indent + "{" + CR); - boolean first = true; - Iterator<String> sItr = constant.keySet().iterator(); - while (sItr.hasNext()) - { - String value = sItr.next(); - AmqpVersionSet versionSet = constant.get(value); - sb.append(indent + tab + (first ? "" : "else ") + "if (" + generateVersionCheck(versionSet) + - ")" + CR); - sb.append(indent + tab + "{" + CR); - if (methodReturnType.compareTo("int") == 0 && !Utils.containsOnlyDigits(value)) - { - sb.append(generateConstantDeclarationException(constant.getName(), methodReturnType, - indentSize + (2 * tabSize), tabSize)); - } - else if (methodReturnType.compareTo("double") == 0 && !Utils.containsOnlyDigitsAndDecimal(value)) - { - sb.append(generateConstantDeclarationException(constant.getName(), methodReturnType, - indentSize + (2 * tabSize), tabSize)); - } - else - { - sb.append(indent + tab + tab + "return " + returnPrefix + value + returnPostfix + ";" + CR); - } - sb.append(indent + tab + "}" + CR); - first = false; - } - sb.append(indent + tab + "else" + CR); - sb.append(indent + tab + "{" + CR); - sb.append(indent + tab + tab + "throw new AMQProtocolVersionException(\"Constant \\\"" + - constant.getName() + "\\\" \" +" + CR); - sb.append(indent + tab + tab + tab + - "\"is undefined for AMQP version \" + major + \"-\" + minor + \".\");" + CR); - sb.append(indent + tab + "}" + CR); - sb.append(indent + "}" + CR); - return sb.toString(); - } - - protected String generateConstantDeclarationException(String name, String methodReturnType, - int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - sb.append(indent + "throw new AMQProtocolVersionException(\"Constant \\\"" + - name + "\\\" \" +" + CR); - sb.append(indent + tab + "\"cannot be converted to type " + methodReturnType + - " for AMQP version \" + major + \"-\" + minor + \".\");" + CR); - return sb.toString(); - } - - // Methods for MessageBody classes - protected String generateMbGetMethod(String codeType, AmqpField field, - AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) - { - return Utils.createSpaces(indentSize) + "public " + codeType + " get" + - Utils.firstUpper(field.getName()) + "() { return " + field.getName() + "; }" + - CR; - } - - protected String generateMbMangledGetMethod(AmqpField field, int indentSize, - int tabSize, boolean nextFlag) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(CR); - sb.append(indent + "public <T> T get" + Utils.firstUpper(field.getName()) + - "(Class<T> classObj) throws AMQProtocolVersionException" + CR); - sb.append(indent + "{" + CR); - Iterator<String> dItr = field.getDomainMap().keySet().iterator(); - int domainCntr = 0; - while (dItr.hasNext()) - { - String domainName = dItr.next(); - AmqpVersionSet versionSet = field.getDomainMap().get(domainName); - String codeType = getGeneratedType(domainName, versionSet.first()); - sb.append(indent + tab + "if (classObj.equals(" + codeType + - ".class)) // AMQP Version(s): " + versionSet + CR); - sb.append(indent + tab + tab + "return (T)(Object)" + field.getName() + "_" + - (domainCntr++) + ";" + CR); - } - sb.append(indent + tab + - "throw new AMQProtocolVersionException(\"None of the AMQP versions defines \" +" + - CR + " \"field \\\"" + field.getName() + - "\\\" as domain \\\"\" + classObj.getName() + \"\\\".\");" + CR); - sb.append(indent + "}" + CR); - sb.append(CR); - return sb.toString(); - } - - protected String generateMbParamList(String codeType, AmqpField field, - AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) - { - return Utils.createSpaces(indentSize) + codeType + " " + field.getName() + - (nextFlag ? "," : "") + " // AMQP version(s): " + versionSet + CR; - } - - - protected String generateMbPassedParamList(String codeType, AmqpField field, - AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) - { - return Utils.createSpaces(indentSize) + field.getName() + - (nextFlag ? "," : "") + " // AMQP version(s): " + versionSet + CR; - } - - - protected String generateMbMangledParamList(AmqpField field, int indentSize, - int tabSize, boolean nextFlag) - { - StringBuffer sb = new StringBuffer(); - Iterator<String> dItr = field.getDomainMap().keySet().iterator(); - int domainCntr = 0; - while (dItr.hasNext()) - { - String domainName = dItr.next(); - AmqpVersionSet versionSet = field.getDomainMap().get(domainName); - String codeType = getGeneratedType(domainName, versionSet.first()); - sb.append(Utils.createSpaces(indentSize) + codeType + " " + field.getName() + "_" + - (domainCntr++) + (nextFlag ? "," : "") + " // AMQP version(s): " + - versionSet + CR); - } - return sb.toString(); - } - - protected String generateMbMangledPassedParamList(AmqpField field, int indentSize, - int tabSize, boolean nextFlag) - { - StringBuffer sb = new StringBuffer(); - Iterator<String> dItr = field.getDomainMap().keySet().iterator(); - int domainCntr = 0; - while (dItr.hasNext()) - { - String domainName = dItr.next(); - AmqpVersionSet versionSet = field.getDomainMap().get(domainName); - sb.append(Utils.createSpaces(indentSize) + field.getName() + "_" + - (domainCntr++) + (nextFlag ? "," : "") + " // AMQP version(s): " + - versionSet + CR); - } - return sb.toString(); - } - - - protected String generateMbBodyInit(String codeType, AmqpField field, - AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) - { - return Utils.createSpaces(indentSize) + "this." + field.getName() + " = " + field.getName() + - ";" + CR; - } - - protected String generateMbMangledBodyInit(AmqpField field, int indentSize, - int tabSize, boolean nextFlag) - { - StringBuffer sb = new StringBuffer(); - Iterator<String> dItr = field.getDomainMap().keySet().iterator(); - int domainCntr = 0; - while (dItr.hasNext()) - { - dItr.next(); - sb.append(Utils.createSpaces(indentSize) + "this." + field.getName() + "_" + domainCntr + - " = " + field.getName() + "_" + (domainCntr++) + ";" + CR); - } - return sb.toString(); - } - - protected String generateMbFieldSize(String domainType, String fieldName, - int ordinal, int indentSize, int tabSize) - { - StringBuffer sb = new StringBuffer(); - sb.append(Utils.createSpaces(indentSize) + "size += " + - typeMap.get(domainType).size.replaceAll("#", fieldName) + - "; // " + fieldName + ": " + domainType + CR); - return sb.toString(); - } - - protected String generateMbBitArrayFieldSize(List<String> bitFieldList, - int ordinal, int indentSize, int tabSize) - { - StringBuffer sb = new StringBuffer(); - int numBytes = ((bitFieldList.size() - 1) / 8) + 1; - String comment = bitFieldList.size() == 1 ? - bitFieldList.get(0) + ": bit" : - "Combinded bits: " + bitFieldList; - sb.append(Utils.createSpaces(indentSize) + "size += " + - typeMap.get("bit").size.replaceAll("~", String.valueOf(numBytes)) + - "; // " + comment + CR); - return sb.toString(); - } - - protected String generateMbFieldEncode(String domain, String fieldName, - int ordinal, int indentSize, int tabSize) - { - StringBuffer sb = new StringBuffer(); - sb.append(Utils.createSpaces(indentSize) + - typeMap.get(domain).encodeExpression.replaceAll("#", fieldName) + - "; // " + fieldName + ": " + domain + CR); - return sb.toString(); - } - - protected String generateMbBitFieldEncode(List<String> bitFieldList, - int ordinal, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - - StringBuilder sb = new StringBuilder(); - int i = 0; - while (i < bitFieldList.size()) - { - - StringBuilder line = new StringBuilder(); - - for (int j = 0; i < bitFieldList.size() && j < 8; i++, j++) - { - if (j != 0) - { - line.append(", "); - } - line.append(bitFieldList.get(i)); - } - - sb.append(indent + - typeMap.get("bit").encodeExpression.replaceAll("#", line.toString()) + ";" + CR); - } - return sb.toString(); - } - - protected String generateMbFieldDecode(String domain, String fieldName, - int ordinal, int indentSize, int tabSize) - { - StringBuffer sb = new StringBuffer(); - sb.append(Utils.createSpaces(indentSize) + - typeMap.get(domain).decodeExpression.replaceAll("#", fieldName) + - "; // " + fieldName + ": " + domain + CR); - return sb.toString(); - } - - protected String generateMbBitFieldDecode(List<String> bitFieldList, - int ordinal, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - - StringBuilder sb = new StringBuilder(indent); - sb.append("byte packedValue;"); - sb.append(CR); - - // RG HERE! - - int i = 0; - while (i < bitFieldList.size()) - { - sb.append(indent + "packedValue = EncodingUtils.readByte(buffer);" + CR); - - for (int j = 0; i < bitFieldList.size() && j < 8; i++, j++) - { - sb.append(indent + bitFieldList.get(i) + " = ( packedValue & (byte) (1 << " + j + ") ) != 0;" + CR); - } - } - return sb.toString(); - } - - protected String generateMbFieldToString(String domain, String fieldName, - int ordinal, int indentSize, int tabSize) - { - StringBuffer sb = new StringBuffer(); - sb.append(Utils.createSpaces(indentSize) + - "buf.append(\" " + fieldName + ": \" + " + fieldName + ");" + CR); - return sb.toString(); - } - - protected String generateMbBitFieldToString(List<String> bitFieldList, - int ordinal, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < bitFieldList.size(); i++) - { - String bitFieldName = bitFieldList.get(i); - sb.append(indent + "buf.append(\" " + bitFieldName + ": \" + " + bitFieldName + - ");" + CR); - } - return sb.toString(); - } - - // Methods for PropertyContentHeader classes - - protected String generatePchClearMethod(String codeType, AmqpField field, - AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) - { - // This is one case where the ordinal info is the only significant factor, - // the domain info plays no part. Defer to the mangled version; the code would be - // identical anyway... - return generatePchMangledClearMethod(field, indentSize, tabSize, nextFlag); - } - - protected String generatePchMangledClearMethod(AmqpField field, int indentSize, - int tabSize, boolean nextFlag) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - sb.append(indent + "public void clear" + Utils.firstUpper(field.getName()) + - "()" + CR); - sb.append(indent + "{" + CR); - - // If there is more than one ordinal for this field or the ordinal does not - // apply to all known versions, then we need to generate version checks so - // we know which fieldProperty to clear. - if (field.getOrdinalMap().size() == 1 && - field.getOrdinalMap().get(field.getOrdinalMap().firstKey()).size() == field.getVersionSet().size()) - { - int ordinal = field.getOrdinalMap().firstKey(); - sb.append(indent + tab + "clearEncodedForm();" + CR); - sb.append(indent + tab + "propertyFlags[" + ordinal + "] = false;" + CR); - } - else - { - Iterator<Integer> oItr = field.getOrdinalMap().keySet().iterator(); - while (oItr.hasNext()) - { - int ordinal = oItr.next(); - AmqpVersionSet versionSet = field.getOrdinalMap().get(ordinal); - sb.append(indent + tab); - if (ordinal != field.getOrdinalMap().firstKey()) - { - sb.append("else "); - } - sb.append("if ("); - sb.append(generateVersionCheck(versionSet)); - sb.append(")" + CR); - sb.append(indent + tab + "{" + CR); - sb.append(indent + tab + tab + "clearEncodedForm();" + CR); - sb.append(indent + tab + tab + "propertyFlags[" + ordinal + "] = false;" + CR); - sb.append(indent + tab + "}" + CR); - } - } - sb.append(indent + "}" + CR); - sb.append(CR); - return sb.toString(); - } - - protected String generatePchGetMethod(String codeType, AmqpField field, - AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(indent + "public " + codeType + " get" + - Utils.firstUpper(field.getName()) + "()" + CR); - sb.append(indent + "{" + CR); - sb.append(indent + tab + "decodeIfNecessary();" + CR); - sb.append(indent + tab + "return " + field.getName() + ";" + CR); - sb.append(indent + "}" + CR); - sb.append(CR); - return sb.toString(); - } - - protected String generatePchMangledGetMethod(AmqpField field, int indentSize, - int tabSize, boolean nextFlag) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(indent + "public <T> T get" + - Utils.firstUpper(field.getName()) + - "(Class<T> classObj) throws AMQProtocolVersionException" + CR); - sb.append(indent + "{" + CR); - Iterator<String> dItr = field.getDomainMap().keySet().iterator(); - int domainCntr = 0; - while (dItr.hasNext()) - { - String domainName = dItr.next(); - AmqpVersionSet versionSet = field.getDomainMap().get(domainName); - String codeType = getGeneratedType(domainName, versionSet.first()); - sb.append(indent + tab + "if (classObj.equals(" + codeType + - ".class)) // AMQP Version(s): " + versionSet + CR); - sb.append(indent + tab + "{" + CR); - sb.append(indent + tab + tab + "decodeIfNecessary();" + CR); - sb.append(indent + tab + tab + "return (T)(Object)" + field.getName() + "_" + - (domainCntr++) + ";" + CR); - sb.append(indent + tab + "}" + CR); - } - sb.append(indent + tab + - "throw new AMQProtocolVersionException(\"None of the AMQP versions defines \" +" + - CR + " \"field \\\"" + field.getName() + - "\\\" as domain \\\"\" + classObj.getName() + \"\\\".\");" + CR); - sb.append(indent + "}" + CR); - sb.append(CR); - return sb.toString(); - } - - protected String generatePchSetMethod(String codeType, AmqpField field, - AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - sb.append(indent + "public void set" + Utils.firstUpper(field.getName()) + - "(" + codeType + " " + field.getName() + ")" + CR); - sb.append(indent + "{" + CR); - - // If there is more than one ordinal for this field or the ordinal does not - // apply to all known versions, then we need to generate version checks so - // we know which fieldProperty to clear. - if (field.getOrdinalMap().size() == 1 && - field.getOrdinalMap().get(field.getOrdinalMap().firstKey()).size() == field.getVersionSet().size()) - { - int ordinal = field.getOrdinalMap().firstKey(); - sb.append(indent + tab + "clearEncodedForm();" + CR); - sb.append(indent + tab + "propertyFlags[" + ordinal + "] = true;" + CR); - sb.append(indent + tab + "this." + field.getName() + " = " + field.getName() + ";" + CR); - } - else - { - Iterator<Integer> oItr = field.getOrdinalMap().keySet().iterator(); - while (oItr.hasNext()) - { - int ordinal = oItr.next(); - AmqpVersionSet oVersionSet = field.getOrdinalMap().get(ordinal); - sb.append(indent + tab); - if (ordinal != field.getOrdinalMap().firstKey()) - { - sb.append("else "); - } - sb.append("if ("); - sb.append(generateVersionCheck(oVersionSet)); - sb.append(")" + CR); - sb.append(indent + tab + "{" + CR); - sb.append(indent + tab + tab + "clearEncodedForm();" + CR); - sb.append(indent + tab + tab + "propertyFlags[" + ordinal + "] = true;" + CR); - sb.append(indent + tab + tab + "this." + field.getName() + " = " + field.getName() + ";" + CR); - sb.append(indent + tab + "}" + CR); - } - } - sb.append(indent + "}" + CR); - sb.append(CR); - return sb.toString(); - } - - protected String generatePchMangledSetMethod(AmqpField field, int indentSize, - int tabSize, boolean nextFlag) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - - Iterator<String> dItr = field.getDomainMap().keySet().iterator(); - int domainCntr = 0; - while (dItr.hasNext()) - { - String domainName = dItr.next(); - AmqpVersionSet versionSet = field.getDomainMap().get(domainName); - String codeType = getGeneratedType(domainName, versionSet.first()); - - // Find ordinal with matching version - AmqpVersionSet commonVersionSet = new AmqpVersionSet(); - Iterator<Integer> oItr = field.getOrdinalMap().keySet().iterator(); - while (oItr.hasNext()) - { - int ordinal = oItr.next(); - AmqpVersionSet oVersionSet = field.getOrdinalMap().get(ordinal); - Iterator<AmqpVersion> vItr = oVersionSet.iterator(); - boolean first = true; - while (vItr.hasNext()) - { - AmqpVersion thisVersion = vItr.next(); - if (versionSet.contains(thisVersion)) - { - commonVersionSet.add(thisVersion); - } - } - if (!commonVersionSet.isEmpty()) - { - sb.append(indent + "public void set" + Utils.firstUpper(field.getName()) + - "(" + codeType + " " + field.getName() + ")" + CR); - sb.append(indent + "{" + CR); - sb.append(indent + tab); - if (!first) - { - sb.append("else "); - } - sb.append("if ("); - sb.append(generateVersionCheck(commonVersionSet)); - sb.append(")" + CR); - sb.append(indent + tab + "{" + CR); - sb.append(indent + tab + tab + "clearEncodedForm();" + CR); - sb.append(indent + tab + tab + "propertyFlags[" + ordinal + "] = true;" + CR); - sb.append(indent + tab + tab + "this." + field.getName() + "_" + (domainCntr++) + - " = " + field.getName() + ";" + CR); - sb.append(indent + tab + "}" + CR); - sb.append(indent + "}" + CR); - sb.append(CR); - first = false; - } - } - } - return sb.toString(); - } - - protected String generatePchFieldSize(String domainType, String fieldName, - int ordinal, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(indent + "if (propertyFlags[" + ordinal + "]) // " + - fieldName + ": " + domainType + CR); - sb.append(indent + Utils.createSpaces(tabSize) + "size += " + - typeMap.get(domainType).size.replaceAll("#", fieldName) + ";" + CR); - sb.append(CR); - return sb.toString(); - } - - protected String generatePchBitArrayFieldSize(List<String> bitFieldList, - int ordinal, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - String comment = bitFieldList.size() == 1 ? - bitFieldList.get(0) + ": bit" : - "Combinded bits: " + bitFieldList; - StringBuffer sb = new StringBuffer(); - - if (bitFieldList.size() == 1) // single bit - { - sb.append(indent + "if (propertyFlags[" + (ordinal - 1) + "]) // " + comment + CR); - sb.append(indent + tab + "size += " + - typeMap.get("bit").size.replaceAll("~", "1") + ";" + CR); - } - else // multiple bits - up to 8 are combined into one byte - { - String bitCntrName = "bitCntr_" + ordinal; - int startOrdinal = ordinal - bitFieldList.size(); - sb.append(indent + "// " + comment + CR); - sb.append(indent + "int " + bitCntrName + " = 0;" + CR); - sb.append(indent + "for (int i=" + startOrdinal + "; i<" + ordinal + "; i++)" + CR); - sb.append(indent + "{" + CR); - sb.append(indent + tab + "if (propertyFlags[i])" + CR); - sb.append(indent + tab + tab + bitCntrName + "++;" + CR); - sb.append(indent + "}" + CR); - sb.append(indent + "size += " + - typeMap.get("bit").size.replaceAll("~", bitCntrName + - " > 0 ? ((" + bitCntrName + " - 1) / 8) + 1 : 0") + ";" + CR); - } - sb.append(CR); - return sb.toString(); - } - - protected String generatePchFieldEncode(String domainType, String fieldName, - int ordinal, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - sb.append(indent + "if (propertyFlags[" + ordinal + "]) // " + fieldName + ": " + - domainType + CR); - sb.append(indent + Utils.createSpaces(tabSize) + - typeMap.get(domainType).encodeExpression.replaceAll("#", fieldName) + ";" + CR); - sb.append(CR); - return sb.toString(); - } - - protected String generatePchBitFieldEncode(List<String> bitFieldList, - int ordinal, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - String comment = bitFieldList.size() == 1 ? - bitFieldList.get(0) + ": bit" : - "Combinded bits: " + bitFieldList; - StringBuffer sb = new StringBuffer(); - - if (bitFieldList.size() == 1) // single bit - { - sb.append(indent + "if (propertyFlags[" + (ordinal - 1) + "]) // " + - bitFieldList.get(0) + ": bit" + CR); - sb.append(indent + tab + typeMap.get("bit").encodeExpression.replaceAll("#", - "new boolean[] {" + bitFieldList.get(0) + "}") + ";" + CR); - } - else // multiple bits - up to 8 are combined into one byte - { - int startOrdinal = ordinal - bitFieldList.size(); - String bitCntrName = "bitCntr" + startOrdinal; - sb.append(indent + "// " + comment + CR); - sb.append(indent + "int " + bitCntrName + " = 0;" + CR); - sb.append(indent + "for (int i=" + startOrdinal + "; i<=" + (ordinal - 1) + "; i++)" + CR); - sb.append(indent + "{" + CR); - sb.append(indent + tab + "if (propertyFlags[i])" + CR); - sb.append(indent + tab + tab + bitCntrName + "++;" + CR); - sb.append(indent + "}" + CR); - sb.append(indent + "if (" + bitCntrName + " > 0) // Are any of the property bits set?" + CR); - sb.append(indent + "{" + CR); - sb.append(indent + tab + "boolean[] fullBitArray = new boolean[] { "); - for (int i = 0; i < bitFieldList.size(); i++) - { - if (i != 0) - { - sb.append(", "); - } - sb.append(bitFieldList.get(i)); - } - sb.append(" };" + CR); - sb.append(indent + tab + "boolean[] flaggedBitArray = new boolean[" + bitCntrName + - "];" + CR); - sb.append(indent + tab + bitCntrName + " = 0;" + CR); - sb.append(indent + tab + "for (int i=" + startOrdinal + "; i<=" + (ordinal - 1) + - "; i++)" + CR); - sb.append(indent + tab + "{" + CR); - sb.append(indent + tab + tab + "if (propertyFlags[i])" + CR); - sb.append(indent + tab + tab + tab + "flaggedBitArray[" + bitCntrName + - "++] = fullBitArray[i];" + CR); - sb.append(indent + tab + "}" + CR); - sb.append(indent + tab + typeMap.get("bit").encodeExpression.replaceAll("#", - "flaggedBitArray") + ";" + CR); - sb.append(indent + "}" + CR); - } - sb.append(CR); - return sb.toString(); - } - - protected String generatePchFieldDecode(String domainType, String fieldName, - int ordinal, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - sb.append(indent + "if (propertyFlags[" + ordinal + "]) // " + fieldName + ": " + - domainType + CR); - sb.append(indent + Utils.createSpaces(tabSize) + - typeMap.get(domainType).decodeExpression.replaceAll("#", fieldName) + ";" + CR); - sb.append(CR); - return sb.toString(); - } - - protected String generatePchBitFieldDecode(List<String> bitFieldList, - int ordinal, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - String comment = bitFieldList.size() == 1 ? - bitFieldList.get(0) + ": bit" : - "Combinded bits: " + bitFieldList; - StringBuffer sb = new StringBuffer(); - - if (bitFieldList.size() == 1) // single bit - { - sb.append(indent + "if (propertyFlags[" + (ordinal - 1) + "]) // " + - bitFieldList.get(0) + ": bit" + CR); - sb.append(indent + "{" + CR); - sb.append(indent + tab + typeMap.get("bit").decodeExpression.replaceAll("#", - "boolean[] flaggedBitArray") + ";" + CR); - sb.append(indent + tab + bitFieldList.get(0) + " = flaggedBitArray[0];" + CR); - sb.append(indent + "}" + CR); - } - else // multiple bits - up to 8 are combined into one byte - { - int startOrdinal = ordinal - bitFieldList.size(); - String bitCntr = "bitCntr" + startOrdinal; - sb.append(indent + "// " + comment + CR); - sb.append(indent + "int " + bitCntr + " = 0;" + CR); - sb.append(indent + "for (int i=" + startOrdinal + "; i<=" + (ordinal - 1) + "; i++)" + CR); - sb.append(indent + "{" + CR); - sb.append(indent + tab + "if (propertyFlags[i])" + CR); - sb.append(indent + tab + tab + bitCntr + "++;" + CR); - sb.append(indent + "}" + CR); - sb.append(indent + "if (" + bitCntr + " > 0) // Are any of the property bits set?" + CR); - sb.append(indent + "{" + CR); - sb.append(indent + tab + typeMap.get("bit").decodeExpression.replaceAll("#", - "boolean[] flaggedBitArray") + ";" + CR); - sb.append(indent + tab + bitCntr + " = 0;" + CR); - for (int i = 0; i < bitFieldList.size(); i++) - { - sb.append(indent + tab + "if (propertyFlags[" + (startOrdinal + i) + "])" + CR); - sb.append(indent + tab + tab + bitFieldList.get(i) + " = flaggedBitArray[" + - bitCntr + "++];" + CR); - } - sb.append(indent + "}" + CR); - } - - sb.append(CR); - return sb.toString(); - } - - protected String generatePchGetPropertyFlags(String domainType, String fieldName, - int ordinal, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - int word = ordinal / 15; - int bit = 15 - (ordinal % 15); - sb.append(indent + "if (propertyFlags[" + ordinal + "]) // " + fieldName + ": " + - domainType + CR); - sb.append(indent + tab + "compactPropertyFlags[" + word + "] |= (1 << " + - bit + ");" + CR); - sb.append(CR); - return sb.toString(); - } - - protected String generatePchBitGetPropertyFlags(List<String> bitFieldList, - int ordinal, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - int startOrdinal = ordinal - bitFieldList.size(); - - for (int i = 0; i < bitFieldList.size(); i++) - { - int thisOrdinal = startOrdinal + i; - int word = thisOrdinal / 15; - int bit = 15 - (thisOrdinal % 15); - sb.append(indent + "if (propertyFlags[" + thisOrdinal + "])" + CR); - sb.append(indent + tab + "compactPropertyFlags[" + word + - "] |= (1 << " + bit + ");" + CR); - } - - sb.append(CR); - return sb.toString(); - } - - protected String generatePchSetPropertyFlags(String domainType, String fieldName, - int ordinal, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - int word = ordinal / 15; - int bit = 15 - (ordinal % 15); - sb.append(indent + "propertyFlags[" + ordinal + "] = (compactPropertyFlags[" + - word + "] & (1 << " + bit + ")) > 0;" + CR); - return sb.toString(); - } - - protected String generatePchBitSetPropertyFlags(List<String> bitFieldList, - int ordinal, int indentSize, int tabSize) - { - String indent = Utils.createSpaces(indentSize); - StringBuffer sb = new StringBuffer(); - int startOrdinal = ordinal - bitFieldList.size(); - - for (int i = 0; i < bitFieldList.size(); i++) - { - int thisOrdinal = startOrdinal + i; - int word = thisOrdinal / 15; - int bit = 15 - (thisOrdinal % 15); - sb.append(indent + "propertyFlags[" + thisOrdinal + "] = (compactPropertyFlags[" + - word + "] & (1 << " + bit + ")) > 0;" + CR); - } - return sb.toString(); - } - - private String generatePchPropertyFlagsDeclare() - { - return "private boolean[] propertyFlags;"; - } - - private String generatePchPropertyFlagsInitializer(int totNumFields) - { - return "propertyFlags = new boolean[" + totNumFields + "];"; - } - - private String generatePchCompactPropertyFlagsInitializer(AmqpClass thisClass, int indentSize, - int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - Iterator<AmqpVersion> vItr = thisClass.getVersionSet().iterator(); - while (vItr.hasNext()) - { - AmqpVersion version = vItr.next(); - int numBytes = ((thisClass.getFieldMap().getNumFields(version) - 1) / 15) + 1; - - sb.append(indent); - if (!version.equals(thisClass.getVersionSet().first())) - { - sb.append("else "); - } - sb.append("if ( major == " + version.getMajor() + " && minor == " + - version.getMinor() + " )" + CR); - sb.append(indent + tab + "compactPropertyFlags = new int[] { "); - for (int i = 0; i < numBytes; i++) - { - if (i != 0) - { - sb.append(", "); - } - sb.append(i < numBytes - 1 ? "1" : "0"); // Set the "continue" flag where required - } - sb.append(" };" + CR); - } - return sb.toString(); - } - - private String generatePchCompactPropertyFlagsCheck(AmqpClass thisClass, int indentSize, - int tabSize) - { - String indent = Utils.createSpaces(indentSize); - String tab = Utils.createSpaces(tabSize); - StringBuffer sb = new StringBuffer(); - Iterator<AmqpVersion> vItr = thisClass.getVersionSet().iterator(); - while (vItr.hasNext()) - { - AmqpVersion version = vItr.next(); - int numFields = thisClass.getFieldMap().getNumFields(version); - int numBytes = ((numFields - 1) / 15) + 1; - - sb.append(indent); - if (!version.equals(thisClass.getVersionSet().first())) - { - sb.append("else "); - } - sb.append("if ( major == " + version.getMajor() + " && minor == " + - version.getMinor() + " && compactPropertyFlags.length != " + numBytes + " )" + CR); - sb.append(indent + tab + - "throw new AMQProtocolVersionException(\"Property flag array size mismatch:\" +" + CR); - sb.append(indent + tab + tab + "\"(Size found: \" + compactPropertyFlags.length +" + CR); - sb.append(indent + tab + tab + "\") Version " + version + " has " + numFields + - " fields which requires an int array of size " + numBytes + ".\");" + CR); - } - return sb.toString(); - } - - private String generateVersionCheck(AmqpVersionSet v) - { - StringBuffer sb = new StringBuffer(); - AmqpVersion[] versionArray = new AmqpVersion[v.size()]; - v.toArray(versionArray); - for (int i = 0; i < versionArray.length; i++) - { - if (i != 0) - { - sb.append(" || "); - } - if (versionArray.length > 1) - { - sb.append("("); - } - sb.append("major == (byte)" + versionArray[i].getMajor() + " && minor == (byte)" + - versionArray[i].getMinor()); - if (versionArray.length > 1) - { - sb.append(")"); - } - } - return sb.toString(); - } - - private String camelCaseName(String name, boolean upperFirstFlag) - { - StringBuffer ccn = new StringBuffer(); - String[] toks = name.split("[-_.\\ ]"); - for (int i = 0; i < toks.length; i++) - { - StringBuffer b = new StringBuffer(toks[i]); - if (upperFirstFlag || i > 0) - { - b.setCharAt(0, Character.toUpperCase(toks[i].charAt(0))); - } - ccn.append(b); - } - return ccn.toString(); - } - - - private String upperCaseName(String name) - { - StringBuffer ccn = new StringBuffer(); - String[] toks = name.split("[-_.\\ ]"); - for (int i = 0; i < toks.length; i++) - { - if (i != 0) - { - ccn.append('_'); - } - ccn.append(toks[i].toUpperCase()); - - - } - return ccn.toString(); - } - - - public static Factory<JavaGenerator> _factoryInstance = new Factory<JavaGenerator>() - { - - public JavaGenerator newInstance() - { - return new JavaGenerator(); - } - }; - - public static Factory<JavaGenerator> getFactory() - { - return _factoryInstance; - } - - - void processModelTemplate(NamedTemplate template, AmqpVersion version) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - void processClassTemplate(NamedTemplate template, AmqpClass amqpClass, AmqpVersion version) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - void processMethodTemplate(NamedTemplate template, AmqpClass amqpClass, AmqpMethod amqpMethod, AmqpVersion version) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - void processFieldTemplate(NamedTemplate template, AmqpClass amqpClass, AmqpMethod amqpMethod, AmqpField amqpField, AmqpVersion version) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - -} diff --git a/gentools/src/org/apache/qpid/gentools/LanguageConverter.java b/gentools/src/org/apache/qpid/gentools/LanguageConverter.java deleted file mode 100644 index 5e692d86e7..0000000000 --- a/gentools/src/org/apache/qpid/gentools/LanguageConverter.java +++ /dev/null @@ -1,42 +0,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. - * - */ -package org.apache.qpid.gentools; - -public interface LanguageConverter -{ - -// public AmqpDomainMap getDomainMap(); -// public AmqpConstantSet getConstantSet(); -// public AmqpModel getModel(); - - // - public String prepareClassName(String className); - - public String prepareMethodName(String methodName); - - public String prepareDomainName(String domainName); - - public String getDomainType(String domainName, AmqpVersion version); - - public String getGeneratedType(String domainName, AmqpVersion version); - - public String prepareConstantName(String constantName); -} diff --git a/gentools/src/org/apache/qpid/gentools/Main.java b/gentools/src/org/apache/qpid/gentools/Main.java deleted file mode 100644 index c0584f7ca7..0000000000 --- a/gentools/src/org/apache/qpid/gentools/Main.java +++ /dev/null @@ -1,301 +0,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. - * - */ -package org.apache.qpid.gentools; - -import org.apache.velocity.app.Velocity; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.xml.sax.SAXException; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Properties; - -public class Main -{ - private static final String DEFAULT_OUTPUT_DIR = ".." + Utils.FILE_SEPARATOR + "gen"; - private static final String DEFAULT_TEMPLATE_DIR_BASE = ".." + Utils.FILE_SEPARATOR; - - private enum GeneratedLanguage - { - CPP(".cpp", CppGenerator.getFactory()), - DOTNET(".net", DotnetGenerator.getFactory()), - JAVA(".java", JavaGenerator.getFactory()); - - private final String _suffix; - private final Generator.Factory _factory; - - - private final String _defaultTemplateDirectory; - - GeneratedLanguage(String suffix, Generator.Factory factory) - { - _suffix = suffix; - _factory = factory; - _defaultTemplateDirectory = DEFAULT_TEMPLATE_DIR_BASE + "templ" + _suffix; - } - - public String getSuffix() - { - return _suffix; - } - - public Generator newGenerator() - { - return _factory.newInstance(); - } - - public String getDefaultTemplateDirectory() - { - return _defaultTemplateDirectory; - } - } - - private Generator generator; - - private String outDir; - private String tmplDir; - private GeneratedLanguage _generatorLang; - private ArrayList<String> xmlFiles; - - public Main() - { - xmlFiles = new ArrayList<String>(); - } - - public void run(String[] args) - throws Exception, - SAXException, - AmqpParseException, - AmqpTypeMappingException, - AmqpTemplateException, - TargetDirectoryException, - IllegalAccessException, - InvocationTargetException, ParserConfigurationException - { - - // 0. Initialize - outDir = DEFAULT_OUTPUT_DIR; - tmplDir = null; - _generatorLang = GeneratedLanguage.CPP; // Default generation language - xmlFiles.clear(); - processArgs(args); - - if (tmplDir == null) - { - tmplDir = _generatorLang.getDefaultTemplateDirectory(); - } - - - generator = _generatorLang.newGenerator(); - generator.setTemplateDirectory(tmplDir); - generator.setOutputDirectory(outDir); - - // 1. Suck in all the XML spec files provided on the command line - analyzeXML(); - - Properties p = new Properties(); - p.setProperty("file.resource.loader.path", tmplDir); - - Velocity.init(p); - - // 2. Load up all templates - generator.initializeTemplates(); - - // 3. Generate output - generator.generate(); - - System.out.println("Files generated: " + generator.getNumberGeneratedFiles()); - System.out.println("Done."); - } - - private void processArgs(String[] args) - { - // Crude but simple... - for (int i = 0; i < args.length; i++) - { - String arg = args[i]; - if (arg.charAt(0) == '-') - { - switch (arg.charAt(1)) - { - case'c': - case'C': - _generatorLang = GeneratedLanguage.CPP; - break; - case'j': - case'J': - _generatorLang = GeneratedLanguage.JAVA; - break; - case'n': - case'N': - _generatorLang = GeneratedLanguage.DOTNET; - break; - case'o': - case'O': - if (++i < args.length) - { - outDir = args[i]; - } - break; - case't': - case'T': - if (++i < args.length) - { - tmplDir = args[i]; - } - break; - } - } - else - { - xmlFiles.add(args[i]); - } - } - } - - private void analyzeXML() - throws IOException, SAXException, AmqpParseException, AmqpTypeMappingException, ParserConfigurationException - { - DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - - System.out.println("XML files: " + xmlFiles); - for (String filename : xmlFiles) - { - File f = new File(filename); - if (f.exists()) - { - // 1a. Initialize dom - System.out.print(" \"" + filename + "\":"); - Document doc = docBuilder.parse(new File(filename)); - Node amqpNode = Utils.findChild(doc, Utils.ELEMENT_AMQP); - - // 1b. Extract version (major and minor) from the XML file - int major = Utils.getNamedIntegerAttribute(amqpNode, Utils.ATTRIBUTE_MAJOR); - int minor = Utils.getNamedIntegerAttribute(amqpNode, Utils.ATTRIBUTE_MINOR); - AmqpVersion version = new AmqpVersion(major, minor); - System.out.println(" Found version " + version.toString() + "."); - generator.addVersion(version); - generator.addFromNode(amqpNode, version); - - - } - else - { - System.err.println("ERROR: AMQP XML file \"" + filename + "\" not found."); - } - } -// *** DEBUG INFO *** Uncomment bits from this block to see lots of stuff.... -// System.out.println(); -// System.out.println("*** Debug output ***"); -// System.out.println(); -// versionSet.print(System.out, 0, 2); // List of loaded versions -// System.out.println(); -// constants.print(System.out, 0, 2); // List of constants -// System.out.println(); -// domainMap.print(System.out, 0, 2); // List of domains -// System.out.println(); -// model.print(System.out, 0, 2); // Internal version map model -// System.out.println(); -// System.out.println("*** End debug output ***"); -// System.out.println(); - } - - public static void main(String[] args) - { - int exitCode = 1; - // TODO: This is a simple and klunky way of hangling command-line args, and could be improved upon. - if (args.length < 2) - { - usage(); - } - else - { - try - { - new Main().run(args); - exitCode = 0; - } - catch (IOException e) - { - e.printStackTrace(); - } - catch (ParserConfigurationException e) - { - e.printStackTrace(); - } - catch (SAXException e) - { - e.printStackTrace(); - } - catch (AmqpParseException e) - { - e.printStackTrace(); - } - catch (AmqpTypeMappingException e) - { - e.printStackTrace(); - } - catch (AmqpTemplateException e) - { - e.printStackTrace(); - } - catch (TargetDirectoryException e) - { - e.printStackTrace(); - } - catch (IllegalAccessException e) - { - e.printStackTrace(); - } - catch (InvocationTargetException e) - { - e.printStackTrace(); - } - catch (Exception e) - { - e.printStackTrace(); - } - } - System.exit(exitCode); - } - - public static void usage() - { - System.out.println("AMQP XML generator v.0.0"); - System.out.println("Usage: Main -c|-j [-o outDir] [-t tmplDir] XMLfile [XMLfile ...]"); - System.out.println(" where -c: Generate C++."); - System.out.println(" -j: Generate Java."); - System.out.println(" -n: Generate .NET."); - System.out.println(" -o outDir: Use outDir as the output dir (default=\"" + DEFAULT_OUTPUT_DIR + "\")."); - System.out.println(" -t tmplDir: Find templates in tmplDir."); - System.out.println(" Defaults: \"" + GeneratedLanguage.CPP.getDefaultTemplateDirectory() + "\" for C++;"); - System.out.println(" \"" + GeneratedLanguage.JAVA.getDefaultTemplateDirectory() + "\" for java.;"); - System.out.println(" \"" + GeneratedLanguage.DOTNET.getDefaultTemplateDirectory() + "\" for .NET."); - System.out.println(" XMLfile is a space-separated list of AMQP XML files to be parsed."); - } - -} diff --git a/gentools/src/org/apache/qpid/gentools/MangledGenerateMethod.java b/gentools/src/org/apache/qpid/gentools/MangledGenerateMethod.java deleted file mode 100644 index ffeefed900..0000000000 --- a/gentools/src/org/apache/qpid/gentools/MangledGenerateMethod.java +++ /dev/null @@ -1,26 +0,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. - * - */ -package org.apache.qpid.gentools; - -public interface MangledGenerateMethod -{ - String generate(AmqpField field, int indentSize, int tabSize, boolean notLast); -} diff --git a/gentools/src/org/apache/qpid/gentools/NodeAware.java b/gentools/src/org/apache/qpid/gentools/NodeAware.java deleted file mode 100644 index f832da75ad..0000000000 --- a/gentools/src/org/apache/qpid/gentools/NodeAware.java +++ /dev/null @@ -1,47 +0,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. - * - */ -package org.apache.qpid.gentools; - -import org.w3c.dom.Node; - -/** - * @author kpvdr - * Interface allowing the addition of elements from a node in the - * DOM of the AMQP specification. It is used by each of the model - * elements in a recursive fashion to build the model. - */ -public interface NodeAware -{ - /** - * Add a model element from the current DOM node. All model elements must implement - * this interface. If the node contains children that are also a part of the model, - * then this method is called on new instances of those model elements. - * - * @param n Node from which the current model element is to be added. - * @param o Ordinal value of the current model elemet. - * @param v Verion of the DOM from which the node comes. - * @throws AmqpParseException - * @throws AmqpTypeMappingException - * @returns true if a node was added, false if not - */ - public boolean addFromNode(Node n, int o, AmqpVersion v) - throws AmqpParseException, AmqpTypeMappingException; -} diff --git a/gentools/src/org/apache/qpid/gentools/Printable.java b/gentools/src/org/apache/qpid/gentools/Printable.java deleted file mode 100644 index aa13df7b68..0000000000 --- a/gentools/src/org/apache/qpid/gentools/Printable.java +++ /dev/null @@ -1,28 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.io.PrintStream; - -public interface Printable -{ - public void print(PrintStream out, int marginSize, int tabSize); -} diff --git a/gentools/src/org/apache/qpid/gentools/SingleVersionClass.java b/gentools/src/org/apache/qpid/gentools/SingleVersionClass.java deleted file mode 100644 index 8e1af1c551..0000000000 --- a/gentools/src/org/apache/qpid/gentools/SingleVersionClass.java +++ /dev/null @@ -1,103 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.util.Map; -import java.util.List; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Map.Entry; - - -public class SingleVersionClass -{ - private final int _classId; - - - private final AmqpClass _amqpClass; - private final AmqpVersion _amqpVersion; - private final Generator _generator; - private final List<SingleVersionMethod> _methodList = new ArrayList<SingleVersionMethod>(); - - public SingleVersionClass(AmqpClass amqpClass, AmqpVersion amqpVersion, Generator generator) - { - _amqpClass = amqpClass; - _amqpVersion = amqpVersion; - _generator = generator; - - AmqpOrdinalVersionMap indexMap = amqpClass.getIndexMap(); - int classId = 0; - for(Entry<Integer, AmqpVersionSet> entry : indexMap.entrySet()) - { - if(entry.getValue().contains(_amqpVersion)) - { - classId = entry.getKey(); - break; - } - } - _classId = classId; - - - Collection<AmqpMethod> methods = _amqpClass.getMethodMap().values(); - - for(AmqpMethod amqpMethod : methods) - { - _methodList.add(new SingleVersionMethod(amqpMethod, _amqpVersion, _generator)); - - } - - Collections.sort(_methodList, new Comparator<SingleVersionMethod>(){ - public int compare(SingleVersionMethod method1, SingleVersionMethod method2) - { - return method1.getMethodId() - method2.getMethodId(); - } - }); - - - } - - public int getClassId() - { - return _classId; - } - - public String getName() - { - return _amqpClass.getName(); - } - - - - - - public List<SingleVersionMethod> getMethodList() - { - return _methodList; - } - - - public int getMaximumMethodId() - { - return _methodList.get(_methodList.size()-1).getMethodId(); - } -} diff --git a/gentools/src/org/apache/qpid/gentools/SingleVersionField.java b/gentools/src/org/apache/qpid/gentools/SingleVersionField.java deleted file mode 100644 index b795663d15..0000000000 --- a/gentools/src/org/apache/qpid/gentools/SingleVersionField.java +++ /dev/null @@ -1,68 +0,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. - * - */ -package org.apache.qpid.gentools; - - -public class SingleVersionField -{ - private final AmqpField _field; - private final AmqpVersion _amqpVersion; - private final Generator _generator; - - public SingleVersionField(AmqpField field, AmqpVersion amqpVersion, Generator generator) - { - _field = field; - _amqpVersion = amqpVersion; - _generator = generator; - } - - public String getName() - { - return _field.getName(); - } - - public String getDomain() - { - return _field.getDomain(_amqpVersion); - } - - - public String getDomainType() - { - return _generator.getDomainType(_field.getDomain(_amqpVersion),_amqpVersion); - } - - public String getNativeType() - { - return _generator.getNativeType(getDomainType()); - } - - public String getEncodingType() - { - return _generator.getEncodingType(getDomainType()); - } - - - public int getPosition() - { - return _field.getOrdinal(_amqpVersion); - } -} diff --git a/gentools/src/org/apache/qpid/gentools/SingleVersionMethod.java b/gentools/src/org/apache/qpid/gentools/SingleVersionMethod.java deleted file mode 100644 index 59a6d9e28a..0000000000 --- a/gentools/src/org/apache/qpid/gentools/SingleVersionMethod.java +++ /dev/null @@ -1,154 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.util.Map.Entry; -import java.util.Collection; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.HashMap; - -public class SingleVersionMethod -{ - private final AmqpMethod _amqpMethod; - private final AmqpVersion _amqpVersion; - private final int _methodId; - private final List<SingleVersionField> _fieldList = new ArrayList<SingleVersionField>(); - private final Generator _generator; - private final List<ConsolidatedField> _consolidatedFields = new ArrayList<ConsolidatedField>(); - private final Map<String, ConsolidatedField> _fieldNameToConsolidatedFieldMap = new HashMap<String, ConsolidatedField>(); - - - public SingleVersionMethod(AmqpMethod amqpMethod, AmqpVersion amqpVersion, Generator generator) - { - _amqpMethod = amqpMethod; - _amqpVersion = amqpVersion; - _generator = generator; - - AmqpOrdinalVersionMap indexMap = amqpMethod.getIndexMap(); - int methodId = 0; - for(Entry<Integer, AmqpVersionSet> entry : indexMap.entrySet()) - { - if(entry.getValue().contains(_amqpVersion)) - { - methodId = entry.getKey(); - break; - } - } - _methodId = methodId; - - Collection<AmqpField> fields = _amqpMethod.getFieldMap().values(); - - for(AmqpField field : fields) - { - _fieldList.add(new SingleVersionField(field, _amqpVersion, _generator)); - - } - - Collections.sort(_fieldList, new Comparator<SingleVersionField>(){ - public int compare(SingleVersionField field1, SingleVersionField field2) - { - return field1.getPosition() - field2.getPosition(); - } - }); - - - - ConsolidatedField lastField = null; - int bitfieldNum = 0; - for(SingleVersionField field : _fieldList) - { - String domainType = field.getDomainType(); - if(!domainType.equals("bit")) - { - lastField = new ConsolidatedField(_generator, - field.getName(), - field.getDomainType()); - _consolidatedFields.add(lastField); - } - else if(lastField == null || !lastField.getType().equals("bitfield")) - { - lastField = new ConsolidatedField(_generator, - domainType.equals("bit") ? "bitfield"+bitfieldNum++ : field.getName(), - domainType.equals("bit") ? "bitfield" : field.getDomainType(), - field.getName()); - _consolidatedFields.add(lastField); - } - else - { - lastField.add(field.getName()); - } - _fieldNameToConsolidatedFieldMap.put(field.getName(), lastField); - - } - } - - public int getMethodId() - { - return _methodId; - } - - public String getName() - { - return _amqpMethod.getName(); - } - - public Collection<SingleVersionField> getFieldList() - { - return Collections.unmodifiableCollection(_fieldList); - } - - public List<ConsolidatedField> getConsolidatedFields() - { - return _consolidatedFields; - } - - public String getConsolidatedFieldName(String fieldName) - { - return _fieldNameToConsolidatedFieldMap.get(fieldName).getName(); - } - - public boolean isConsolidated(String fieldName) - { - return _fieldNameToConsolidatedFieldMap.get(fieldName).isConsolidated(); - } - - public int getPositionInBitField(String fieldName) - { - return _fieldNameToConsolidatedFieldMap.get(fieldName).getPosition(fieldName); - } - - - public boolean isServerMethod() - { - return _amqpMethod.isServerMethod(_amqpVersion); - } - - - public boolean isClientMethod() - { - return _amqpMethod.isClientMethod(_amqpVersion); - } - -} diff --git a/gentools/src/org/apache/qpid/gentools/SingleVersionModel.java b/gentools/src/org/apache/qpid/gentools/SingleVersionModel.java deleted file mode 100644 index 22b416e45a..0000000000 --- a/gentools/src/org/apache/qpid/gentools/SingleVersionModel.java +++ /dev/null @@ -1,71 +0,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. - * - */ -package org.apache.qpid.gentools; - -import java.util.Collection; -import java.util.List; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; - - -public class SingleVersionModel -{ - private final AmqpModel _amqpModel; - private final AmqpVersion _amqpVersion; - private final Generator _generator; - private final List<SingleVersionClass> _classList = new ArrayList<SingleVersionClass>(); - - public SingleVersionModel(AmqpModel amqpModel, AmqpVersion amqpVersion, Generator generator) - { - _amqpModel = amqpModel; - _amqpVersion = amqpVersion; - _generator = generator; - - - Collection<AmqpClass> originalClasses = _amqpModel.getClassMap().values(); - - for(AmqpClass amqpClass : originalClasses) - { - _classList.add(new SingleVersionClass(amqpClass, _amqpVersion, _generator)); - - } - - Collections.sort(_classList, new Comparator<SingleVersionClass>(){ - public int compare(SingleVersionClass amqpClass1, SingleVersionClass amqpClass2) - { - return amqpClass1.getClassId() - amqpClass2.getClassId(); - } - }); - - - } - - public Collection<SingleVersionClass> getClassList() - { - return Collections.unmodifiableCollection(_classList); - } - - public int getMaximumClassId() - { - return _classList.get(_classList.size()-1).getClassId(); - } -} diff --git a/gentools/src/org/apache/qpid/gentools/TargetDirectoryException.java b/gentools/src/org/apache/qpid/gentools/TargetDirectoryException.java deleted file mode 100644 index 39ce666288..0000000000 --- a/gentools/src/org/apache/qpid/gentools/TargetDirectoryException.java +++ /dev/null @@ -1,30 +0,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. - * - */ -package org.apache.qpid.gentools; - -@SuppressWarnings("serial") -public class TargetDirectoryException extends RuntimeException -{ - public TargetDirectoryException(String msg) - { - super(msg); - } -} diff --git a/gentools/src/org/apache/qpid/gentools/Utils.java b/gentools/src/org/apache/qpid/gentools/Utils.java deleted file mode 100644 index 1cedaeea12..0000000000 --- a/gentools/src/org/apache/qpid/gentools/Utils.java +++ /dev/null @@ -1,159 +0,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. - * - */ -package org.apache.qpid.gentools; - -import org.w3c.dom.Attr; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -public class Utils -{ - public final static String FILE_SEPARATOR = System.getProperty("file.separator"); - public final static String LINE_SEPARATOR = System.getProperty("line.separator"); - - public final static String ATTRIBUTE_NAME = "name"; - public final static String ATTRIBUTE_MAJOR = "major"; - public final static String ATTRIBUTE_MINOR = "minor"; - public final static String ATTRIBUTE_INDEX = "index"; - public final static String ATTRIBUTE_LABEL = "label"; - public final static String ATTRIBUTE_SYNCHRONOUS = "synchronous"; - public final static String ATTRIBUTE_CONTENT = "content"; - public final static String ATTRIBUTE_HANDLER = "handler"; - public final static String ATTRIBUTE_DOMAIN = "domain"; - public final static String ATTRIBUTE_VALUE = "value"; - public final static String ATTRIBUTE_TYPE = "type"; // For compatibility with AMQP 8.0 - - public final static String ELEMENT_AMQP = "amqp"; - public final static String ELEMENT_CHASSIS = "chassis"; - public final static String ELEMENT_CLASS = "class"; - public final static String ELEMENT_CODEGEN = "codegen"; - public final static String ELEMENT_CONSTANT = "constant"; - public final static String ELEMENT_DOMAIN = "domain"; - public final static String ELEMENT_METHOD = "method"; - public final static String ELEMENT_FIELD = "field"; - public final static String ELEMENT_VERSION = "version"; - - // Attribute functions - - public static String getNamedAttribute(Node n, String attrName) throws AmqpParseException - { - NamedNodeMap nnm = n.getAttributes(); - if (nnm == null) - { - throw new AmqpParseException("Node \"" + n.getNodeName() + "\" has no attributes."); - } - Attr a = (Attr) nnm.getNamedItem(attrName); - if (a == null) - { - throw new AmqpParseException("Node \"" + n.getNodeName() + "\" has no attribute \"" + attrName + "\"."); - } - return a.getNodeValue(); - } - - public static int getNamedIntegerAttribute(Node n, String attrName) throws AmqpParseException - { - return Integer.parseInt(getNamedAttribute(n, attrName)); - } - - // Element functions - - public static Node findChild(Node n, String eltName) throws AmqpParseException - { - NodeList nl = n.getChildNodes(); - for (int i = 0; i < nl.getLength(); i++) - { - Node cn = nl.item(i); - if (cn.getNodeName().compareTo(eltName) == 0) - { - return cn; - } - } - throw new AmqpParseException("Node \"" + n.getNodeName() + - "\" does not contain child element \"" + eltName + "\"."); - } - - // String functions - - public static String firstUpper(String str) - { - if (!Character.isLetter(str.charAt(0)) || !Character.isLowerCase(str.charAt(0))) - { - return str; - } - StringBuffer sb = new StringBuffer(str); - sb.setCharAt(0, Character.toUpperCase(str.charAt(0))); - return sb.toString(); - } - - public static String firstLower(String str) - { - if (!Character.isUpperCase(str.charAt(0))) - { - return str; - } - StringBuffer sb = new StringBuffer(str); - sb.setCharAt(0, Character.toLowerCase(str.charAt(0))); - return sb.toString(); - } - - public static String createSpaces(int cnt) - { - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < cnt; i++) - { - sb.append(' '); - } - return sb.toString(); - } - - public static boolean containsOnlyDigits(String str) - { - boolean foundNonDigit = false; - for (int i = 0; i < str.length() && !foundNonDigit; i++) - { - if (!Character.isDigit(str.charAt(i))) - { - foundNonDigit = true; - } - } - return !foundNonDigit; - } - - public static boolean containsOnlyDigitsAndDecimal(String str) - { - boolean foundNonDigit = false; - int decimalCntr = 0; - for (int i = 0; i < str.length() && !foundNonDigit && decimalCntr < 2; i++) - { - char ch = str.charAt(i); - if (!(Character.isDigit(ch) || ch == '.')) - { - foundNonDigit = true; - } - else if (ch == '.') - { - decimalCntr++; - } - } - return !foundNonDigit && decimalCntr < 2; - } -} diff --git a/gentools/src/org/apache/qpid/gentools/VersionConsistencyCheck.java b/gentools/src/org/apache/qpid/gentools/VersionConsistencyCheck.java deleted file mode 100644 index a9cdd56e88..0000000000 --- a/gentools/src/org/apache/qpid/gentools/VersionConsistencyCheck.java +++ /dev/null @@ -1,26 +0,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. - * - */ -package org.apache.qpid.gentools; - -public interface VersionConsistencyCheck -{ - public boolean isVersionConsistent(AmqpVersionSet globalVersionSet); -} diff --git a/gentools/templ.cpp/method/MethodBodyClass.h.tmpl b/gentools/templ.cpp/method/MethodBodyClass.h.tmpl deleted file mode 100644 index 5819a9cf9c..0000000000 --- a/gentools/templ.cpp/method/MethodBodyClass.h.tmpl +++ /dev/null @@ -1,112 +0,0 @@ -&{${CLASS}${METHOD}Body.h} -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 is auto-generated by ${GENERATOR} - do not modify. - * Supported AMQP versions: -%{VLIST} * ${major}-${minor} - */ - -#ifndef qpid_framing_${CLASS}${METHOD}Body__ -#define qpid_framing_${CLASS}${METHOD}Body__ - -#include <string> -#include <sstream> - -#include <amqp_types.h> -#include <AMQMethodBody.h> -#include <Buffer.h> -#include <FieldTable.h> - -namespace qpid -{ -namespace framing -{ -${version_namespace_start} - -class ${CLASS}${METHOD}Body : public AMQMethodBody -{ - // Method field declarations - -%{FLIST} ${mb_field_declaration} - - -public: - typedef boost::shared_ptr<${CLASS}${METHOD}Body> shared_ptr; - - // Constructors and destructors - -${mb_constructor_with_initializers} - - inline ${CLASS}${METHOD}Body(u_int8_t major, u_int8_t minor): AMQMethodBody(major, minor) {} - inline ${CLASS}${METHOD}Body(ProtocolVersion& version): AMQMethodBody(version) {} - virtual ~${CLASS}${METHOD}Body() {} - - // Attribute get methods - -%{FLIST} ${mb_field_get_method} - - // Helper methods - - inline void print(std::ostream& out) const - { - out << "${CLASS}${METHOD}: "; -%{FLIST} ${mb_field_print} - } - - inline u_int16_t amqpClassId() const - { - return ${CLASS_ID_INIT}; - } - - inline u_int16_t amqpMethodId() const - { - return ${METHOD_ID_INIT}; - } - - inline u_int32_t bodySize() const - { - u_int32_t size = 0; -%{FLIST} ${mb_body_size} - return size; - } - - inline void encodeContent(Buffer&${mb_buffer_param}) const - { -%{FLIST} ${mb_encode} - } - - inline void decodeContent(Buffer&${mb_buffer_param}) - { -%{FLIST} ${mb_decode} - } - -${mb_server_operation_invoke} - -}; // class ${CLASS}${METHOD}Body - -${version_namespace_end} -} // namespace framing -} // namespace qpid - -#endif - diff --git a/gentools/templ.cpp/model/AMQP_ClientOperations.h.tmpl b/gentools/templ.cpp/model/AMQP_ClientOperations.h.tmpl deleted file mode 100644 index a9fb0e0f69..0000000000 --- a/gentools/templ.cpp/model/AMQP_ClientOperations.h.tmpl +++ /dev/null @@ -1,82 +0,0 @@ -&{AMQP_ClientOperations.h} -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 is auto-generated by ${GENERATOR} - do not modify. - * Supported AMQP versions: -%{VLIST} * ${major}-${minor} - */ - -#ifndef qpid_framing_AMQP_ClientOperations__ -#define qpid_framing_AMQP_ClientOperations__ - -#include <sstream> - -#include <FieldTable.h> -#include <ProtocolVersion.h> -#include <ProtocolVersionException.h> - -namespace qpid { -namespace framing { - -class AMQP_ClientProxy; - -class AMQP_ClientOperations -{ -protected: - ProtocolVersion version; - AMQP_ClientOperations() {} - -public: - AMQP_ClientOperations(u_int8_t major, u_int8_t minor) : version(major, minor) {} - AMQP_ClientOperations(ProtocolVersion& version) : version(version) {} - virtual ~AMQP_ClientOperations() {} - - inline u_int8_t getMajor() const { return version.getMajor(); } - inline u_int8_t getMinor() const { return version.getMinor(); } - inline const ProtocolVersion& getVersion() const { return version; } - inline bool isVersion(u_int8_t _major, u_int8_t _minor) const - { - return version.equals(_major, _minor); - } - inline bool isVersion(ProtocolVersion& _version) const - { - return version.equals(_version); - } - - // Include framing constant declarations - #include <AMQP_Constants.h> - - // Inner classes - -%{CLIST} ${coh_inner_class} - - // Method handler get methods - -%{CLIST} ${coh_method_handler_get_method} - -}; /* class AMQP_ClientOperations */ - -} /* namespace framing */ -} /* namespace qpid */ - -#endif diff --git a/gentools/templ.cpp/model/AMQP_ClientProxy.cpp.tmpl b/gentools/templ.cpp/model/AMQP_ClientProxy.cpp.tmpl deleted file mode 100644 index 8cca6e5cec..0000000000 --- a/gentools/templ.cpp/model/AMQP_ClientProxy.cpp.tmpl +++ /dev/null @@ -1,52 +0,0 @@ -&{AMQP_ClientProxy.cpp} -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 is auto-generated by ${GENERATOR} - do not modify. - * Supported AMQP versions: -%{VLIST} * ${major}-${minor} - */ - -#include <sstream> - -#include <AMQP_ClientProxy.h> -#include <AMQFrame.h> -%{MLIST} ${cpc_method_body_include} - -namespace qpid { -namespace framing { - -AMQP_ClientProxy::AMQP_ClientProxy(OutputHandler* out, u_int8_t major, u_int8_t minor) : -%{CLIST} ${cpc_constructor_initializer} - -{} - - // Inner class instance get methods - -%{CLIST} ${cpc_inner_class_get_method} - - // Inner class implementation - -%{CLIST} ${cpc_inner_class_impl} - -} /* namespace framing */ -} /* namespace qpid */ diff --git a/gentools/templ.cpp/model/AMQP_ClientProxy.h.tmpl b/gentools/templ.cpp/model/AMQP_ClientProxy.h.tmpl deleted file mode 100644 index 0653ed7186..0000000000 --- a/gentools/templ.cpp/model/AMQP_ClientProxy.h.tmpl +++ /dev/null @@ -1,75 +0,0 @@ -&{AMQP_ClientProxy.h} -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 is auto-generated by ${GENERATOR} - do not modify. - * Supported AMQP versions: -%{VLIST} * ${major}-${minor} - */ - -#ifndef qpid_framing_AMQP_ClientProxy__ -#define qpid_framing_AMQP_ClientProxy__ - -#include <AMQP_ClientOperations.h> -#include <FieldTable.h> -#include <OutputHandler.h> - -namespace qpid { -namespace framing { - -class AMQP_ClientProxy : public AMQP_ClientOperations -{ -private: - - ProtocolVersion version; - OutputHandler* out; -%{CLIST} ${cph_handler_pointer_defn} - -public: - AMQP_ClientProxy(OutputHandler* out, u_int8_t major, u_int8_t minor); - ProtocolVersion& getProtocolVersion() {return version;} - virtual ~AMQP_ClientProxy() {} - - // Get methods for handlers - -%{CLIST} ${cph_handler_pointer_get_method} - - // Inner class definitions - -%{CLIST} ${cph_inner_class_defn} - -private: - // Inner class instances - -%{CLIST} ${cph_inner_class_instance} - -public: - // Inner class instance get methods - -%{CLIST} ${cph_inner_class_get_method} - -}; /* class AMQP_ClientProxy */ - -} /* namespace framing */ -} /* namespace qpid */ - -#endif diff --git a/gentools/templ.cpp/model/AMQP_Constants.h.tmpl b/gentools/templ.cpp/model/AMQP_Constants.h.tmpl deleted file mode 100644 index 4631bc8de6..0000000000 --- a/gentools/templ.cpp/model/AMQP_Constants.h.tmpl +++ /dev/null @@ -1,34 +0,0 @@ -&{AMQP_Constants.h} -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 is auto-generated by ${GENERATOR} - do not modify. - * Supported AMQP versions: -%{VLIST} * ${major}-${minor} - */ - // NOTE: This file is intended to be included within the class structure of both - // the client and server operations classes. These need to have <sstream> included. - - // Constant getValue methods - -%{TLIST} ${ch_get_value_method} -
\ No newline at end of file diff --git a/gentools/templ.cpp/model/AMQP_HighestVersion.h.tmpl b/gentools/templ.cpp/model/AMQP_HighestVersion.h.tmpl deleted file mode 100644 index 9753b454ba..0000000000 --- a/gentools/templ.cpp/model/AMQP_HighestVersion.h.tmpl +++ /dev/null @@ -1,42 +0,0 @@ -&{AMQP_HighestVersion.h} -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 is auto-generated by ${GENERATOR} - do not modify. - * Supported AMQP versions: -%{VLIST} * ${major}-${minor} - */ -#ifndef qpid_framing_highestProtocolVersion__ -#define qpid_framing_highestProtocolVersion__ - -#include <ProtocolVersion.h> - - -namespace qpid { -namespace framing { - -static ProtocolVersion highestProtocolVersion(${hv_latest_major}, ${hv_latest_minor}); - -} /* namespace framing */ -} /* namespace qpid */ - -#endif diff --git a/gentools/templ.cpp/model/AMQP_MethodVersionMap.cpp.tmpl b/gentools/templ.cpp/model/AMQP_MethodVersionMap.cpp.tmpl deleted file mode 100644 index dc2a890c88..0000000000 --- a/gentools/templ.cpp/model/AMQP_MethodVersionMap.cpp.tmpl +++ /dev/null @@ -1,62 +0,0 @@ -&{AMQP_MethodVersionMap.cpp} -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 is auto-generated by ${GENERATOR} - do not modify. - * Supported AMQP versions: -%{VLIST} * ${major}-${minor} - */ - -#include <sstream> - -#include <AMQP_MethodVersionMap.h> - -namespace qpid -{ -namespace framing -{ - -AMQP_MethodVersionMap::AMQP_MethodVersionMap() -{ -%{CLIST} ${mc_create_method_body_map_entry} -} - -AMQMethodBody* AMQP_MethodVersionMap::createMethodBody(u_int16_t classId, u_int16_t methodId, u_int8_t major, u_int8_t minor) -{ - iterator itr = find(createMapKey(classId, methodId, major, minor)); - if (itr == end()) - { - std::stringstream ss; - ss << "Unable to find MethodBody class for classId = " << classId << ", methodId = " << - methodId << ", AMQ protocol version = " << major << "-" << minor << "."; - throw ProtocolVersionException(ss.str()); - } - return (itr->second)(major, minor); -} - -u_int64_t AMQP_MethodVersionMap::createMapKey(u_int16_t classId, u_int16_t methodId, u_int8_t major, u_int8_t minor) -{ - return ((u_int64_t)classId<<48) + ((u_int64_t)methodId<<32) + ((u_int64_t)major<<16) + minor; -} - -} /* namespace framing */ -} /* namespace qpid */ diff --git a/gentools/templ.cpp/model/AMQP_MethodVersionMap.h.tmpl b/gentools/templ.cpp/model/AMQP_MethodVersionMap.h.tmpl deleted file mode 100644 index c197871d4b..0000000000 --- a/gentools/templ.cpp/model/AMQP_MethodVersionMap.h.tmpl +++ /dev/null @@ -1,57 +0,0 @@ -&{AMQP_MethodVersionMap.h} -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 is auto-generated by ${GENERATOR} - do not modify. - * Supported AMQP versions: -%{VLIST} * ${major}-${minor} - */ - -#ifndef qpid_framing_AMQP_MethodVersionMap__ -#define qpid_framing_AMQP_MethodVersionMap__ - -#include <map> -#include <AMQMethodBody.h> - -%{MLIST} ${mc_method_body_include} - -namespace qpid -{ -namespace framing -{ - -template <class T> AMQMethodBody* createMethodBodyFn(u_int8_t major, u_int8_t minor) { return new T(major, minor); } -typedef AMQMethodBody* (*fnPtr)(u_int8_t, u_int8_t); - -class AMQP_MethodVersionMap: public std::map<u_int64_t, fnPtr> -{ -protected: - u_int64_t createMapKey(u_int16_t classId, u_int16_t methodId, u_int8_t major, u_int8_t minor); -public: - AMQP_MethodVersionMap(); - AMQMethodBody* createMethodBody(u_int16_t classId, u_int16_t methodId, u_int8_t major, u_int8_t minor); -}; - -} /* namespace framing */ -} /* namespace qpid */ - -#endif diff --git a/gentools/templ.cpp/model/AMQP_ServerOperations.h.tmpl b/gentools/templ.cpp/model/AMQP_ServerOperations.h.tmpl deleted file mode 100644 index e87723667b..0000000000 --- a/gentools/templ.cpp/model/AMQP_ServerOperations.h.tmpl +++ /dev/null @@ -1,83 +0,0 @@ -&{AMQP_ServerOperations.h} -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 is auto-generated by ${GENERATOR} - do not modify. - * Supported AMQP versions: -%{VLIST} * ${major}-${minor} - */ - -#ifndef qpid_framing_AMQP_ServerOperations__ -#define qpid_framing_AMQP_ServerOperations__ - -#include <sstream> - -#include <FieldTable.h> -#include <ProtocolVersion.h> -#include <ProtocolVersionException.h> - -namespace qpid { -namespace framing { - -class AMQP_ServerProxy; -class AMQP_ClientProxy; - -class AMQP_ServerOperations -{ -protected: - ProtocolVersion version; - AMQP_ServerOperations() {} - -public: - AMQP_ServerOperations(u_int8_t major, u_int8_t minor) : version(major, minor) {} - AMQP_ServerOperations(ProtocolVersion& version) : version(version) {} - virtual ~AMQP_ServerOperations() {} - - inline u_int8_t getMajor() const { return version.getMajor(); } - inline u_int8_t getMinor() const { return version.getMinor(); } - inline const ProtocolVersion& getVersion() const { return version; } - inline bool isVersion(u_int8_t _major, u_int8_t _minor) const - { - return version.equals(_major, _minor); - } - inline bool isVersion(ProtocolVersion& _version) const - { - return version.equals(_version); - } - - // Include framing constant declarations - #include <AMQP_Constants.h> - - // Inner classes - -%{CLIST} ${soh_inner_class} - - // Method handler get methods - -%{CLIST} ${soh_method_handler_get_method} - -}; /* class AMQP_ServerOperations */ - -} /* namespace framing */ -} /* namespace qpid */ - -#endif diff --git a/gentools/templ.cpp/model/AMQP_ServerProxy.cpp.tmpl b/gentools/templ.cpp/model/AMQP_ServerProxy.cpp.tmpl deleted file mode 100644 index cce369f98b..0000000000 --- a/gentools/templ.cpp/model/AMQP_ServerProxy.cpp.tmpl +++ /dev/null @@ -1,51 +0,0 @@ -&{AMQP_ServerProxy.cpp} -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 is auto-generated by ${GENERATOR} - do not modify. - * Supported AMQP versions: -%{VLIST} * ${major}-${minor} - */ - -#include <sstream> - -#include <AMQP_ServerProxy.h> -#include <AMQFrame.h> -%{MLIST} ${spc_method_body_include} - -namespace qpid { -namespace framing { - -AMQP_ServerProxy::AMQP_ServerProxy(OutputHandler* out, u_int8_t major, u_int8_t minor) : -%{CLIST} ${spc_constructor_initializer} -{} - - // Inner class instance get methods - -%{CLIST} ${spc_inner_class_get_method} - - // Inner class implementation - -%{CLIST} ${spc_inner_class_impl} - -} /* namespace framing */ -} /* namespace qpid */ diff --git a/gentools/templ.cpp/model/AMQP_ServerProxy.h.tmpl b/gentools/templ.cpp/model/AMQP_ServerProxy.h.tmpl deleted file mode 100644 index fab29f2c60..0000000000 --- a/gentools/templ.cpp/model/AMQP_ServerProxy.h.tmpl +++ /dev/null @@ -1,74 +0,0 @@ -&{AMQP_ServerProxy.h} -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 is auto-generated by ${GENERATOR} - do not modify. - * Supported AMQP versions: -%{VLIST} * ${major}-${minor} - */ - -#ifndef qpid_framing_AMQP_ServerProxy__ -#define qpid_framing_AMQP_ServerProxy__ - -#include <AMQP_ServerOperations.h> -#include <FieldTable.h> -#include <OutputHandler.h> - -namespace qpid { -namespace framing { - -class AMQP_ServerProxy : public AMQP_ServerOperations -{ -private: - ProtocolVersion version; - OutputHandler* out; -%{CLIST} ${sph_handler_pointer_defn} - -public: - AMQP_ServerProxy(OutputHandler* out, u_int8_t major, u_int8_t minor); - ProtocolVersion& getProtocolVersion() {return version;} - virtual ~AMQP_ServerProxy() {} - - // Get methods for handlers - -%{CLIST} ${sph_handler_pointer_get_method} - - // Inner class definitions - -%{CLIST} ${sph_inner_class_defn} - -private: - // Inner class instances - -%{CLIST} ${sph_inner_class_instance} - -public: - // Inner class instance get methods - -%{CLIST} ${sph_inner_class_get_method} - -}; /* class AMQP_ServerProxy */ - -} /* namespace framing */ -} /* namespace qpid */ - -#endif diff --git a/gentools/templ.java/PropertyContentHeaderClass.tmpl b/gentools/templ.java/PropertyContentHeaderClass.tmpl deleted file mode 100644 index ab6406b1fe..0000000000 --- a/gentools/templ.java/PropertyContentHeaderClass.tmpl +++ /dev/null @@ -1,208 +0,0 @@ -&{${CLASS}ContentHeaderProperties.java} -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 is auto-generated by ${GENERATOR} - do not modify. - * Supported AMQP versions: -%{VLIST} * ${major}-${minor} - */ - -package org.apache.qpid.framing; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.mina.common.ByteBuffer; - -public class ${CLASS}ContentHeaderProperties implements ContentHeaderProperties -{ - private static final Logger logger = LoggerFactory.getLogger(BasicContentHeaderProperties.class); - - /** - * We store the encoded form when we decode the content header so that if we need to - * write it out without modifying it we can do so without incurring the expense of - * reencoding it. - */ - private byte[] encodedBuffer; - - /** - * Flag indicating whether the entire content header has been decoded yet. - */ - private boolean decodedFlag = true; - - /** - * We have some optimisations for partial decoding for maximum performance. The - * headers are used in the broker for routing in some cases so we can decode that - * separately. - */ - private boolean decodedHeadersFlag = true; - - /** - * We have some optimisations for partial decoding for maximum performance. The - * content type is used by all clients to determine the message type. - */ - private boolean decodedContentTypeFlag = true; - - /** - * AMQP major and minor version of this instance. - */ - private byte major; - private byte minor; - - /** - * Property flags. - */ - ${pch_property_flags_declare} - - // Header fields from specification -%{FLIST} ${field_declaration} - - /** - * Constructor - */ - public ${CLASS}ContentHeaderProperties(byte major, byte minor) - { - this.major = major; - this.minor = minor; - - // Although one flag is initialized per property, the flags are used - // in ordinal order of the AMQP version represented by this instance, - // thus the number of flags actually used may be less than the total - // number defined. - ${pch_property_flags_initializer} - } - - public int getPropertyListSize() - { - if (encodedBuffer != null) - { - return encodedBuffer.length; - } - else - { - int size = 0; -%{FLIST} ${pch_field_list_size} - return size; - } - } - - private void clearEncodedForm() - { - if (!decodedFlag && encodedBuffer != null) - { - //decode(); - } - encodedBuffer = null; - } - - public void setPropertyFlags(int[] compactPropertyFlags) - throws AMQProtocolVersionException - { - clearEncodedForm(); -${pch_compact_property_flags_check} -%{FLIST} ${pch_set_compact_property_flags} - } - - public int[] getPropertyFlags() - { - int[] compactPropertyFlags = new int[] { 0 }; -${pch_compact_property_flags_initializer} -%{FLIST} ${pch_get_compact_property_flags} - return compactPropertyFlags; - } - - public void writePropertyListPayload(ByteBuffer buffer) - { - if (encodedBuffer != null) - { - buffer.put(encodedBuffer); - } - else - { -%{FLIST} ${pch_field_list_payload} - } - } - - public void populatePropertiesFromBuffer(ByteBuffer buffer, int[] propertyFlags, int size) - throws AMQFrameDecodingException, AMQProtocolVersionException - { - setPropertyFlags(propertyFlags); - - if (logger.isDebugEnabled()) - { - logger.debug("Property flags: " + propertyFlags); - } - decode(buffer); - /*encodedBuffer = new byte[size]; - buffer.get(encodedBuffer, 0, size); - decodedFlag = false; - decodedHeadersFlag = false; - decodedContentTypeFlag = false;*/ - } - - private void decode(ByteBuffer buffer) - { - //ByteBuffer buffer = ByteBuffer.wrap(encodedBuffer); - int pos = buffer.position(); - try - { -%{FLIST} ${pch_field_list_decode} - // This line does nothing, but prevents a compiler error (Exception not thrown) - // if this block is empty. - if (false) throw new AMQFrameDecodingException(""); - } - catch (AMQFrameDecodingException e) - { - throw new RuntimeException("Error in content header data: " + e); - } - - final int endPos = buffer.position(); - buffer.position(pos); - final int len = endPos - pos; - encodedBuffer = new byte[len]; - final int limit = buffer.limit(); - buffer.limit(endPos); - buffer.get(encodedBuffer, 0, len); - buffer.limit(limit); - buffer.position(endPos); - decodedFlag = true; - } - - private void decodeIfNecessary() - { - if (!decodedFlag) - { - //decode(); - } - } - - // Field clear methods - -%{FLIST} ${pch_field_clear_methods} - - // Field get methods - -%{FLIST} ${pch_field_get_methods} - - // Field set methods - -%{FLIST} ${pch_field_set_methods} -} diff --git a/gentools/templ.java/method/version/MethodBodyClass.vm b/gentools/templ.java/method/version/MethodBodyClass.vm deleted file mode 100644 index bb62438a65..0000000000 --- a/gentools/templ.java/method/version/MethodBodyClass.vm +++ /dev/null @@ -1,190 +0,0 @@ -#macro( UpperCamel $name ) -#set( $name = "${name.substring(0,1).toUpperCase()}${name.substring(1)}" ) -#end -#macro( toUpperCamel $name )${name.substring(0,1).toUpperCase()}${name.substring(1)}#end - - - -#set( $amqp_ClassName = $amqpClass.Name) -#UpperCamel( $amqp_ClassName ) -#set( $amqp_MethodName = $amqpMethod.Name ) -#UpperCamel( $amqp_MethodName ) -#set( $javaClassName = "${amqp_ClassName}${amqp_MethodName}BodyImpl" ) -#set( $interfaceName = "${amqp_ClassName}${amqp_MethodName}Body" ) -#set( $amqpPackageName = "amqp_$version.getMajor()_$version.getMinor()" ) - -#set( $filename = "${amqpPackageName}/${javaClassName}.java") -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 is auto-generated by ${generator} - do not modify. - * Supported AMQP version: - * $version.getMajor()-$version.getMinor() - */ - -#set( $clazz = $amqpClass.asSingleVersionClass( $version ) ) -#set( $method = $amqpMethod.asSingleVersionMethod( $version ) ) - -package org.apache.qpid.framing.amqp_$version.getMajor()_$version.getMinor(); - -import java.util.HashMap; - -import org.apache.mina.common.ByteBuffer; -import org.apache.qpid.framing.*; - -public class ${javaClassName} extends AMQMethodBody_$version.getMajor()_$version.getMinor() implements $interfaceName -{ - private static final AMQMethodBodyInstanceFactory FACTORY_INSTANCE = new AMQMethodBodyInstanceFactory() - { - public AMQMethodBody newInstance(ByteBuffer in, long size) throws AMQFrameDecodingException - { - return new ${javaClassName}(in); - } - - - }; - - - public static AMQMethodBodyInstanceFactory getFactory() - { - return FACTORY_INSTANCE; - } - - public static int CLASS_ID = $clazz.ClassId; - - public static int METHOD_ID = $method.MethodId; - - - - // Fields declared in specification -#foreach( $field in $method.ConsolidatedFields ) - private final $field.NativeType _$field.getName(); // $field.UnderlyingFields -#end - - - // Constructor - - public ${javaClassName}(ByteBuffer buffer) throws AMQFrameDecodingException - { -#foreach( $field in $method.ConsolidatedFields ) - _$field.Name = read$field.getEncodingType()( buffer ); -#end - } - - public ${javaClassName}( -#foreach( $field in $method.FieldList ) -#if( $velocityCount == $method.getFieldList().size() ) - $field.NativeType $field.Name -#else - $field.NativeType $field.Name, -#end -#end) - { -#set( $consolidatedFieldName = "" ) -#foreach( $field in $method.FieldList ) -#if( $method.isConsolidated( $field.Name ) ) -#if( !$method.getConsolidatedFieldName( $field.Name ).equals( $consolidatedFieldName ) ) -#if( !$consolidatedFieldName.equals("") ) - _$consolidatedFieldName = $consolidatedFieldName; // 1 -#end -#set( $consolidatedFieldName = $method.getConsolidatedFieldName( $field.Name ) ) - byte $consolidatedFieldName = (byte)0; -#end - if( $field.Name ) - { - $consolidatedFieldName = (byte) (((int) $consolidatedFieldName) | (1 << $method.getPositionInBitField( $field.Name ))); - } -#if( $velocityCount == $method.getFieldList().size()) - _$consolidatedFieldName = $consolidatedFieldName; -#else - -#end -#else -#if( !$consolidatedFieldName.equals("") ) - _$consolidatedFieldName = $consolidatedFieldName; -#end -#set( $consolidatedFieldName = "" ) - _$field.Name = $field.Name; -#end -#end - } - - public int getClazz() - { - return CLASS_ID; - } - - public int getMethod() - { - return METHOD_ID; - } - - -#foreach( $field in $method.FieldList ) - public final $field.NativeType get#toUpperCamel( ${field.Name} )() - { -#if( $method.isConsolidated( $field.Name ) ) - return (((int)(_$method.getConsolidatedFieldName( $field.Name ))) & ( 1 << $method.getPositionInBitField( $field.Name ))) != 0; -#else - return _$field.Name; -#end - } -#end - - protected int getBodySize() - { - int size = 0; -#foreach( $field in $method.ConsolidatedFields ) -#if( $field.isFixedSize() ) - size += $field.Size; -#else - size += getSizeOf( _$field.Name ); -#end -#end - return size; - } - - public void writeMethodPayload(ByteBuffer buffer) - { -#foreach( $field in $method.ConsolidatedFields ) - - write$field.getEncodingType()( buffer, _$field.Name ); -#end - } - - - public String toString() - { - StringBuffer buf = new StringBuffer("[$javaClassName: "); -#foreach( $field in $method.FieldList ) - buf.append( "$field.Name=" ); - buf.append( get#toUpperCamel( $field.Name )() ); -#if( $velocityCount != $method.FieldList.size() ) - buf.append( ", " ); -#end -#end - buf.append("]"); - return buf.toString(); - } - - -} diff --git a/gentools/templ.java/model/ProtocolVersionListClass.vm b/gentools/templ.java/model/ProtocolVersionListClass.vm deleted file mode 100644 index bcf7db345b..0000000000 --- a/gentools/templ.java/model/ProtocolVersionListClass.vm +++ /dev/null @@ -1,154 +0,0 @@ -#set( $filename = "ProtocolVersion.java" ) -/* -* -* Licensed to the Apache Software Foundation (ASF) under one -* or more contributor license agreements. See the NOTICE file -* distributed with this work for additional information -* regarding copyright ownership. The ASF licenses this file -* to you under the Apache License, Version 2.0 (the -* "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, -* software distributed under the License is distributed on an -* "AS IS" BASIS, WITHOUT 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 is auto-generated by $generator - do not modify. -* Supported AMQP versions: -#foreach( $version in $model.getVersionSet() ) -* $version.getMajor()-$version.getMinor() -#end -*/ - -package org.apache.qpid.framing; - -import java.util.SortedSet; -import java.util.Collections; -import java.util.TreeSet; - - -public class ProtocolVersion implements Comparable -{ - private final byte _majorVersion; - private final byte _minorVersion; - private final String _stringFormat; - - - public ProtocolVersion(byte majorVersion, byte minorVersion) - { - _majorVersion = majorVersion; - _minorVersion = minorVersion; - _stringFormat = _majorVersion+"-"+_minorVersion; - } - - public byte getMajorVersion() - { - return _majorVersion; - } - - public byte getMinorVersion() - { - return _minorVersion; - } - - public String toString() - { - return _stringFormat; - } - - public int compareTo(Object o) - { - ProtocolVersion pv = (ProtocolVersion) o; - - /* - * 0-8 has it's major and minor numbers the wrong way round (it's actually 8-0)... - * so we need to deal with that case specially - */ - - if((_majorVersion == (byte) 8) && (_minorVersion == (byte) 0)) - { - ProtocolVersion fixedThis = new ProtocolVersion(_minorVersion, _majorVersion); - return fixedThis.compareTo(pv); - } - - if((pv.getMajorVersion() == (byte) 8) && (pv.getMinorVersion() == (byte) 0)) - { - ProtocolVersion fixedOther = new ProtocolVersion(pv.getMinorVersion(), pv.getMajorVersion()); - return this.compareTo(fixedOther); - } - - if(_majorVersion > pv.getMajorVersion()) - { - return 1; - } - else if(_majorVersion < pv.getMajorVersion()) - { - return -1; - } - else if(_minorVersion > pv.getMinorVersion()) - { - return 1; - } - else if(getMinorVersion() < pv.getMinorVersion()) - { - return -1; - } - else - { - return 0; - } - - } - - public boolean equals(Object o) - { - return o != null && (o == this || (compareTo(o) == 0)); - } - - public int hashCode() - { - return (0xFF & (int)_minorVersion) | ((0xFF & (int)_majorVersion) << 8); - } - - - public boolean isSupported() - { - return _supportedVersions.contains(this); - } - - public static ProtocolVersion getLatestSupportedVersion() - { - return _supportedVersions.last(); - } - - private static final SortedSet<ProtocolVersion> _supportedVersions; - - static - { - SortedSet<ProtocolVersion> versions = new TreeSet<ProtocolVersion>(); - -#foreach( $version in $model.getVersionSet() ) - versions.add(new ProtocolVersion((byte)$version.getMajor(),(byte)$version.getMinor())); -#end - _supportedVersions = Collections.unmodifiableSortedSet(versions); - } - - - public static SortedSet<ProtocolVersion> getSupportedProtocolVersions() - { - return _supportedVersions; - } - - - - - -} diff --git a/gentools/templ.java/model/version/AmqpConstantsClass.vm b/gentools/templ.java/model/version/AmqpConstantsClass.vm deleted file mode 100644 index 8d459f2977..0000000000 --- a/gentools/templ.java/model/version/AmqpConstantsClass.vm +++ /dev/null @@ -1,37 +0,0 @@ -&{AmqpConstants.java} -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 is auto-generated by ${GENERATOR} - do not modify. - * Supported AMQP versions: -%{VLIST} * ${major}-${minor} - */ - -package org.apache.qpid.framing; - -class AmqpConstants -{ - // Constant getValue methods - -%{TLIST} ${const_get_method} - -} diff --git a/gentools/templ.java/model/version/MethodRegistryClass.vm b/gentools/templ.java/model/version/MethodRegistryClass.vm deleted file mode 100644 index 82287e7f8f..0000000000 --- a/gentools/templ.java/model/version/MethodRegistryClass.vm +++ /dev/null @@ -1,145 +0,0 @@ -#set( $filename = "amqp_$version.getMajor()_$version.getMinor()/MethodRegistry_${version.getMajor()}_${version.getMinor()}.java") -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 is auto-generated by $generator - do not modify. - * Supported AMQP version: - * $version.getMajor()-$version.getMinor() - */ - -package org.apache.qpid.framing.amqp_${version.getMajor()}_${version.getMinor()}; - -import org.apache.qpid.framing.AMQMethodBodyInstanceFactory; -import org.apache.qpid.framing.AMQFrameDecodingException; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.ProtocolVersion; - - -import org.apache.log4j.Logger; -import org.apache.mina.common.ByteBuffer; - -public class MethodRegistry_$version.getMajor()_$version.getMinor() extends MethodRegistry -{ - - private static final Logger _log = Logger.getLogger(MethodRegistry.class); - -#set( $specificModel = $model.asSingleVersionModel() ) - - - - private final AMQMethodBodyInstanceFactory[][] _factories = new AMQMethodBodyInstanceFactory[$specificModel.getMaximumClassId()+1][]; - - public MethodRegistry_$version.getMajor()_$version.getMinor()() - { - this(new ProtocolVersion((byte)$version.getMajor(),(byte)$version.getMinor())); - } - - public MethodRegistry_$version.getMajor()_$version.getMinor()(ProtocolVersion pv) - { - super(pv); -#foreach( $amqpClass in $specificModel.getClassList() ) -#set( $amqpClassNameFirstChar = $amqpClass.getName().substring(0,1) ) -#set( $amqpClassNameFirstCharU = $amqpClassNameFirstChar.toUpperCase() ) -#set( $amqpClassNameUpperCamel = "$amqpClassNameFirstCharU$amqpClass.getName().substring(1)" ) - - - - // Register method body instance factories for the $amqpClassNameUpperCamel class. - - _factories[$amqpClass.getClassId()] = new AMQMethodBodyInstanceFactory[$amqpClass.getMaximumMethodId()+1]; - -#foreach( $amqpMethod in $amqpClass.getMethodList() ) -#set( $amqpMethodNameFirstChar = $amqpMethod.getName().substring(0,1) ) -#set( $amqpMethodNameFirstCharU = $amqpMethodNameFirstChar.toUpperCase() ) -#set( $amqpMethodNameUpperCamel = "$amqpMethodNameFirstCharU$amqpMethod.getName().substring(1)" ) - _factories[$amqpClass.getClassId()][$amqpMethod.getMethodId()] = ${amqpClassNameUpperCamel}${amqpMethodNameUpperCamel}BodyImpl.getFactory(); -#end - -#end - - - } - - - public AMQMethodBody convertToBody(ByteBuffer in, long size) - throws AMQFrameDecodingException - { - int classId = in.getUnsignedShort(); - int methodId = in.getUnsignedShort(); - - AMQMethodBodyInstanceFactory bodyFactory; - try - { - bodyFactory = _factories[classId][methodId]; - } - catch(NullPointerException e) - { - throw new AMQFrameDecodingException(_log, - "Class " + classId + " unknown in AMQP version $version.getMajor()-$version.getMinor()" - + " (while trying to decode class " + classId + " method " + methodId + "."); - } - catch(IndexOutOfBoundsException e) - { - if(classId >= _factories.length) - { - throw new AMQFrameDecodingException(_log, - "Class " + classId + " unknown in AMQP version $version.getMajor()-$version.getMinor()" - + " (while trying to decode class " + classId + " method " + methodId + "."); - - } - else - { - throw new AMQFrameDecodingException(_log, - "Method " + methodId + " unknown in AMQP version $version.getMajor()-$version.getMinor()" - + " (while trying to decode class " + classId + " method " + methodId + "."); - - } - } - - - if (bodyFactory == null) - { - throw new AMQFrameDecodingException(_log, - "Method " + methodId + " unknown in AMQP version $version.getMajor()-$version.getMinor()" - + " (while trying to decode class " + classId + " method " + methodId + "."); - } - - - return bodyFactory.newInstance(in, size); - - - } - - - public int getMaxClassId() - { - return $specificModel.getMaximumClassId(); - } - - public int getMaxMethodId(int classId) - { - return _factories[classId].length - 1; - } - - -} diff --git a/gentools/xml-src/amqp-0.10.test.xml b/gentools/xml-src/amqp-0.10.test.xml deleted file mode 100644 index 5d3d80648b..0000000000 --- a/gentools/xml-src/amqp-0.10.test.xml +++ /dev/null @@ -1,4241 +0,0 @@ -<?xml version = "1.0"?> - -<!-- - EDITORS: (PH) Pieter Hintjens <ph@imatix.com> - (KvdR) Kim van der Riet <kim.vdriet@redhat.com> - - These editors have been assigned by the AMQP working group. - Please do not edit/commit this file without consulting with - one of the above editors. - ======================================================== - - TODOs - - see TODO comments in the text ---> - -<!-- - Copyright Notice - ================ - (c) Copyright JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., - iMatix Corporation, IONA\ufffd Technologies, Red Hat, Inc., - TWIST Process Innovations, and 29West Inc. 2006. All rights reserved. - - License - ======= - JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., iMatix - Corporation, IONA\ufffd Technologies, Red Hat, Inc., TWIST Process Innovations, and - 29West Inc. (collectively, the "Authors") each hereby grants to you a worldwide, - perpetual, royalty-free, nontransferable, nonexclusive license to - (i) copy, display, and implement the Advanced Messaging Queue Protocol - ("AMQP") Specification and (ii) the Licensed Claims that are held by - the Authors, all for the purpose of implementing the Advanced Messaging - Queue Protocol Specification. Your license and any rights under this - Agreement will terminate immediately without notice from - any Author if you bring any claim, suit, demand, or action related to - the Advanced Messaging Queue Protocol Specification against any Author. - Upon termination, you shall destroy all copies of the Advanced Messaging - Queue Protocol Specification in your possession or control. - - As used hereunder, "Licensed Claims" means those claims of a patent or - patent application, throughout the world, excluding design patents and - design registrations, owned or controlled, or that can be sublicensed - without fee and in compliance with the requirements of this - Agreement, by an Author or its affiliates now or at any - future time and which would necessarily be infringed by implementation - of the Advanced Messaging Queue Protocol Specification. A claim is - necessarily infringed hereunder only when it is not possible to avoid - infringing it because there is no plausible non-infringing alternative - for implementing the required portions of the Advanced Messaging Queue - Protocol Specification. Notwithstanding the foregoing, Licensed Claims - shall not include any claims other than as set forth above even if - contained in the same patent as Licensed Claims; or that read solely - on any implementations of any portion of the Advanced Messaging Queue - Protocol Specification that are not required by the Advanced Messaging - Queue Protocol Specification, or that, if licensed, would require a - payment of royalties by the licensor to unaffiliated third parties. - Moreover, Licensed Claims shall not include (i) any enabling technologies - that may be necessary to make or use any Licensed Product but are not - themselves expressly set forth in the Advanced Messaging Queue Protocol - Specification (e.g., semiconductor manufacturing technology, compiler - technology, object oriented technology, networking technology, operating - system technology, and the like); or (ii) the implementation of other - published standards developed elsewhere and merely referred to in the - body of the Advanced Messaging Queue Protocol Specification, or - (iii) any Licensed Product and any combinations thereof the purpose or - function of which is not required for compliance with the Advanced - Messaging Queue Protocol Specification. For purposes of this definition, - the Advanced Messaging Queue Protocol Specification shall be deemed to - include both architectural and interconnection requirements essential - for interoperability and may also include supporting source code artifacts - where such architectural, interconnection requirements and source code - artifacts are expressly identified as being required or documentation to - achieve compliance with the Advanced Messaging Queue Protocol Specification. - - As used hereunder, "Licensed Products" means only those specific portions - of products (hardware, software or combinations thereof) that implement - and are compliant with all relevant portions of the Advanced Messaging - Queue Protocol Specification. - - The following disclaimers, which you hereby also acknowledge as to any - use you may make of the Advanced Messaging Queue Protocol Specification: - - THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION IS PROVIDED "AS IS," - AND THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR - IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE - CONTENTS OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION ARE - SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF THE ADVANCED - MESSAGING QUEUE PROTOCOL SPECIFICATION WILL NOT INFRINGE ANY THIRD PARTY - PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. - - THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, - INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY - USE, IMPLEMENTATION OR DISTRIBUTION OF THE ADVANCED MESSAGING QUEUE - PROTOCOL SPECIFICATION. - - The name and trademarks of the Authors may NOT be used in any manner, - including advertising or publicity pertaining to the Advanced Messaging - Queue Protocol Specification or its contents without specific, written - prior permission. Title to copyright in the Advanced Messaging Queue - Protocol Specification will at all times remain with the Authors. - - No other rights are granted by implication, estoppel or otherwise. - - Upon termination of your license or rights under this Agreement, you - shall destroy all copies of the Advanced Messaging Queue Protocol - Specification in your possession or control. - - Trademarks - ========== - "JPMorgan", "JPMorgan Chase", "Chase", the JPMorgan Chase logo and the - Octagon Symbol are trademarks of JPMorgan Chase & Co. - - IMATIX and the iMatix logo are trademarks of iMatix Corporation sprl. - - IONA, IONA Technologies, and the IONA logos are trademarks of IONA - Technologies PLC and/or its subsidiaries. - - LINUX is a trademark of Linus Torvalds. RED HAT and JBOSS are registered - trademarks of Red Hat, Inc. in the US and other countries. - - Java, all Java-based trademarks and OpenOffice.org are trademarks of - Sun Microsystems, Inc. in the United States, other countries, or both. - - Other company, product, or service names may be trademarks or service - marks of others. - - Links to full AMQP specification: - ================================= - http://www.envoytech.org/spec/amq/ - http://www.iona.com/opensource/amqp/ - http://www.redhat.com/solutions/specifications/amqp/ - http://www.twiststandards.org/tiki-index.php?page=AMQ - http://www.imatix.com/amqp ---> - -<!-- - <!DOCTYPE amqp SYSTEM "amqp.dtd"> ---> - -<!-- XML Notes - - We use entities to indicate repetition; attributes to indicate properties. - - We use the 'name' attribute as an identifier, usually within the context - of the surrounding entities. - - We use spaces to seperate words in names, so that we can print names in - their natural form depending on the context - underlines for source code, - hyphens for written text, etc. - - We do not enforce any particular validation mechanism but we support all - mechanisms. The protocol definition conforms to a formal grammar that is - published seperately in several technologies. - - --> - -<amqp major = "0" minor = "10" port = "5672" comment = "AMQ Protocol"> - <!-- - ====================================================== - == CONSTANTS - ====================================================== - --> - <!-- Frame types --> - <constant name = "frame-method" value = "1" /> - <constant name = "frame-header" value = "2" /> - <constant name = "frame-body" value = "3" /> - <constant name = "frame-oob-method" value = "4" /> - <constant name = "frame-oob-header" value = "5" /> - <constant name = "frame-oob-body" value = "6" /> - <constant name = "frame-trace" value = "7" /> - <constant name = "frame-heartbeat" value = "8" /> - - <!-- Protocol constants --> - <constant name = "frame-min-size" value = "4096" /> - <constant name = "frame-end" value = "206" /> - - <!-- Reply codes --> - <constant name = "reply-success" value = "200"> - <doc> - Indicates that the method completed successfully. This reply code is - reserved for future use - the current protocol design does not use positive - confirmation and reply codes are sent only in case of an error. - </doc> - </constant> - - <constant name = "not-delivered" value = "310" class = "soft-error"> - <doc> - The client asked for a specific message that is no longer available. - The message was delivered to another client, or was purged from the queue - for some other reason. - </doc> - </constant> - - <constant name = "content-too-large" value = "311" class = "soft-error"> - <doc> - The client attempted to transfer content larger than the server could accept - at the present time. The client may retry at a later time. - </doc> - </constant> - - <constant name = "connection-forced" value = "320" class = "hard-error"> - <doc> - An operator intervened to close the connection for some reason. The client - may retry at some later date. - </doc> - </constant> - - <constant name = "invalid-path" value = "402" class = "hard-error"> - <doc> - The client tried to work with an unknown virtual host. - </doc> - </constant> - - <constant name = "access-refused" value = "403" class = "soft-error"> - <doc> - The client attempted to work with a server entity to which it has no - access due to security settings. - </doc> - </constant> - - <constant name = "not-found" value = "404" class = "soft-error"> - <doc>The client attempted to work with a server entity that does not exist.</doc> - </constant> - - <constant name = "resource-locked" value = "405" class = "soft-error"> - <doc> - The client attempted to work with a server entity to which it has no - access because another client is working with it. - </doc> - </constant> - - <constant name = "precondition-failed" value = "406" class = "soft-error"> - <doc> - The client requested a method that was not allowed because some precondition - failed. - </doc> - </constant> - - <constant name = "frame-error" value = "501" class = "hard-error"> - <doc> - The client sent a malformed frame that the server could not decode. This - strongly implies a programming error in the client. - </doc> - </constant> - - <constant name = "syntax-error" value = "502" class = "hard-error"> - <doc> - The client sent a frame that contained illegal values for one or more - fields. This strongly implies a programming error in the client. - </doc> - </constant> - - <constant name = "command-invalid" value = "503" class = "hard-error"> - <doc> - The client sent an invalid sequence of frames, attempting to perform an - operation that was considered invalid by the server. This usually implies - a programming error in the client. - </doc> - </constant> - - <constant name = "channel-error" value = "504" class = "hard-error"> - <doc> - The client attempted to work with a channel that had not been correctly - opened. This most likely indicates a fault in the client layer. - </doc> - </constant> - - <constant name = "resource-error" value = "506" class = "hard-error"> - <doc> - The server could not complete the method because it lacked sufficient - resources. This may be due to the client creating too many of some type - of entity. - </doc> - </constant> - - <constant name = "not-allowed" value = "530" class = "hard-error"> - <doc> - The client tried to work with some entity in a manner that is prohibited - by the server, due to security settings or by some other criteria. - </doc> - </constant> - - <constant name = "not-implemented" value = "540" class = "hard-error"> - <doc> - The client tried to use functionality that is not implemented in the - server. - </doc> - </constant> - - <constant name = "internal-error" value = "545" class = "hard-error"> - <doc> - The server could not complete the method because of an internal error. - The server may require intervention by an operator in order to resume - normal operations. - </doc> - </constant> - - <constant name = "test-double" value = "3.141592654"/> - <constant name = "test-str1" value = "hello, world!"/> - <constant name = "test-str2" value = "1.2.3.4"/> - - <!-- - ====================================================== - == DOMAIN TYPES - ====================================================== - --> - - <domain name = "access-ticket" type = "short" label = "access ticket granted by server"> - <doc> - An access ticket granted by the server for a certain set of access rights - within a specific realm. Access tickets are valid within the channel where - they were created, and expire when the channel closes. - </doc> - <assert check = "ne" value = "0" /> - </domain> - - <domain name = "class-id" type = "short" /> - - <domain name = "consumer-tag" type = "shortstr" label = "consumer tag"> - <doc> - Identifier for the consumer, valid within the current connection. - </doc> - </domain> - - <domain name = "delivery-tag" type = "longlong" label = "server-assigned delivery tag"> - <doc> - The server-assigned and channel-specific delivery tag - </doc> - <rule name = "channel-local"> - <doc> - The delivery tag is valid only within the channel from which the message was - received. I.e. a client MUST NOT receive a message on one channel and then - acknowledge it on another. - </doc> - </rule> - <rule name = "non-zero"> - <doc> - The server MUST NOT use a zero value for delivery tags. Zero is reserved - for client use, meaning "all messages so far received". - </doc> - </rule> - </domain> - - <domain name = "exchange-name" type = "shortstr" label = "exchange name"> - <doc> - The exchange name is a client-selected string that identifies the exchange for publish - methods. Exchange names may consist of any mixture of digits, letters, and underscores. - Exchange names are scoped by the virtual host. - </doc> - <assert check = "length" value = "127" /> - </domain> - - <domain name = "known-hosts" type = "shortstr" label = "list of known hosts"> - <doc> - Specifies the list of equivalent or alternative hosts that the server knows about, - which will normally include the current server itself. Clients can cache this - information and use it when reconnecting to a server after a failure. This field - may be empty. - </doc> - </domain> - - <domain name = "method-id" type = "long" /> - - <domain name = "no-ack" type = "bit" label = "no acknowledgement needed"> - <doc> - If this field is set the server does not expect acknowledgments for - messages. That is, when a message is delivered to the client the server - automatically and silently acknowledges it on behalf of the client. This - functionality increases performance but at the cost of reliability. - Messages can get lost if a client dies before it can deliver them to the - application. - </doc> - </domain> - - <domain name = "no-local" type = "bit" label = "do not deliver own messages"> - <doc> - If the no-local field is set the server will not send messages to the client that - published them. - </doc> - </domain> - - <domain name = "path" type = "shortstr"> - <doc> - Must start with a slash "/" and continue with path names separated by slashes. A path - name consists of any combination of at least one of [A-Za-z0-9] plus zero or more of - [.-_+!=:]. - </doc> - - <assert check = "notnull" /> - <assert check = "syntax" rule = "path" /> - <assert check = "length" value = "127" /> - </domain> - - <domain name = "peer-properties" type = "table"> - <doc> - This string provides a set of peer properties, used for identification, debugging, and - general information. - </doc> - </domain> - - <domain name = "queue-name" type = "shortstr" label = "queue name"> - <doc> - The queue name identifies the queue within the vhost. Queue names may consist of any - mixture of digits, letters, and underscores. - </doc> - <assert check = "length" value = "127" /> - </domain> - - <domain name = "redelivered" type = "bit" label = "message is being redelivered"> - <doc> - This indicates that the message has been previously delivered to this or - another client. - </doc> - <rule name = "implementation"> - <doc> - The server SHOULD try to signal redelivered messages when it can. When - redelivering a message that was not successfully acknowledged, the server - SHOULD deliver it to the original client if possible. - </doc> - <doc type = "scenario"> - Create a shared queue and publish a message to the queue. Consume the - message using explicit acknowledgements, but do not acknowledge the - message. Close the connection, reconnect, and consume from the queue - again. The message should arrive with the redelivered flag set. - </doc> - </rule> - <rule name = "hinting"> - <doc> - The client MUST NOT rely on the redelivered field but should take it as a - hint that the message may already have been processed. A fully robust - client must be able to track duplicate received messages on non-transacted, - and locally-transacted channels. - </doc> - </rule> - </domain> - - <domain name = "reply-code" type = "short" label = "reply code from server"> - <doc> - The reply code. The AMQ reply codes are defined as constants at the start - of this formal specification. - </doc> - <assert check = "notnull" /> - </domain> - - <domain name = "reply-text" type = "shortstr" label = "localised reply text"> - <doc> - The localised reply text. This text can be logged as an aid to resolving - issues. - </doc> - <assert check = "notnull" /> - </domain> - - <!-- Elementary domains --> - <domain name = "bit" type = "bit" label = "single bit" /> - <domain name = "octet" type = "octet" label = "single octet" /> - <domain name = "short" type = "short" label = "16-bit integer" /> - <domain name = "long" type = "long" label = "32-bit integer" /> - <domain name = "longlong" type = "longlong" label = "64-bit integer" /> - <domain name = "shortstr" type = "shortstr" label = "short string" /> - <domain name = "longstr" type = "longstr" label = "long string" /> - <domain name = "timestamp" type = "timestamp" label = "64-bit timestamp" /> - <domain name = "table" type = "table" label = "field table" /> - - <!-- == CONNECTION ======================================================= --> - - <!-- TODO 0.81 - the 'handler' attribute of methods needs to be reviewed, and if - no current implementations use it, removed. /PH 2006/07/20 - --> - - <class name = "connection" handler = "connection" index = "10" label = "work with socket connections"> - <doc> - The connection class provides methods for a client to establish a network connection to - a server, and for both peers to operate the connection thereafter. - </doc> - - <doc type = "grammar"> - connection = open-connection *use-connection close-connection - open-connection = C:protocol-header - S:START C:START-OK - *challenge - S:TUNE C:TUNE-OK - C:OPEN S:OPEN-OK | S:REDIRECT - challenge = S:SECURE C:SECURE-OK - use-connection = *channel - close-connection = C:CLOSE S:CLOSE-OK - / S:CLOSE C:CLOSE-OK - </doc> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "start" synchronous = "1" index = "10" label = "start connection negotiation"> - <doc> - This method starts the connection negotiation process by telling the client the - protocol version that the server proposes, along with a list of security mechanisms - which the client can use for authentication. - </doc> - - <rule name = "protocol-name"> - <doc> - If the server cannot support the protocol specified in the protocol header, - it MUST close the socket connection without sending any response method. - </doc> - <doc type = "scenario"> - The client sends a protocol header containing an invalid protocol name. - The server must respond by closing the connection. - </doc> - </rule> - <rule name = "server-support"> - <doc> - The server MUST provide a protocol version that is lower than or equal to - that requested by the client in the protocol header. - </doc> - <doc type = "scenario"> - The client requests a protocol version that is higher than any valid - implementation, e.g. 9.0. The server must respond with a current - protocol version, e.g. 1.0. - </doc> - </rule> - <rule name = "client-support"> - <doc> - If the client cannot handle the protocol version suggested by the server - it MUST close the socket connection. - </doc> - <doc type = "scenario"> - The server sends a protocol version that is lower than any valid - implementation, e.g. 0.1. The client must respond by closing the - connection. - </doc> - </rule> - - <chassis name = "client" implement = "MUST" /> - <response name = "start-ok" /> - - <field name = "version-major" domain = "octet" label = "protocol major version"> - <doc> - The version of the protocol, expressed in protocol units of 0.1 public - versions and properly printed as two digits with a leading zero. I.e. a - protocol version of "09" represents a public version "0.9". The decimal - shift allows the correct expression of pre-1.0 protocol releases. - </doc> - <doc type = "todo"> - This field should be renamed to "protocol version". - </doc> - </field> - - <field name = "version-minor" domain = "octet" label = "protocol major version"> - <doc> - The protocol revision, expressed as an integer from 0 to 9. The use of more - than ten revisions is discouraged. The public version string is constructed - from the protocol version and revision as follows: we print the protocol - version with one decimal position, and we append the protocol revision. A - version=10 and revision=2 are printed as "1.02". - </doc> - <doc type = "todo"> - This field should be renamed to "protocol revision". - </doc> - </field> - - <field name = "server-properties" domain = "peer-properties" label = "server properties"> - <rule name = "required-fields"> - <doc> - The properties SHOULD contain at least these fields: "host", specifying the - server host name or address, "product", giving the name of the server product, - "version", giving the name of the server version, "platform", giving the name - of the operating system, "copyright", if appropriate, and "information", giving - other general information. - </doc> - <doc type = "scenario"> - Client connects to server and inspects the server properties. It checks for - the presence of the required fields. - </doc> - </rule> - </field> - - <field name = "mechanisms" domain = "longstr" label = "available security mechanisms"> - <doc> - A list of the security mechanisms that the server supports, delimited by spaces. - Currently ASL supports these mechanisms: PLAIN. - </doc> - <assert check = "notnull" /> - </field> - - <field name = "locales" domain = "longstr" label = "available message locales"> - <doc> - A list of the message locales that the server supports, delimited by spaces. The - locale defines the language in which the server will send reply texts. - </doc> - <rule name = "required-support"> - <doc> - The server MUST support at least the en_US locale. - </doc> - <doc type = "scenario"> - Client connects to server and inspects the locales field. It checks for - the presence of the required locale(s). - </doc> - </rule> - <assert check = "notnull" /> - </field> - </method> - - <method name = "start-ok" synchronous = "1" index = "11" - label = "select security mechanism and locale"> - <doc> - This method selects a SASL security mechanism. ASL uses SASL (RFC2222) to - negotiate authentication and encryption. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "client-properties" domain = "peer-properties" label = "client properties"> - <rule name = "required-fields"> - <!-- This rule is not testable from the client side --> - <doc> - The properties SHOULD contain at least these fields: "product", giving the name - of the client product, "version", giving the name of the client version, "platform", - giving the name of the operating system, "copyright", if appropriate, and - "information", giving other general information. - </doc> - </rule> - </field> - - <field name = "mechanism" domain = "shortstr" label = "selected security mechanism"> - <doc> - A single security mechanisms selected by the client, which must be one of those - specified by the server. - </doc> - <rule name = "security"> - <doc> - The client SHOULD authenticate using the highest-level security profile it - can handle from the list provided by the server. - </doc> - </rule> - <rule name = "validity"> - <doc> - If the mechanism field does not contain one of the security mechanisms - proposed by the server in the Start method, the server MUST close the - connection without sending any further data. - </doc> - <doc type = "scenario"> - Client connects to server and sends an invalid security mechanism. The - server must respond by closing the connection (a socket close, with no - connection close negotiation). - </doc> - </rule> - <assert check = "notnull" /> - </field> - - <field name = "response" domain = "longstr" label = "security response data"> - <doc> - A block of opaque data passed to the security mechanism. The contents of this - data are defined by the SASL security mechanism. - </doc> - <assert check = "notnull" /> - </field> - - <field name = "locale" domain = "shortstr" label = "selected message locale"> - <doc> - A single message local selected by the client, which must be one of those - specified by the server. - </doc> - <assert check = "notnull" /> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "secure" synchronous = "1" index = "20" label = "security mechanism challenge"> - <doc> - The SASL protocol works by exchanging challenges and responses until both peers have - received sufficient information to authenticate each other. This method challenges - the client to provide more information. - </doc> - - <chassis name = "client" implement = "MUST" /> - <response name = "secure-ok" /> - - <field name = "challenge" domain = "longstr" label = "security challenge data"> - <doc> - Challenge information, a block of opaque binary data passed to the security - mechanism. - </doc> - </field> - </method> - - <method name = "secure-ok" synchronous = "1" index = "21" label = "security mechanism response"> - <doc> - This method attempts to authenticate, passing a block of SASL data for the security - mechanism at the server side. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "response" domain = "longstr" label = "security response data"> - <doc> - A block of opaque data passed to the security mechanism. The contents of this - data are defined by the SASL security mechanism. - </doc> - <assert check = "notnull" /> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "tune" synchronous = "1" index = "30" - label = "propose connection tuning parameters"> - <doc> - This method proposes a set of connection configuration values to the client. The - client can accept and/or adjust these. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <response name = "tune-ok" /> - - <field name = "channel-max" domain = "short" label = "proposed maximum channels"> - <doc> - The maximum total number of channels that the server allows per connection. Zero - means that the server does not impose a fixed limit, but the number of allowed - channels may be limited by available server resources. - </doc> - </field> - - <field name = "frame-max" domain = "long" label = "proposed maximum frame size"> - <doc> - The largest frame size that the server proposes for the connection. The client - can negotiate a lower value. Zero means that the server does not impose any - specific limit but may reject very large frames if it cannot allocate resources - for them. - </doc> - <rule name = "minimum"> - <doc> - Until the frame-max has been negotiated, both peers MUST accept frames of up - to frame-min-size octets large, and the minimum negotiated value for frame-max - is also frame-min-size. - </doc> - <doc type = "scenario"> - Client connects to server and sends a large properties field, creating a frame - of frame-min-size octets. The server must accept this frame. - </doc> - </rule> - </field> - - <field name = "heartbeat" domain = "short" label = "desired heartbeat delay"> - <!-- TODO 0.82 - the heartbeat negotiation mechanism was changed during - implementation because the model documented here does not actually - work properly. The best model we found is that the server proposes - a heartbeat value to the client; the client can reply with zero, meaning - 'do not use heartbeats (as documented here), or can propose its own - heartbeat value, which the server should then accept. This is different - from the model here which is disconnected - e.g. each side requests a - heartbeat independently. Basically a connection is heartbeated in - both ways, or not at all, depending on whether both peers support - heartbeating or not, and the heartbeat value should itself be chosen - by the client so that remote links can get a higher value. Also, the - actual heartbeat mechanism needs documentation, and is as follows: so - long as there is activity on a connection - in or out - both peers - assume the connection is active. When there is no activity, each peer - must send heartbeat frames. When no heartbeat frame is received after - N cycles (where N is at least 2), the connection can be considered to - have died. /PH 2006/07/19 - --> - <doc> - The delay, in seconds, of the connection heartbeat that the server wants. - Zero means the server does not want a heartbeat. - </doc> - </field> - </method> - - <method name = "tune-ok" synchronous = "1" index = "31" - label = "negotiate connection tuning parameters"> - <doc> - This method sends the client's connection tuning parameters to the server. - Certain fields are negotiated, others provide capability information. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "channel-max" domain = "short" label = "negotiated maximum channels"> - <doc> - The maximum total number of channels that the client will use per connection. - </doc> - <rule name = "upper-limit"> - <doc> - If the client specifies a channel max that is higher than the value provided - by the server, the server MUST close the connection without attempting a - negotiated close. The server may report the error in some fashion to assist - implementors. - </doc> - </rule> - <assert check = "notnull" /> - <assert check = "le" method = "tune" field = "channel-max" /> - </field> - - <field name = "frame-max" domain = "long" label = "negotiated maximum frame size"> - <doc> - The largest frame size that the client and server will use for the connection. - Zero means that the client does not impose any specific limit but may reject - very large frames if it cannot allocate resources for them. Note that the - frame-max limit applies principally to content frames, where large contents can - be broken into frames of arbitrary size. - </doc> - <rule name = "minimum"> - <doc> - Until the frame-max has been negotiated, both peers MUST accept frames of up - to frame-min-size octets large, and the minimum negotiated value for frame-max - is also frame-min-size. - </doc> - </rule> - <rule name = "upper-limit"> - <doc> - If the client specifies a frame max that is higher than the value provided - by the server, the server MUST close the connection without attempting a - negotiated close. The server may report the error in some fashion to assist - implementors. - </doc> - </rule> - </field> - - <field name = "heartbeat" domain = "short" label = "desired heartbeat delay"> - <doc> - The delay, in seconds, of the connection heartbeat that the client wants. Zero - means the client does not want a heartbeat. - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "open" synchronous = "1" index = "40" label = "open connection to virtual host"> - <doc> - This method opens a connection to a virtual host, which is a collection of - resources, and acts to separate multiple application domains within a server. - The server may apply arbitrary limits per virtual host, such as the number - of each type of entity that may be used, per connection and/or in total. - </doc> - - <chassis name = "server" implement = "MUST" /> - <response name = "open-ok" /> - <response name = "redirect" /> - - <field name = "virtual-host" domain = "path" label = "virtual host name"> - <!-- TODO 0.82 - the entire vhost model needs review. This concept was - prompted by the HTTP vhost concept but does not fit very well into - AMQP. Currently we use the vhost as a "cluster identifier" which is - inaccurate usage. /PH 2006/07/19 - --> - <assert check = "regexp" value = "^[a-zA-Z0-9/-_]+$" /> - <doc> - The name of the virtual host to work with. - </doc> - <rule name = "separation"> - <doc> - If the server supports multiple virtual hosts, it MUST enforce a full - separation of exchanges, queues, and all associated entities per virtual - host. An application, connected to a specific virtual host, MUST NOT be able - to access resources of another virtual host. - </doc> - </rule> - <rule name = "security"> - <doc> - The server SHOULD verify that the client has permission to access the - specified virtual host. - </doc> - </rule> - </field> - - <field name = "capabilities" domain = "shortstr" label = "required capabilities"> - <doc> - The client can specify zero or more capability names, delimited by spaces. - The server can use this string to how to process the client's connection - request. - </doc> - </field> - - <field name = "insist" domain = "bit" label = "insist on connecting to server"> - <doc> - In a configuration with multiple collaborating servers, the server may respond - to a Connection.Open method with a Connection.Redirect. The insist option tells - the server that the client is insisting on a connection to the specified server. - </doc> - <rule name = "behaviour"> - <doc> - When the client uses the insist option, the server MUST NOT respond with a - Connection.Redirect method. If it cannot accept the client's connection - request it should respond by closing the connection with a suitable reply - code. - </doc> - </rule> - </field> - </method> - - <method name = "open-ok" synchronous = "1" index = "41" label = "signal that connection is ready"> - <doc> - This method signals to the client that the connection is ready for use. - </doc> - <chassis name = "client" implement = "MUST" /> - <field name = "known-hosts" domain = "known-hosts" /> - </method> - - <method name = "redirect" synchronous = "1" index = "42" label = "redirects client to other server"> - <doc> - This method redirects the client to another server, based on the requested virtual - host and/or capabilities. - </doc> - <rule name = "usage"> - <doc> - When getting the Connection.Redirect method, the client SHOULD reconnect to - the host specified, and if that host is not present, to any of the hosts - specified in the known-hosts list. - </doc> - </rule> - <chassis name = "client" implement = "MUST" /> - <field name = "host" domain = "shortstr" label = "server to connect to"> - <doc> - Specifies the server to connect to. This is an IP address or a DNS name, - optionally followed by a colon and a port number. If no port number is - specified, the client should use the default port number for the protocol. - </doc> - <assert check = "notnull" /> - </field> - <field name = "known-hosts" domain = "known-hosts" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "close" synchronous = "1" index = "50" label = "request a connection close"> - <doc> - This method indicates that the sender wants to close the connection. This may be - due to internal conditions (e.g. a forced shut-down) or due to an error handling - a specific method, i.e. an exception. When a close is due to an exception, the - sender provides the class and method id of the method which caused the exception. - </doc> - <!-- TODO: the connection close mechanism needs to be reviewed from the ODF - documentation and better expressed as rules here. /PH 2006/07/20 - --> - <rule name = "stability"> - <doc> - After sending this method any received method except the Close-OK method MUST - be discarded. - </doc> - </rule> - - <chassis name = "client" implement = "MUST" /> - <chassis name = "server" implement = "MUST" /> - <response name = "close-ok" /> - - <field name = "reply-code" domain = "reply-code" /> - <field name = "reply-text" domain = "reply-text" /> - - <field name = "class-id" domain = "class-id" label = "failing method class"> - <doc> - When the close is provoked by a method exception, this is the class of the - method. - </doc> - </field> - - <field name = "method-id" domain = "method-id" label = "failing method ID"> - <doc> - When the close is provoked by a method exception, this is the ID of the method. - </doc> - </field> - </method> - - <method name = "close-ok" synchronous = "1" index = "51" label = "confirm a connection close"> - <doc> - This method confirms a Connection.Close method and tells the recipient that it is - safe to release resources for the connection and close the socket. - </doc> - <rule name = "reporting"> - <doc> - A peer that detects a socket closure without having received a Close-Ok - handshake method SHOULD log the error. - </doc> - </rule> - <chassis name = "client" implement = "MUST" /> - <chassis name = "server" implement = "MUST" /> - </method> - </class> - - <!-- == CHANNEL ========================================================== --> - - <class name = "channel" handler = "channel" index = "20" label = "work with channels"> - <doc> - The channel class provides methods for a client to establish a channel to a - server and for both peers to operate the channel thereafter. - </doc> - - <doc type = "grammar"> - channel = open-channel *use-channel close-channel - open-channel = C:OPEN S:OPEN-OK - use-channel = C:FLOW S:FLOW-OK - / S:FLOW C:FLOW-OK - / S:ALERT - / functional-class - close-channel = C:CLOSE S:CLOSE-OK - / S:CLOSE C:CLOSE-OK - </doc> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "open" synchronous = "1" index = "10" label = "open a channel for use"> - <doc> - This method opens a channel to the server. - </doc> - <rule name = "state" on-failure = "channel-error"> - <doc> - The client MUST NOT use this method on an alread-opened channel. - </doc> - <doc type = "scenario"> - Client opens a channel and then reopens the same channel. - </doc> - </rule> - <chassis name = "server" implement = "MUST" /> - <response name = "open-ok" /> - <field name = "out of band" domain = "shortstr" label = "out-of-band settings"> - <doc> - Configures out-of-band transfers on this channel. The syntax and meaning of this - field will be formally defined at a later date. - </doc> - <assert check = "null" /> - </field> - </method> - - <method name = "open-ok" synchronous = "1" index = "11" label = "signal that the channel is ready"> - <doc> - This method signals to the client that the channel is ready for use. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "flow" synchronous = "1" index = "20" label = "enable/disable flow from peer"> - <doc> - This method asks the peer to pause or restart the flow of content data. This is a - simple flow-control mechanism that a peer can use to avoid oveflowing its queues or - otherwise finding itself receiving more messages than it can process. Note that this - method is not intended for window control. The peer that receives a disable flow - method should finish sending the current content frame, if any, then pause. - </doc> - - <rule name = "initial-state"> - <doc> - When a new channel is opened, it is active (flow is active). Some applications - assume that channels are inactive until started. To emulate this behaviour a - client MAY open the channel, then pause it. - </doc> - </rule> - - <rule name = "bidirectional"> - <doc> - When sending content frames, a peer SHOULD monitor the channel for incoming - methods and respond to a Channel.Flow as rapidly as possible. - </doc> - </rule> - - <rule name = "throttling"> - <doc> - A peer MAY use the Channel.Flow method to throttle incoming content data for - internal reasons, for example, when exchanging data over a slower connection. - </doc> - </rule> - - <rule name = "expected-behaviour"> - <doc> - The peer that requests a Channel.Flow method MAY disconnect and/or ban a peer - that does not respect the request. This is to prevent badly-behaved clients - from overwhelming a broker. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <response name = "flow-ok" /> - - <field name = "active" domain = "bit" label = "start/stop content frames"> - <doc> - If 1, the peer starts sending content frames. If 0, the peer stops sending - content frames. - </doc> - </field> - </method> - - <method name = "flow-ok" index = "21" label = "confirm a flow method"> - <doc> - Confirms to the peer that a flow command was received and processed. - </doc> - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - <field name = "active" domain = "bit" label = "current flow setting"> - <doc> - Confirms the setting of the processed flow method: 1 means the peer will start - sending or continue to send content frames; 0 means it will not. - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <!-- TODO 0.82 - remove this method entirely - /PH 2006/07/20 - --> - <method name = "alert" index = "30" label = "send a non-fatal warning message"> - <doc> - This method allows the server to send a non-fatal warning to the client. This is - used for methods that are normally asynchronous and thus do not have confirmations, - and for which the server may detect errors that need to be reported. Fatal errors - are handled as channel or connection exceptions; non-fatal errors are sent through - this method. - </doc> - <chassis name = "client" implement = "MUST" /> - <field name = "reply-code" domain = "reply-code" /> - <field name = "reply-text" domain = "reply-text" /> - <field name = "details" domain = "table" label = "detailed information for warning"> - <doc> - A set of fields that provide more information about the problem. The meaning of - these fields are defined on a per-reply-code basis (TO BE DEFINED). - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "close" synchronous = "1" index = "40" label = "request a channel close"> - <doc> - This method indicates that the sender wants to close the channel. This may be due to - internal conditions (e.g. a forced shut-down) or due to an error handling a specific - method, i.e. an exception. When a close is due to an exception, the sender provides - the class and method id of the method which caused the exception. - </doc> - - <!-- TODO: the channel close behaviour needs to be reviewed from the ODF - documentation and better expressed as rules here. /PH 2006/07/20 - --> - <rule name = "stability"> - <doc> - After sending this method any received method except the Close-OK method MUST - be discarded. - </doc> - </rule> - - <chassis name = "client" implement = "MUST" /> - <chassis name = "server" implement = "MUST" /> - <response name = "close-ok" /> - - <field name = "reply-code" domain = "reply-code" /> - <field name = "reply-text" domain = "reply-text" /> - - <field name = "class-id" domain = "class-id" label = "failing method class"> - <doc> - When the close is provoked by a method exception, this is the class of the - method. - </doc> - </field> - - <field name = "method-id" domain = "method-id" label = "failing method ID"> - <doc> - When the close is provoked by a method exception, this is the ID of the method. - </doc> - </field> - </method> - - <method name = "close-ok" synchronous = "1" index = "41" label = "confirm a channel close"> - <doc> - This method confirms a Channel.Close method and tells the recipient that it is safe - to release resources for the channel and close the socket. - </doc> - <rule name = "reporting"> - <doc> - A peer that detects a socket closure without having received a Channel.Close-Ok - handshake method SHOULD log the error. - </doc> - </rule> - <chassis name = "client" implement = "MUST" /> - <chassis name = "server" implement = "MUST" /> - </method> - </class> - - <!-- == ACCESS =========================================================== --> - - <!-- TODO 0.82 - this class must be implemented by two teams before we can - consider it matured. - --> - - <class name = "access" handler = "connection" index = "30" label = "work with access tickets"> - <doc> - The protocol control access to server resources using access tickets. A - client must explicitly request access tickets before doing work. An access - ticket grants a client the right to use a specific set of resources - - called a "realm" - in specific ways. - </doc> - - <doc type = "grammar"> - access = C:REQUEST S:REQUEST-OK - </doc> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "request" synchronous = "1" index = "10" label = "request an access ticket"> - <doc> - This method requests an access ticket for an access realm. The server - responds by granting the access ticket. If the client does not have - access rights to the requested realm this causes a connection exception. - Access tickets are a per-channel resource. - </doc> - - <chassis name = "server" implement = "MUST" /> - <response name = "request-ok" /> - - <field name = "realm" domain = "shortstr" label = "name of requested realm"> - <doc> - Specifies the name of the realm to which the client is requesting access. - The realm is a configured server-side object that collects a set of - resources (exchanges, queues, etc.). If the channel has already requested - an access ticket onto this realm, the previous ticket is destroyed and a - new ticket is created with the requested access rights, if allowed. - </doc> - <rule name = "validity" on-failure = "access-refused"> - <doc> - The client MUST specify a realm that is known to the server. The server - makes an identical response for undefined realms as it does for realms - that are defined but inaccessible to this client. - </doc> - <doc type = "scenario"> - Client specifies an undefined realm. - </doc> - </rule> - </field> - - <field name = "exclusive" domain = "bit" label = "request exclusive access"> - <doc> - Request exclusive access to the realm, meaning that this will be the only - channel that uses the realm's resources. - </doc> - <rule name = "validity" on-failure = "access-refused"> - <doc> - The client MAY NOT request exclusive access to a realm that has active - access tickets, unless the same channel already had the only access - ticket onto that realm. - </doc> - <doc type = "scenario"> - Client opens two channels and requests exclusive access to the same realm. - </doc> - </rule> - </field> - <field name = "passive" domain = "bit" label = "request passive access"> - <doc> - Request message passive access to the specified access realm. Passive - access lets a client get information about resources in the realm but - not to make any changes to them. - </doc> - </field> - <field name = "active" domain = "bit" label = "request active access"> - <doc> - Request message active access to the specified access realm. Active access lets - a client get create and delete resources in the realm. - </doc> - </field> - <field name = "write" domain = "bit" label = "request write access"> - <doc> - Request write access to the specified access realm. Write access lets a client - publish messages to all exchanges in the realm. - </doc> - </field> - <field name = "read" domain = "bit" label = "request read access"> - <doc> - Request read access to the specified access realm. Read access lets a client - consume messages from queues in the realm. - </doc> - </field> - </method> - - <method name = "request-ok" synchronous = "1" index = "11" label = "grant access to server resources"> - <doc> - This method provides the client with an access ticket. The access ticket is valid - within the current channel and for the lifespan of the channel. - </doc> - <rule name = "per-channel" on-failure = "not-allowed"> - <doc> - The client MUST NOT use access tickets except within the same channel as - originally granted. - </doc> - <doc type = "scenario"> - Client opens two channels, requests a ticket on one channel, and then - tries to use that ticket in a seconc channel. - </doc> - </rule> - <chassis name = "client" implement = "MUST" /> - <field name = "ticket" domain = "access-ticket" /> - </method> - </class> - - <!-- == EXCHANGE ========================================================= --> - - <class name = "exchange" handler = "channel" index = "40" label = "work with exchanges"> - <doc> - Exchanges match and distribute messages across queues. Exchanges can be configured in - the server or created at runtime. - </doc> - - <doc type = "grammar"> - exchange = C:DECLARE S:DECLARE-OK - / C:DELETE S:DELETE-OK - </doc> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <rule name = "required-types"> - <doc> - The server MUST implement these standard exchange types: fanout, direct. - </doc> - <doc type = "scenario"> - Client attempts to declare an exchange with each of these standard types. - </doc> - </rule> - <rule name = "recommended-types"> - <doc> - The server SHOULD implement these standard exchange types: topic, headers. - </doc> - <doc type = "scenario"> - Client attempts to declare an exchange with each of these standard types. - </doc> - </rule> - <rule name = "required-instances"> - <doc> - The server MUST, in each virtual host, pre-declare an exchange instance - for each standard exchange type that it implements, where the name of the - exchange instance is "amq." followed by the exchange type name. - </doc> - <doc type = "scenario"> - Client creates a temporary queue and attempts to bind to each required - exchange instance (amq.fanout, amq.direct, and amq.topic, amq.headers if - those types are defined). - </doc> - </rule> - <rule name = "default-exchange"> - <doc> - The server MUST predeclare a direct exchange to act as the default exchange - for content Publish methods and for default queue bindings. - </doc> - <doc type = "scenario"> - Client checks that the default exchange is active by specifying a queue - binding with no exchange name, and publishing a message with a suitable - routing key but without specifying the exchange name, then ensuring that - the message arrives in the queue correctly. - </doc> - </rule> - <rule name = "default-access"> - <doc> - The server MUST NOT allow clients to access the default exchange except - by specifying an empty exchange name in the Queue.Bind and content Publish - methods. - </doc> - </rule> - <rule name = "extensions"> - <doc> - The server MAY implement other exchange types as wanted. - </doc> - </rule> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "declare" synchronous = "1" index = "10" label = "declare exchange, create if needed"> - <doc> - This method creates an exchange if it does not already exist, and if the exchange - exists, verifies that it is of the correct and expected class. - </doc> - <rule name = "minimum"> - <doc> - The server SHOULD support a minimum of 16 exchanges per virtual host and - ideally, impose no limit except as defined by available resources. - </doc> - <doc type = "scenario"> - The client creates as many exchanges as it can until the server reports - an error; the number of exchanges successfuly created must be at least - sixteen. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - <response name = "declare-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <doc> - When a client defines a new exchange, this belongs to the access realm of the - ticket used. All further work done with that exchange must be done with an - access ticket for the same realm. - </doc> - <rule name = "validity" on-failure = "access-refused"> - <doc> - The client MUST provide a valid access ticket giving "active" access to - the realm in which the exchange exists or will be created, or "passive" - access if the if-exists flag is set. - </doc> - <doc type = "scenario"> - Client creates access ticket with wrong access rights and attempts to use - in this method. - </doc> - </rule> - </field> - - <field name = "exchange" domain = "exchange-name"> - <rule name = "reserved" on-failure = "access-refused"> - <doc> - Exchange names starting with "amq." are reserved for predeclared and - standardised exchanges. The client MUST NOT attempt to create an exchange - starting with "amq.". - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - <assert check = "regexp" value = "^[a-zA-Z0-9-_.:]+$" /> - </field> - - <field name = "type" domain = "shortstr" label = "exchange type"> - <doc> - Each exchange belongs to one of a set of exchange types implemented by the - server. The exchange types define the functionality of the exchange - i.e. how - messages are routed through it. It is not valid or meaningful to attempt to - change the type of an existing exchange. - </doc> - <rule name = "typed" on-failure = "not-allowed"> - <doc> - Exchanges cannot be redeclared with different types. The client MUST not - attempt to redeclare an existing exchange with a different type than used - in the original Exchange.Declare method. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - <rule name = "support" on-failure = "command-invalid"> - <doc> - The client MUST NOT attempt to create an exchange with a type that the - server does not support. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - <assert check = "regexp" value = "^[a-zA-Z0-9-_.:]+$" /> - </field> - - <field name = "passive" domain = "bit" label = "do not create exchange"> - <doc> - If set, the server will not create the exchange. The client can use this to - check whether an exchange exists without modifying the server state. - </doc> - <rule name = "not-found"> - <doc> - If set, and the exchange does not already exist, the server MUST raise a - channel exception with reply code 404 (not found). - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <field name = "durable" domain = "bit" label = "request a durable exchange"> - <doc> - If set when creating a new exchange, the exchange will be marked as durable. - Durable exchanges remain active when a server restarts. Non-durable exchanges - (transient exchanges) are purged if/when a server restarts. - </doc> - <rule name = "support"> - <doc> - The server MUST support both durable and transient exchanges. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - <rule name = "sticky"> - <doc> - The server MUST ignore the durable field if the exchange already exists. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <!-- TODO 0.82 - clarify how this works; there is no way to cancel a binding - except by deleting a queue. - --> - <field name = "auto-delete" domain = "bit" label = "auto-delete when unused"> - <doc> - If set, the exchange is deleted when all queues have finished using it. - </doc> - <rule name = "sticky"> - <doc> - The server MUST ignore the auto-delete field if the exchange already - exists. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <field name = "internal" domain = "bit" label = "create internal exchange"> - <doc> - If set, the exchange may not be used directly by publishers, but only when bound - to other exchanges. Internal exchanges are used to construct wiring that is not - visible to applications. - </doc> - </field> - - <field name = "arguments" domain = "table" label = "arguments for declaration"> - <doc> - A set of arguments for the declaration. The syntax and semantics of these - arguments depends on the server implementation. This field is ignored if passive - is 1. - </doc> - </field> - </method> - - <method name = "declare-ok" synchronous = "1" index = "11" label = "confirm exchange declaration"> - <doc> - This method confirms a Declare method and confirms the name of the exchange, - essential for automatically-named exchanges. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "delete" synchronous = "1" index = "20" label = "delete an exchange"> - <doc> - This method deletes an exchange. When an exchange is deleted all queue bindings on - the exchange are cancelled. - </doc> - - <chassis name = "server" implement = "MUST" /> - <response name = "delete-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "validity" on-failure = "access-refused"> - <doc> - The client MUST provide a valid access ticket giving "active" access - rights to the exchange's access realm. - </doc> - <doc type = "scenario"> - Client creates access ticket with wrong access rights and attempts to use - in this method. - </doc> - </rule> - </field> - - <field name = "exchange" domain = "exchange-name"> - <rule name = "exists" on-failure = "not-found"> - <doc> - The client MUST NOT attempt to delete an exchange that does not exist. - </doc> - </rule> - <assert check = "notnull" /> - </field> - - <!-- TODO 0.82 - discuss whether this option is useful or not. I don't have - any real use case for it. /PH 2006-07-23. - --> - <field name = "if-unused" domain = "bit" label = "delete only if unused"> - <doc> - If set, the server will only delete the exchange if it has no queue bindings. If - the exchange has queue bindings the server does not delete it but raises a - channel exception instead. - </doc> - </field> - </method> - - <method name = "delete-ok" synchronous = "1" index = "21" - label = "confirm deletion of an exchange"> - <doc>This method confirms the deletion of an exchange.</doc> - <chassis name = "client" implement = "MUST" /> - </method> - </class> - - <!-- == QUEUE ============================================================ --> - - <class name = "queue" handler = "channel" index = "50" label = "work with queues"> - <doc> - Queues store and forward messages. Queues can be configured in the server or created at - runtime. Queues must be attached to at least one exchange in order to receive messages - from publishers. - </doc> - - <doc type = "grammar"> - queue = C:DECLARE S:DECLARE-OK - / C:BIND S:BIND-OK - / C:PURGE S:PURGE-OK - / C:DELETE S:DELETE-OK - </doc> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <rule name = "any-content"> - <doc> - A server MUST allow any content class to be sent to any queue, in any mix, and - queue and deliver these content classes independently. Note that all methods - that fetch content off queues are specific to a given content class. - </doc> - <doc type = "scenario"> - Client creates an exchange of each standard type and several queues that - it binds to each exchange. It must then sucessfully send each of the standard - content types to each of the available queues. - </doc> - </rule> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "declare" synchronous = "1" index = "10" label = "declare queue, create if needed"> - <doc> - This method creates or checks a queue. When creating a new queue the client can - specify various properties that control the durability of the queue and its - contents, and the level of sharing for the queue. - </doc> - - <rule name = "default-binding"> - <doc> - The server MUST create a default binding for a newly-created queue to the - default exchange, which is an exchange of type 'direct'. - </doc> - <doc type = "scenario"> - Client creates a new queue, and then without explicitly binding it to an - exchange, attempts to send a message through the default exchange binding, - i.e. publish a message to the empty exchange, with the queue name as routing - key. - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_35" --> - <rule name = "minimum-queues"> - <doc> - The server SHOULD support a minimum of 256 queues per virtual host and ideally, - impose no limit except as defined by available resources. - </doc> - <doc type = "scenario"> - Client attempts to create as many queues as it can until the server reports - an error. The resulting count must at least be 256. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - <response name = "declare-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <doc> - When a client defines a new queue, this belongs to the access realm of the - ticket used. All further work done with that queue must be done with an access - ticket for the same realm. - </doc> - <rule name = "validity" on-failure = "access-refused"> - <doc> - The client MUST provide a valid access ticket giving "active" access to - the realm in which the queue exists or will be created. - </doc> - <doc type = "scenario"> - Client creates access ticket with wrong access rights and attempts to use - in this method. - </doc> - </rule> - </field> - - <field name = "queue" domain = "queue-name"> - <rule name = "default-name"> - <doc> - The queue name MAY be empty, in which case the server MUST create a new - queue with a unique generated name and return this to the client in the - Declare-Ok method. - </doc> - <doc type = "scenario"> - Client attempts to create several queues with an empty name. The client then - verifies that the server-assigned names are unique and different. - </doc> - </rule> - <rule name = "reserved-prefix" on-failure = "not-allowed"> - <doc> - Queue names starting with "amq." are reserved for predeclared and - standardised server queues. A client MAY NOT attempt to declare a queue with a - name that starts with "amq." and the passive option set to zero. - </doc> - <doc type = "scenario"> - A client attempts to create a queue with a name starting with "amq." and with - the passive option set to zero. - </doc> - </rule> - <assert check = "regexp" value = "^[a-zA-Z0-9-_.:]*$" /> - </field> - - <field name = "passive" domain = "bit" label = "do not create queue"> - <doc> - If set, the server will not create the queue. This field allows the client - to assert the presence of a queue without modifying the server state. - </doc> - <rule name = "passive" on-failure = "not-found"> - <doc> - The client MAY ask the server to assert that a queue exists without - creating the queue if not. If the queue does not exist, the server - treats this as a failure. - </doc> - <doc type = "scenario"> - Client declares an existing queue with the passive option and expects - the server to respond with a declare-ok. Client then attempts to declare - a non-existent queue with the passive option, and the server must close - the channel with the correct reply-code. - </doc> - </rule> - </field> - - <field name = "durable" domain = "bit" label = "request a durable queue"> - <doc> - If set when creating a new queue, the queue will be marked as durable. Durable - queues remain active when a server restarts. Non-durable queues (transient - queues) are purged if/when a server restarts. Note that durable queues do not - necessarily hold persistent messages, although it does not make sense to send - persistent messages to a transient queue. - </doc> - <!-- Rule test name: was "amq_queue_03" --> - <rule name = "persistence"> - <doc>The server MUST recreate the durable queue after a restart.</doc> - - <!-- TODO: use 'client does something' rather than 'a client does something'. --> - <doc type = "scenario"> - A client creates a durable queue. The server is then restarted. The client - then attempts to send a message to the queue. The message should be successfully - delivered. - </doc> - </rule> - <!-- Rule test name: was "amq_queue_36" --> - <rule name = "types"> - <doc>The server MUST support both durable and transient queues.</doc> - <doc type = "scenario"> - A client creates two named queues, one durable and one transient. - </doc> - </rule> - <!-- Rule test name: was "amq_queue_37" --> - <rule name = "pre-existence"> - <doc>The server MUST ignore the durable field if the queue already exists.</doc> - <doc type = "scenario"> - A client creates two named queues, one durable and one transient. The client - then attempts to declare the two queues using the same names again, but reversing - the value of the durable flag in each case. Verify that the queues still exist - with the original durable flag values. - <!-- TODO: but how? --> - </doc> - </rule> - </field> - - <field name = "exclusive" domain = "bit" label = "request an exclusive queue"> - <doc> - Exclusive queues may only be consumed from by the current connection. Setting - the 'exclusive' flag always implies 'auto-delete'. - </doc> - - <!-- Rule test name: was "amq_queue_38" --> - <rule name = "types"> - <doc> - The server MUST support both exclusive (private) and non-exclusive (shared) - queues. - </doc> - <doc type = "scenario"> - A client creates two named queues, one exclusive and one non-exclusive. - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_04" --> - <rule name = "02" on-failure = "channel-error"> - <doc> - The client MAY NOT attempt to declare any existing and exclusive queue - on multiple connections. - </doc> - <doc type = "scenario"> - A client declares an exclusive named queue. A second client on a different - connection attempts to declare a queue of the same name. - </doc> - </rule> - </field> - - <field name = "auto-delete" domain = "bit" label = "auto-delete queue when unused"> - <doc> - If set, the queue is deleted when all consumers have finished using it. Last - consumer can be cancelled either explicitly or because its channel is closed. If - there was no consumer ever on the queue, it won't be deleted. - </doc> - - <!-- Rule test name: was "amq_queue_31" --> - <rule name = "pre-existence"> - <doc> - The server MUST ignore the auto-delete field if the queue already exists. - </doc> - <doc type = "scenario"> - A client creates two named queues, one as auto-delete and one explicit-delete. - The client then attempts to declare the two queues using the same names again, - but reversing the value of the auto-delete field in each case. Verify that the - queues still exist with the original auto-delete flag values. - <!-- TODO: but how? --> - </doc> - </rule> - </field> - - <field name = "arguments" domain = "table" label = "arguments for declaration"> - <doc> - A set of arguments for the declaration. The syntax and semantics of these - arguments depends on the server implementation. This field is ignored if passive - is 1. - </doc> - </field> - </method> - - <method name = "declare-ok" synchronous = "1" index = "11" label = "confirms a queue definition"> - <doc> - This method confirms a Declare method and confirms the name of the queue, essential - for automatically-named queues. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "queue" domain = "queue-name"> - <doc> - Reports the name of the queue. If the server generated a queue name, this field - contains that name. - </doc> - <assert check = "notnull" /> - </field> - - <field name = "message-count" domain = "long" label = "number of messages in queue"> - <doc> - Reports the number of messages in the queue, which will be zero for - newly-created queues. - </doc> - </field> - - <field name = "consumer-count" domain = "long" label = "number of consumers"> - <doc> - Reports the number of active consumers for the queue. Note that consumers can - suspend activity (Channel.Flow) in which case they do not appear in this count. - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "bind" synchronous = "1" index = "20" label = "bind queue to an exchange"> - <doc> - This method binds a queue to an exchange. Until a queue is bound it will not receive - any messages. In a classic messaging model, store-and-forward queues are bound to a - dest exchange and subscription queues are bound to a dest_wild exchange. - </doc> - - <!-- Rule test name: was "amq_queue_25" --> - <rule name = "duplicates"> - <doc> - A server MUST allow ignore duplicate bindings - that is, two or more bind - methods for a specific queue, with identical arguments - without treating these - as an error. - </doc> - <doc type = "scenario"> - A client binds a named queue to an exchange. The client then repeats the bind - (with identical arguments). - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_39" --> - <rule name = "failure" on-failure = "??????"> - <!-- - TODO: Find correct code. The on-failure code returned should depend on why the bind - failed. Assuming that failures owing to bad parameters are covered in the rules relating - to those parameters, the only remaining reason for a failure would be the lack of - server resorces or some internal error - such as too many queues open. Would these - cases qualify as "resource error" 506 or "internal error" 541? - --> - <doc>If a bind fails, the server MUST raise a connection exception.</doc> - <doc type = "scenario"> - TODO - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_12" --> - <rule name = "transient-exchange" on-failure = "not-allowed"> - <doc> - The server MUST NOT allow a durable queue to bind to a transient exchange. - </doc> - <doc type = "scenario"> - A client creates a transient exchange. The client then declares a named durable - queue and then attempts to bind the transient exchange to the durable queue. - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_13" --> - <rule name = "durable-exchange"> - <doc> - Bindings for durable queues are automatically durable and the server SHOULD - restore such bindings after a server restart. - </doc> - <doc type = "scenario"> - A server creates a named durable queue and binds it to a durable exchange. The - server is restarted. The client then attempts to use the queue/exchange combination. - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_17" --> - <rule name = "internal-exchange"> - <doc> - If the client attempts to bind to an exchange that was declared as internal, the server - MUST raise a connection exception with reply code 530 (not allowed). - </doc> - <doc type = "scenario"> - A client attempts to bind a named queue to an internal exchange. - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_40" --> - <rule name = "binding-count"> - <doc> - The server SHOULD support at least 4 bindings per queue, and ideally, impose no - limit except as defined by available resources. - </doc> - <doc type = "scenario"> - A client creates a named queue and attempts to bind it to 4 different non-internal - exchanges. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - - <response name = "bind-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <doc> - The client provides a valid access ticket giving "active" access rights to the - queue's access realm. - </doc> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue to bind. If the queue name is empty, refers to - the current queue for the channel, which is the last declared queue. - </doc> - - <rule name = "empty-queue" on-failure = "not-allowed"> - <doc> - A client MUST NOT be allowed to bind a non-existent and unnamed queue (i.e. - empty queue name) to an exchange. - </doc> - <doc type = "scenario"> - A client attempts to bind with an unnamed (empty) queue name to an exchange. - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_26" --> - <rule name = "queue-existence" on-failure = "not-found"> - <doc> - A client MUST NOT be allowed to bind a non-existent queue (i.e. not previously - declared) to an exchange. - </doc> - <doc type = "scenario"> - A client attempts to bind an undeclared queue name to an exchange. - </doc> - </rule> - </field> - - <field name = "exchange" domain = "exchange-name" label = "name of the exchange to bind to"> - <!-- Rule test name: was "amq_queue_14" --> - <rule name = "exchange-existence" on-failure = "not-found"> - <doc> - A client MUST NOT be allowed to bind a queue to a non-existent exchange. - </doc> - <doc type = "scenario"> - A client attempts to bind an named queue to a undeclared exchange. - </doc> - </rule> - </field> - - <field name = "routing-key" domain = "shortstr" label = "message routing key"> - <doc> - Specifies the routing key for the binding. The routing key is used for routing - messages depending on the exchange configuration. Not all exchanges use a - routing key - refer to the specific exchange documentation. If the queue name - is empty, the server uses the last queue declared on the channel. If the - routing key is also empty, the server uses this queue name for the routing - key as well. If the queue name is provided but the routing key is empty, the - server does the binding with that empty routing key. The meaning of empty - routing keys depends on the exchange implementation. - </doc> - </field> - - <field name = "arguments" domain = "table" label = "arguments for binding"> - <doc> - A set of arguments for the binding. The syntax and semantics of these arguments - depends on the exchange class. - </doc> - </field> - </method> - - <method name = "bind-ok" synchronous = "1" index = "21" label = "confirm bind successful"> - <doc>This method confirms that the bind was successful.</doc> - - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "purge" synchronous = "1" index = "30" label = "purge a queue"> - <doc> - This method removes all messages from a queue. It does not cancel consumers. Purged - messages are deleted without any formal "undo" mechanism. - </doc> - - <!-- Rule test name: was "amq_queue_15" --> - <rule name = "01"> - <doc>A call to purge MUST result in an empty queue.</doc> - </rule> - - <!-- Rule test name: was "amq_queue_41" --> - <rule name = "02"> - <doc> - On transacted channels the server MUST not purge messages that have already been - sent to a client but not yet acknowledged. - </doc> - </rule> - - <!-- TODO: Rule split? --> - - <!-- Rule test name: was "amq_queue_42" --> - <rule name = "03"> - <doc> - The server MAY implement a purge queue or log that allows system administrators - to recover accidentally-purged messages. The server SHOULD NOT keep purged - messages in the same storage spaces as the live messages since the volumes of - purged messages may get very large. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - - <response name = "purge-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <doc>The access ticket must be for the access realm that holds the queue.</doc> - - <rule name = "01"> - <doc> - The client MUST provide a valid access ticket giving "read" access rights to - the queue's access realm. Note that purging a queue is equivalent to reading - all messages and discarding them. - </doc> - </rule> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue to purge. If the queue name is empty, refers to - the current queue for the channel, which is the last declared queue. - </doc> - - <rule name = "01"> - <doc> - If the client did not previously declare a queue, and the queue name in this - method is empty, the server MUST raise a connection exception with reply - code 530 (not allowed). - </doc> - </rule> - - <!-- TODO Rule split? --> - - <!-- Rule test name: was "amq_queue_16" --> - <rule name = "02"> - <doc> - The queue MUST exist. Attempting to purge a non-existing queue MUST cause a - channel exception. - </doc> - </rule> - </field> - </method> - - <method name = "purge-ok" synchronous = "1" index = "31" label = "confirms a queue purge"> - <doc>This method confirms the purge of a queue.</doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "message-count" domain = "long" label = "number of messages purged"> - <doc>Reports the number of messages purged.</doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "delete" synchronous = "1" index = "40" label = "delete a queue"> - <doc> - This method deletes a queue. When a queue is deleted any pending messages are sent - to a dead-letter queue if this is defined in the server configuration, and all - consumers on the queue are cancelled. - </doc> - - <!-- TODO: Rule split? --> - - <!-- Rule test name: was "amq_queue_43" --> - <rule name = "01"> - <doc> - The server SHOULD use a dead-letter queue to hold messages that were pending on - a deleted queue, and MAY provide facilities for a system administrator to move - these messages back to an active queue. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - - <response name = "delete-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <doc> - The client provides a valid access ticket giving "active" access rights to the - queue's access realm. - </doc> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue to delete. If the queue name is empty, refers to - the current queue for the channel, which is the last declared queue. - </doc> - - <rule name = "01"> - <doc> - If the client did not previously declare a queue, and the queue name in this - method is empty, the server MUST raise a connection exception with reply - code 530 (not allowed). - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_21" --> - <rule name = "02"> - <doc> - The queue must exist. If the client attempts to delete a non-existing queue - the server MUST raise a channel exception with reply code 404 (not found). - </doc> - </rule> - </field> - - <field name = "if-unused" domain = "bit" label = "delete only if unused"> - <doc> - If set, the server will only delete the queue if it has no consumers. If the - queue has consumers the server does does not delete it but raises a channel - exception instead. - </doc> - - <!-- Rule test name: was "amq_queue_29" and "amq_queue_30" --> - <rule name = "01"> - <doc>The server MUST respect the if-unused flag when deleting a queue.</doc> - </rule> - </field> - - <field name = "if-empty" domain = "bit" label = "delete only if empty"> - <doc> - If set, the server will only delete the queue if it has no messages. - </doc> - <rule name = "01"> - <doc> - If the queue is not empty the server MUST raise a channel exception with - reply code 406 (precondition failed). - </doc> - </rule> - </field> - </method> - - <method name = "delete-ok" synchronous = "1" index = "41" label = "confirm deletion of a queue"> - <doc>This method confirms the deletion of a queue.</doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "message-count" domain = "long" label = "number of messages purged"> - <doc>Reports the number of messages purged.</doc> - </field> - </method> - </class> - - <!-- == BASIC ============================================================ --> - - <class name = "basic" handler = "channel" index = "60" label = "work with basic content"> - <doc> - The Basic class provides methods that support an industry-standard messaging model. - </doc> - - <doc type = "grammar"> - basic = C:QOS S:QOS-OK - / C:CONSUME S:CONSUME-OK - / C:CANCEL S:CANCEL-OK - / C:PUBLISH content - / S:RETURN content - / S:DELIVER content - / C:GET ( S:GET-OK content / S:GET-EMPTY ) - / C:ACK - / C:REJECT - </doc> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MAY" /> - - <!-- Rule test name: was "amq_basic_08" --> - <rule name = "01"> - <doc> - The server SHOULD respect the persistent property of basic messages and - SHOULD make a best-effort to hold persistent basic messages on a reliable - storage mechanism. - </doc> - <doc type = "scenario"> - Send a persistent message to queue, stop server, restart server and then - verify whether message is still present. Assumes that queues are durable. - Persistence without durable queues makes no sense. - </doc> - </rule> - - <!-- Rule test name: was "amq_basic_09" --> - <rule name = "02"> - <doc> - The server MUST NOT discard a persistent basic message in case of a queue - overflow. - </doc> - <doc type = "scenario"> - Create a queue overflow situation with persistent messages and verify that - messages do not get lost (presumably the server will write them to disk). - </doc> - </rule> - - <rule name = "03"> - <doc> - The server MAY use the Channel.Flow method to slow or stop a basic message - publisher when necessary. - </doc> - <doc type = "scenario"> - Create a queue overflow situation with non-persistent messages and verify - whether the server responds with Channel.Flow or not. Repeat with persistent - messages. - </doc> - </rule> - - <!-- Rule test name: was "amq_basic_10" --> - <rule name = "04"> - <doc> - The server MAY overflow non-persistent basic messages to persistent - storage. - </doc> - <!-- Test scenario: untestable --> - </rule> - - <rule name = "05"> - <doc> - The server MAY discard or dead-letter non-persistent basic messages on a - priority basis if the queue size exceeds some configured limit. - </doc> - <!-- Test scenario: untestable --> - </rule> - - <!-- Rule test name: was "amq_basic_11" --> - <rule name = "06"> - <doc> - The server MUST implement at least 2 priority levels for basic messages, - where priorities 0-4 and 5-9 are treated as two distinct levels. - </doc> - <doc type = "scenario"> - Send a number of priority 0 messages to a queue. Send one priority 9 - message. Consume messages from the queue and verify that the first message - received was priority 9. - </doc> - </rule> - - <rule name = "07"> - <doc> - The server MAY implement up to 10 priority levels. - </doc> - <doc type = "scenario"> - Send a number of messages with mixed priorities to a queue, so that all - priority values from 0 to 9 are exercised. A good scenario would be ten - messages in low-to-high priority. Consume from queue and verify how many - priority levels emerge. - </doc> - </rule> - - <!-- Rule test name: was "amq_basic_12" --> - <rule name = "08"> - <doc> - The server MUST deliver messages of the same priority in order irrespective of - their individual persistence. - </doc> - <doc type = "scenario"> - Send a set of messages with the same priority but different persistence - settings to a queue. Consume and verify that messages arrive in same order - as originally published. - </doc> - </rule> - - <!-- Rule test name: was "amq_basic_13" --> - <rule name = "09"> - <doc> - The server MUST support automatic acknowledgements on Basic content, i.e. - consumers with the no-ack field set to FALSE. - </doc> - <doc type = "scenario"> - Create a queue and a consumer using automatic acknowledgements. Publish - a set of messages to the queue. Consume the messages and verify that all - messages are received. - </doc> - </rule> - - <rule name = "10"> - <doc> - The server MUST support explicit acknowledgements on Basic content, i.e. - consumers with the no-ack field set to TRUE. - </doc> - <doc type = "scenario"> - Create a queue and a consumer using explicit acknowledgements. Publish a - set of messages to the queue. Consume the messages but acknowledge only - half of them. Disconnect and reconnect, and consume from the queue. - Verify that the remaining messages are received. - </doc> - </rule> - - <!-- These are the properties for a Basic content --> - - <field name = "content-type" domain = "shortstr" label = "MIME content type" /> - <field name = "content-encoding" domain = "shortstr" label = "MIME content encoding" /> - <field name = "headers" domain = "table" label = "message header field table" /> - <field name = "delivery-mode" domain = "octet" label = "non-persistent (1) or persistent (2)" /> - <field name = "priority" domain = "short" label = "message priority, 0 to 9" /> - <field name = "correlation-id" domain = "shortstr" label = "application correlation identifier" /> - <field name = "reply-to" domain = "shortstr" label = "destination to reply to" /> - <field name = "expiration" domain = "shortstr" label = "message expiration specification" /> - <field name = "timestamp" domain = "timestamp" label = "message timestamp" /> - <field name = "message-id" domain = "shortstr" label = "application message identifier" /> - <field name = "type" domain = "shortstr" label = "message type name" /> - <field name = "user-id" domain = "shortstr" label = "creating user id" /> - <field name = "app-id" domain = "shortstr" label = "creating application id" /> - <!-- This field is deprecated pending review --> - <field name = "cluster-id" domain = "shortstr" label = "intra-cluster routing identifier" /> - - <!-- Type diversity test --> - <field name = "property-bit" domain = "bit" label = "Extra property for testing only" /> - <field name = "property-octet" domain = "octet" label = "Extra property for testing only" /> - <field name = "property-short" domain = "short" label = "Extra property for testing only" /> - <field name = "property-long" domain = "long" label = "Extra property for testing only" /> - <field name = "property-longlong" domain = "longlong" label = "Extra property for testing only" /> - <field name = "property-shortstr" domain = "shortstr" label = "Extra property for testing only" /> - <field name = "property-longstr" domain = "longstr" label = "Extra property for testing only" /> - <field name = "property-timestamp" domain = "timestamp" label = "Extra property for testing only" /> - <field name = "property-table" domain = "table" label = "Extra property for testing only" /> - <field name = "property-access-ticket" domain = "access-ticket" label = "Extra property for testing only" /> - <field name = "property-class-id" domain = "class-id" label = "Extra property for testing only" /> - <field name = "property-consumer-tag" domain = "consumer-tag" label = "Extra property for testing only" /> - <field name = "property-delivery-tag" domain = "delivery-tag" label = "Extra property for testing only" /> - <field name = "property-exchange-name" domain = "exchange-name" label = "Extra property for testing only" /> - <field name = "property-known-hosts" domain = "known-hosts" label = "Extra property for testing only" /> - <field name = "property-method-id" domain = "method-id" label = "Extra property for testing only" /> - <field name = "property-no-ack" domain = "no-ack" label = "Extra property for testing only" /> - <field name = "property-no-local" domain = "no-local" label = "Extra property for testing only" /> - <field name = "property-path" domain = "path" label = "Extra property for testing only" /> - <field name = "property-peer-properties" domain = "peer-properties" label = "Extra property for testing only" /> - <field name = "property-queue-name" domain = "queue-name" label = "Extra property for testing only" /> - <field name = "property-redelivered" domain = "redelivered" label = "Extra property for testing only" /> - <field name = "property-reply-code" domain = "reply-code" label = "Extra property for testing only" /> - <field name = "property-reply-text" domain = "reply-text" label = "Extra property for testing only" /> - - <!-- Bit field test --> - <field name = "property-long-A" domain = "long" label = "Extra property for testing only" /> - <field name = "property-bit-B" domain = "bit" label = "Extra property for testing only" /> - <field name = "property-bit-C" domain = "bit" label = "Extra property for testing only" /> - <field name = "property-bit-D" domain = "bit" label = "Extra property for testing only" /> - <field name = "property-bit-E" domain = "bit" label = "Extra property for testing only" /> - <field name = "property-bit-F" domain = "bit" label = "Extra property for testing only" /> - <field name = "property-shortstr-G" domain = "shortstr" label = "Extra property for testing only" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "qos" synchronous = "1" index = "10" label = "specify quality of service"> - <doc> - This method requests a specific quality of service. The QoS can be specified for the - current channel or for all channels on the connection. The particular properties and - semantics of a qos method always depend on the content class semantics. Though the - qos method could in principle apply to both peers, it is currently meaningful only - for the server. - </doc> - - <chassis name = "server" implement = "MUST" /> - <response name = "qos-ok" /> - - <field name = "prefetch-size" domain = "long" label = "prefetch window in octets"> - <doc> - The client can request that messages be sent in advance so that when the client - finishes processing a message, the following message is already held locally, - rather than needing to be sent down the channel. Prefetching gives a performance - improvement. This field specifies the prefetch window size in octets. The server - will send a message in advance if it is equal to or smaller in size than the - available prefetch size (and also falls into other prefetch limits). May be set - to zero, meaning "no specific limit", although other prefetch limits may still - apply. The prefetch-size is ignored if the no-ack option is set. - </doc> - <!-- Rule test name: was "amq_basic_17" --> - <rule name = "01"> - <doc> - The server MUST ignore this setting when the client is not processing any - messages - i.e. the prefetch size does not limit the transfer of single - messages to a client, only the sending in advance of more messages while - the client still has one or more unacknowledged messages. - </doc> - <doc type = "scenario"> - Define a QoS prefetch-size limit and send a single message that exceeds - that limit. Verify that the message arrives correctly. - </doc> - </rule> - </field> - - <field name = "prefetch-count" domain = "short" label = "prefetch window in messages"> - <doc> - Specifies a prefetch window in terms of whole messages. This field may be used - in combination with the prefetch-size field; a message will only be sent in - advance if both prefetch windows (and those at the channel and connection level) - allow it. The prefetch-count is ignored if the no-ack option is set. - </doc> - <!-- Rule test name: was "amq_basic_18" --> - <rule name = "01"> - <doc> - The server may send less data in advance than allowed by the client's - specified prefetch windows but it MUST NOT send more. - </doc> - <doc type = "scenario"> - Define a QoS prefetch-size limit and a prefetch-count limit greater than - one. Send multiple messages that exceed the prefetch size. Verify that - no more than one message arrives at once. - </doc> - </rule> - </field> - - <field name = "global" domain = "bit" label = "apply to entire connection"> - <doc> - By default the QoS settings apply to the current channel only. If this field is - set, they are applied to the entire connection. - </doc> - </field> - </method> - - <method name = "qos-ok" synchronous = "1" index = "11" label = "confirm the requested qos"> - <doc> - This method tells the client that the requested QoS levels could be handled by the - server. The requested QoS applies to all active consumers until a new QoS is - defined. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "consume" synchronous = "1" index = "20" label = "start a queue consumer"> - <doc> - This method asks the server to start a "consumer", which is a transient request for - messages from a specific queue. Consumers last as long as the channel they were - created on, or until the client cancels them. - </doc> - - <!-- Rule test name: was "amq_basic_01" --> - <rule name = "01"> - <doc> - The server SHOULD support at least 16 consumers per queue, and ideally, impose - no limit except as defined by available resources. - </doc> - <doc type = "scenario"> - Create a queue and create consumers on that queue until the server closes the - connection. Verify that the number of consumers created was at least sixteen - and report the total number. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - <response name = "consume-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "01" on-failure = "access-refused"> - <doc> - The client MUST provide a valid access ticket giving "read" access rights to - the realm for the queue. - </doc> - <doc type = "scenario"> - Attempt to create a consumer with an invalid (non-zero) access ticket. - </doc> - </rule> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue to consume from. If the queue name is null, - refers to the current queue for the channel, which is the last declared queue. - </doc> - <rule name = "01" on-failure = "not-allowed"> - <doc> - If the queue name is empty the client MUST have previously declared a - queue using this channel. - </doc> - <doc type = "scenario"> - Attempt to create a consumer with an empty queue name and no previously - declared queue on the channel. - </doc> - </rule> - </field> - - <field name = "consumer-tag" domain = "consumer-tag"> - <doc> - Specifies the identifier for the consumer. The consumer tag is local to a - connection, so two clients can use the same consumer tags. If this field is - empty the server will generate a unique tag. - </doc> - <rule name = "01" on-failure = "not-allowed"> - <doc> - The client MUST NOT specify a tag that refers to an existing consumer. - </doc> - <doc type = "scenario"> - Attempt to create two consumers with the same non-empty tag. - </doc> - </rule> - <rule name = "02" on-failure = "not-allowed"> - <doc> - The consumer tag is valid only within the channel from which the - consumer was created. I.e. a client MUST NOT create a consumer in one - channel and then use it in another. - </doc> - <doc type = "scenario"> - Attempt to create a consumer in one channel, then use in another channel, - in which consumers have also been created (to test that the server uses - unique consumer tags). - </doc> - </rule> - </field> - - <field name = "no-local" domain = "no-local" /> - - <field name = "nowait" domain = "bit" label = "do not send a reply method"> - <doc> - If set, the server will not respond to the method. The client should not wait - for a reply method. If the server could not complete the method it will raise - a channel or connection exception. - </doc> - </field> - - <field name = "bit-test-1" domain = "bit" /> - <field name = "bit-test-2" domain = "bit" /> - <field name = "bit-test-3" domain = "bit" /> - <field name = "bit-test-4" domain = "bit" /> - <field name = "bit-test-5" domain = "bit" /> - <field name = "bit-test-6" domain = "bit" /> - <field name = "bit-test-7" domain = "bit" /> - <field name = "bit-test-8" domain = "bit" /> - <field name = "bit-test-9" domain = "bit" /> - - <field name = "no-ack" domain = "short" /> - - <field name = "exclusive" domain = "bit" label = "request exclusive access"> - <doc> - Request exclusive consumer access, meaning only this consumer can access the - queue. - </doc> - <!-- Rule test name: was "amq_basic_02" --> - <rule name = "01" on-failure = "access-refused"> - <doc> - The client MAY NOT gain exclusive access to a queue that already has - active consumers. - </doc> - <doc type = "scenario"> - Open two connections to a server, and in one connection create a shared - (non-exclusive) queue and then consume from the queue. In the second - connection attempt to consume from the same queue using the exclusive - option. - </doc> - </rule> - </field> - - <field name = "priority" domain = "short" label = "consume priority"/> - </method> - - <method name = "consume-ok" synchronous = "1" index = "21" label = "confirm a new consumer"> - <doc> - The server provides the client with a consumer tag, which is used by the client - for methods called on the consumer at a later stage. - </doc> - <chassis name = "client" implement = "MUST" /> - <field name = "consumer-tag" domain = "consumer-tag"> - <doc> - Holds the consumer tag specified by the client or provided by the server. - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "cancel" synchronous = "1" index = "30" label = "end a queue consumer"> - <doc> - This method cancels a consumer. This does not affect already delivered - messages, but it does mean the server will not send any more messages for - that consumer. The client may receive an abitrary number of messages in - between sending the cancel method and receiving the cancel-ok reply. - </doc> - - <rule name = "01"> - <doc> - If the queue does not exist the server MUST ignore the cancel method, so - long as the consumer tag is valid for that channel. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - <response name = "cancel-ok" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - </method> - - <method name = "cancel-ok" synchronous = "1" index = "31" label = "confirm a cancelled consumer"> - <doc> - This method confirms that the cancellation was completed. - </doc> - <chassis name = "client" implement = "MUST" /> - <field name = "consumer-tag" domain = "consumer-tag" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "publish" content = "1" index = "40" label = "publish a message"> - <doc> - This method publishes a message to a specific exchange. The message will be routed - to queues as defined by the exchange configuration and distributed to any active - consumers when the transaction, if any, is committed. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "01"> - <doc> - The client MUST provide a valid access ticket giving "write" access rights - to the access realm for the exchange. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange to publish to. The exchange name can be - empty, meaning the default exchange. If the exchange name is specified, and that - exchange does not exist, the server will raise a channel exception. - </doc> - - <!-- Rule test name: was "amq_basic_06" --> - <rule name = "01"> - <doc> - The server MUST accept a blank exchange name to mean the default exchange. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <!-- Rule test name: was "amq_basic_14" --> - <rule name = "02"> - <doc> - If the exchange was declared as an internal exchange, the server MUST raise - a channel exception with a reply code 403 (access refused). - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <!-- Rule test name: was "amq_basic_15" --> - <rule name = "03"> - <doc> - The exchange MAY refuse basic content in which case it MUST raise a channel - exception with reply code 540 (not implemented). - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc> - Specifies the routing key for the message. The routing key is used for routing - messages depending on the exchange configuration. - </doc> - </field> - - <field name = "mandatory" domain = "bit" label = "indicate mandatory routing"> - <doc> - This flag tells the server how to react if the message cannot be routed to a - queue. If this flag is set, the server will return an unroutable message with a - Return method. If this flag is zero, the server silently drops the message. - </doc> - <!-- Rule test name: was "amq_basic_07" --> - <rule name = "01"> - <doc> - The server SHOULD implement the mandatory flag. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <field name = "immediate" domain = "bit" label = "request immediate delivery"> - <doc> - This flag tells the server how to react if the message cannot be routed to a - queue consumer immediately. If this flag is set, the server will return an - undeliverable message with a Return method. If this flag is zero, the server - will queue the message, but with no guarantee that it will ever be consumed. - </doc> - <!-- Rule test name: was "amq_basic_16" --> - <rule name = "01"> - <doc> - The server SHOULD implement the immediate flag. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - </method> - - <method name = "return" content = "1" index = "50" label = "return a failed message"> - <doc> - This method returns an undeliverable message that was published with the "immediate" - flag set, or an unroutable message published with the "mandatory" flag set. The - reply code and text provide information about the reason that the message was - undeliverable. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "reply-code" domain = "reply-code" /> - - <field name = "reply-text" domain = "reply-text" /> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange that the message was originally published to. - </doc> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc> - Specifies the routing key name specified when the message was published. - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "deliver" content = "1" index = "60" - label = "notify the client of a consumer message"> - <doc> - This method delivers a message to the client, via a consumer. In the asynchronous - message delivery model, the client starts a consumer using the Consume method, then - the server responds with Deliver methods as and when messages arrive for that - consumer. - </doc> - - <!-- Rule test name: was "amq_basic_19" --> - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The server SHOULD track the number of times a message has been delivered to - clients and when a message is redelivered a certain number of times - e.g. 5 - times - without being acknowledged, the server SHOULD consider the message to be - unprocessable (possibly causing client applications to abort), and move the - message to a dead letter queue. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "redelivered" domain = "redelivered" /> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange that the message was originally published to. - </doc> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc>Specifies the routing key name specified when the message was published.</doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "get" synchronous = "1" index = "70" label = "direct access to a queue"> - <doc> - This method provides a direct access to the messages in a queue using a synchronous - dialogue that is designed for specific types of application where synchronous - functionality is more important than performance. - </doc> - - <response name = "get-ok" /> - <response name = "get-empty" /> - <chassis name = "server" implement = "MUST" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "01"> - <doc> - The client MUST provide a valid access ticket giving "read" access rights to - the realm for the queue. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue to consume from. If the queue name is null, - refers to the current queue for the channel, which is the last declared queue. - </doc> - <rule name = "01"> - <doc> - If the client did not previously declare a queue, and the queue name in this - method is empty, the server MUST raise a connection exception with reply - code 530 (not allowed). - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <field name = "no-ack" domain = "no-ack" /> - </method> - - <method name = "get-ok" synchronous = "1" content = "1" index = "71" - label = "provide client with a message"> - <doc> - This method delivers a message to the client following a get method. A message - delivered by 'get-ok' must be acknowledged unless the no-ack option was set in the - get method. - </doc> - - <chassis name = "client" implement = "MAY" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "redelivered" domain = "redelivered" /> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange that the message was originally published to. - If empty, the message was published to the default exchange. - </doc> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc>Specifies the routing key name specified when the message was published.</doc> - </field> - - <field name = "message-count" domain = "long" label = "number of messages pending"> - <doc> - This field reports the number of messages pending on the queue, excluding the - message being delivered. Note that this figure is indicative, not reliable, and - can change arbitrarily as messages are added to the queue and removed by other - clients. - </doc> - </field> - </method> - - <method name = "get-empty" synchronous = "1" index = "72" - label = "indicate no messages available"> - <doc> - This method tells the client that the queue has no messages available for the - client. - </doc> - - <chassis name = "client" implement = "MAY" /> - - <!-- This field is deprecated pending review --> - <field name = "cluster-id" domain = "shortstr" label = "Cluster id"> - <doc> - For use by cluster applications, should not be used by client applications. - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "ack" index = "80" label = "acknowledge one or more messages"> - <doc> - This method acknowledges one or more messages delivered via the Deliver or Get-Ok - methods. The client can ask to confirm a single message or a set of messages up to - and including a specific message. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "multiple" domain = "bit" label = "acknowledge multiple messages"> - <doc> - If set to 1, the delivery tag is treated as "up to and including", so that the - client can acknowledge multiple messages with a single method. If set to zero, - the delivery tag refers to a single message. If the multiple field is 1, and the - delivery tag is zero, tells the server to acknowledge all outstanding mesages. - </doc> - - <!-- Rule test name: was "amq_basic_20" --> - <rule name = "01"> - <doc> - The server MUST validate that a non-zero delivery-tag refers to an delivered - message, and raise a channel exception if this is not the case. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "reject" index = "90" label = "reject an incoming message"> - <doc> - This method allows a client to reject a message. It can be used to interrupt and - cancel large incoming messages, or return untreatable messages to their original - queue. - </doc> - - <!-- Rule test name: was "amq_basic_21" --> - <rule name = "01"> - <doc> - The server SHOULD be capable of accepting and process the Reject method while - sending message content with a Deliver or Get-Ok method. I.e. the server should - read and process incoming methods while sending output frames. To cancel a - partially-send content, the server sends a content body frame of size 1 (i.e. - with no data except the frame-end octet). - </doc> - </rule> - - <!-- Rule test name: was "amq_basic_22" --> - <rule name = "02"> - <doc> - The server SHOULD interpret this method as meaning that the client is unable to - process the message at this time. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <rule name = "03"> - <!-- TODO: Rule split? --> - <doc> - A client MUST NOT use this method as a means of selecting messages to process. A - rejected message MAY be discarded or dead-lettered, not necessarily passed to - another client. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "requeue" domain = "bit" label = "requeue the message"> - <doc> - If this field is zero, the message will be discarded. If this bit is 1, the - server will attempt to requeue the message. - </doc> - - <!-- Rule test name: was "amq_basic_23" --> - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The server MUST NOT deliver the message to the same client within the - context of the current channel. The recommended strategy is to attempt to - deliver the message to an alternative consumer, and if that is not possible, - to move the message to a dead-letter queue. The server MAY use more - sophisticated tracking to hold the message on the queue and redeliver it to - the same client at a later stage. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - </method> - - <method name = "recover" index = "100" label = "redeliver unacknowledged messages"> - <doc> - This method asks the broker to redeliver all unacknowledged messages on a specified - channel. Zero or more messages may be redelivered. This method is only allowed on - non-transacted channels. - </doc> - - <rule name = "01"> - <doc> - The server MUST set the redelivered flag on all messages that are resent. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <rule name = "02"> - <doc> - The server MUST raise a channel exception if this is called on a transacted - channel. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - - <field name = "requeue" domain = "bit" label = "requeue the message"> - <doc> - If this field is zero, the message will be redelivered to the original - recipient. If this bit is 1, the server will attempt to requeue the message, - potentially then delivering it to an alternative subscriber. - </doc> - </field> - </method> - </class> - - <!-- == FILE ============================================================= --> - - <class name = "file" handler = "channel" index = "70" label = "work with file content"> - <doc> - The file class provides methods that support reliable file transfer. File - messages have a specific set of properties that are required for interoperability - with file transfer applications. File messages and acknowledgements are subject to - channel transactions. Note that the file class does not provide message browsing - methods; these are not compatible with the staging model. Applications that need - browsable file transfer should use Basic content and the Basic class. - </doc> - - <doc type = "grammar"> - file = C:QOS S:QOS-OK - / C:CONSUME S:CONSUME-OK - / C:CANCEL S:CANCEL-OK - / C:OPEN S:OPEN-OK C:STAGE content - / S:OPEN C:OPEN-OK S:STAGE content - / C:PUBLISH - / S:DELIVER - / S:RETURN - / C:ACK - / C:REJECT - </doc> - - <chassis name = "server" implement = "MAY" /> - <chassis name = "client" implement = "MAY" /> - - <rule name = "01"> - <doc> - The server MUST make a best-effort to hold file messages on a reliable storage - mechanism. - </doc> - </rule> - - <!-- TODO Rule implement attr inverse? --> - - <!-- TODO: Rule split? --> - - <rule name = "02"> - <doc> - The server MUST NOT discard a file message in case of a queue overflow. The server - MUST use the Channel.Flow method to slow or stop a file message publisher when - necessary. - </doc> - </rule> - - <!-- TODO: Rule split? --> - - <rule name = "03"> - <doc> - The server MUST implement at least 2 priority levels for file messages, where - priorities 0-4 and 5-9 are treated as two distinct levels. The server MAY implement - up to 10 priority levels. - </doc> - </rule> - - <rule name = "04"> - <doc> - The server MUST support both automatic and explicit acknowledgements on file - content. - </doc> - </rule> - - <!-- These are the properties for a File content --> - - <field name = "content-type" domain = "shortstr" label = "MIME content type" /> - <field name = "content-encoding" domain = "shortstr" label = "MIME content encoding" /> - <field name = "headers" domain = "table" label = "message header field table" /> - <field name = "priority" domain = "octet" label = "message priority, 0 to 9" /> - <field name = "reply-to" domain = "shortstr" label = "destination to reply to" /> - <field name = "message-id" domain = "shortstr" label = "application message identifier" /> - <field name = "filename" domain = "shortstr" label = "message filename" /> - <field name = "timestamp" domain = "timestamp" label = "message timestamp" /> - <!-- This field is deprecated pending review --> - <field name = "cluster-id" domain = "shortstr" label = "intra-cluster routing identifier" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "qos" synchronous = "1" index = "10" label = "specify quality of service"> - <doc> - This method requests a specific quality of service. The QoS can be specified for the - current channel or for all channels on the connection. The particular properties and - semantics of a qos method always depend on the content class semantics. Though the - qos method could in principle apply to both peers, it is currently meaningful only - for the server. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <response name = "qos-ok" /> - - <field name = "prefetch-size" domain = "long" label = "prefetch window in octets"> - <doc> - The client can request that messages be sent in advance so that when the client - finishes processing a message, the following message is already held locally, - rather than needing to be sent down the channel. Prefetching gives a performance - improvement. This field specifies the prefetch window size in octets. May be set - to zero, meaning "no specific limit". Note that other prefetch limits may still - apply. The prefetch-size is ignored if the no-ack option is set. - </doc> - </field> - - <field name = "prefetch-count" domain = "short" label = "prefetch window in messages"> - <doc> - Specifies a prefetch window in terms of whole messages. This is compatible with - some file API implementations. This field may be used in combination with the - prefetch-size field; a message will only be sent in advance if both prefetch - windows (and those at the channel and connection level) allow it. The - prefetch-count is ignored if the no-ack option is set. - </doc> - - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The server MAY send less data in advance than allowed by the client's - specified prefetch windows but it MUST NOT send more. - </doc> - </rule> - </field> - - <field name = "global" domain = "bit" label = "apply to entire connection"> - <doc> - By default the QoS settings apply to the current channel only. If this field is - set, they are applied to the entire connection. - </doc> - </field> - </method> - - <method name = "qos-ok" synchronous = "1" index = "11" label = "confirm the requested qos"> - <doc> - This method tells the client that the requested QoS levels could be handled by the - server. The requested QoS applies to all active consumers until a new QoS is - defined. - </doc> - - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "consume" synchronous = "1" index = "20" label = "start a queue consumer"> - <doc> - This method asks the server to start a "consumer", which is a transient request for - messages from a specific queue. Consumers last as long as the channel they were - created on, or until the client cancels them. - </doc> - - <rule name = "01"> - <doc> - The server SHOULD support at least 16 consumers per queue, unless the queue was - declared as private, and ideally, impose no limit except as defined by available - resources. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - - <response name = "consume-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "01"> - <doc> - The client MUST provide a valid access ticket giving "read" access rights to - the realm for the queue. - </doc> - </rule> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue to consume from. If the queue name is null, - refers to the current queue for the channel, which is the last declared queue. - </doc> - - <rule name = "01"> - <doc> - If the client did not previously declare a queue, and the queue name in this - method is empty, the server MUST raise a connection exception with reply - code 530 (not allowed). - </doc> - </rule> - </field> - - <field name = "consumer-tag" domain = "consumer-tag"> - <doc> - Specifies the identifier for the consumer. The consumer tag is local to a - connection, so two clients can use the same consumer tags. If this field is - empty the server will generate a unique tag. - </doc> - - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The tag MUST NOT refer to an existing consumer. If the client attempts to - create two consumers with the same non-empty tag the server MUST raise a - connection exception with reply code 530 (not allowed). - </doc> - </rule> - </field> - - <field name = "no-local" domain = "no-local" /> - - <field name = "no-ack" domain = "no-ack" /> - - <field name = "exclusive" domain = "bit" label = "request exclusive access"> - <doc> - Request exclusive consumer access, meaning only this consumer can access the - queue. - </doc> - - <!-- Rule test name: was "amq_file_00" --> - <rule name = "01"> - <doc> - If the server cannot grant exclusive access to the queue when asked, - - because there are other consumers active - it MUST raise a channel exception - with return code 405 (resource locked). - </doc> - </rule> - </field> - </method> - - <method name = "consume-ok" synchronous = "1" index = "21" label = "confirm a new consumer"> - <doc> - This method provides the client with a consumer tag which it MUST use in methods - that work with the consumer. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag"> - <doc>Holds the consumer tag specified by the client or provided by the server.</doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "cancel" synchronous = "1" index = "30" label = "end a queue consumer"> - <doc> - This method cancels a consumer. This does not affect already delivered messages, but - it does mean the server will not send any more messages for that consumer. - </doc> - - <response name = "cancel-ok" /> - - <chassis name = "server" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - </method> - - <method name = "cancel-ok" synchronous = "1" index = "31" label = "confirm a cancelled consumer"> - <doc>This method confirms that the cancellation was completed.</doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "open" synchronous = "1" index = "40" label = "request to start staging"> - <doc> - This method requests permission to start staging a message. Staging means sending - the message into a temporary area at the recipient end and then delivering the - message by referring to this temporary area. Staging is how the protocol handles - partial file transfers - if a message is partially staged and the connection breaks, - the next time the sender starts to stage it, it can restart from where it left off. - </doc> - - <response name = "open-ok" /> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <field name = "identifier" domain = "shortstr" label = "staging identifier"> - <doc> - This is the staging identifier. This is an arbitrary string chosen by the - sender. For staging to work correctly the sender must use the same staging - identifier when staging the same message a second time after recovery from a - failure. A good choice for the staging identifier would be the SHA1 hash of the - message properties data (including the original filename, revised time, etc.). - </doc> - </field> - - <field name = "content-size" domain = "longlong" label = "message content size"> - <doc> - The size of the content in octets. The recipient may use this information to - allocate or check available space in advance, to avoid "disk full" errors during - staging of very large messages. - </doc> - - <rule name = "01"> - <doc> - The sender MUST accurately fill the content-size field. Zero-length content - is permitted. - </doc> - </rule> - </field> - </method> - - <method name = "open-ok" synchronous = "1" index = "41" label = "confirm staging ready"> - <doc> - This method confirms that the recipient is ready to accept staged data. If the - message was already partially-staged at a previous time the recipient will report - the number of octets already staged. - </doc> - - <response name = "stage" /> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <field name = "staged-size" domain = "longlong" label = "already staged amount"> - <doc> - The amount of previously-staged content in octets. For a new message this will - be zero. - </doc> - - <rule name = "01"> - <doc> - The sender MUST start sending data from this octet offset in the message, - counting from zero. - </doc> - </rule> - - <rule name = "02"> - <!-- TODO: Rule split? --> - <doc> - The recipient MAY decide how long to hold partially-staged content and MAY - implement staging by always discarding partially-staged content. However if - it uses the file content type it MUST support the staging methods. - </doc> - </rule> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "stage" content = "1" index = "50" label = "stage message content"> - <doc> - This method stages the message, sending the message content to the recipient from - the octet offset specified in the Open-Ok method. - </doc> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "publish" index = "60" label = "publish a message"> - <doc> - This method publishes a staged file message to a specific exchange. The file message - will be routed to queues as defined by the exchange configuration and distributed to - any active consumers when the transaction, if any, is committed. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "01"> - <doc> - The client MUST provide a valid access ticket giving "write" access rights - to the access realm for the exchange. - </doc> - </rule> - </field> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange to publish to. The exchange name can be - empty, meaning the default exchange. If the exchange name is specified, and that - exchange does not exist, the server will raise a channel exception. - </doc> - - <rule name = "01"> - <doc> - The server MUST accept a blank exchange name to mean the default exchange. - </doc> - </rule> - - <rule name = "02"> - <doc> - If the exchange was declared as an internal exchange, the server MUST - respond with a reply code 403 (access refused) and raise a channel - exception. - </doc> - </rule> - - <!-- TODO: Rule split? --> - - <rule name = "03"> - <doc> - The exchange MAY refuse file content in which case it MUST respond with a - reply code 540 (not implemented) and raise a channel exception. - </doc> - </rule> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc> - Specifies the routing key for the message. The routing key is used for routing - messages depending on the exchange configuration. - </doc> - </field> - - <field name = "mandatory" domain = "bit" label = "indicate mandatory routing"> - <doc> - This flag tells the server how to react if the message cannot be routed to a - queue. If this flag is set, the server will return an unroutable message with a - Return method. If this flag is zero, the server silently drops the message. - </doc> - - <!-- Rule test name: was "amq_file_00" --> - <rule name = "01"> - <doc>The server SHOULD implement the mandatory flag.</doc> - </rule> - </field> - - <field name = "immediate" domain = "bit" label = "request immediate delivery"> - <doc> - This flag tells the server how to react if the message cannot be routed to a - queue consumer immediately. If this flag is set, the server will return an - undeliverable message with a Return method. If this flag is zero, the server - will queue the message, but with no guarantee that it will ever be consumed. - </doc> - - <!-- Rule test name: was "amq_file_00" --> - <rule name = "01"> - <doc>The server SHOULD implement the immediate flag.</doc> - </rule> - </field> - - <field name = "identifier" domain = "shortstr" label = "staging identifier"> - <doc> - This is the staging identifier of the message to publish. The message must have - been staged. Note that a client can send the Publish method asynchronously - without waiting for staging to finish. - </doc> - </field> - </method> - - <method name = "return" content = "1" index = "70" label = "return a failed message"> - <doc> - This method returns an undeliverable message that was published with the "immediate" - flag set, or an unroutable message published with the "mandatory" flag set. The - reply code and text provide information about the reason that the message was - undeliverable. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "reply-code" domain = "reply-code" /> - - <field name = "reply-text" domain = "reply-text" /> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange that the message was originally published to. - </doc> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc>Specifies the routing key name specified when the message was published.</doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "deliver" index = "80" label = "notify the client of a consumer message"> - <doc> - This method delivers a staged file message to the client, via a consumer. In the - asynchronous message delivery model, the client starts a consumer using the Consume - method, then the server responds with Deliver methods as and when messages arrive - for that consumer. - </doc> - - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The server SHOULD track the number of times a message has been delivered to - clients and when a message is redelivered a certain number of times - e.g. 5 - times - without being acknowledged, the server SHOULD consider the message to be - unprocessable (possibly causing client applications to abort), and move the - message to a dead letter queue. - </doc> - </rule> - - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "redelivered" domain = "redelivered" /> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange that the message was originally published to. - </doc> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc>Specifies the routing key name specified when the message was published.</doc> - </field> - - <field name = "identifier" domain = "shortstr" label = "staging identifier"> - <doc> - This is the staging identifier of the message to deliver. The message must have - been staged. Note that a server can send the Deliver method asynchronously - without waiting for staging to finish. - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "ack" index = "90" label = "acknowledge one or more messages"> - <doc> - This method acknowledges one or more messages delivered via the Deliver method. The - client can ask to confirm a single message or a set of messages up to and including - a specific message. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "multiple" domain = "bit" label = "acknowledge multiple messages"> - <doc> - If set to 1, the delivery tag is treated as "up to and including", so that the - client can acknowledge multiple messages with a single method. If set to zero, - the delivery tag refers to a single message. If the multiple field is 1, and the - delivery tag is zero, tells the server to acknowledge all outstanding mesages. - </doc> - - <rule name = "01"> - <doc> - The server MUST validate that a non-zero delivery-tag refers to an delivered - message, and raise a channel exception if this is not the case. - </doc> - </rule> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "reject" index = "100" label = "reject an incoming message"> - <doc> - This method allows a client to reject a message. It can be used to return - untreatable messages to their original queue. Note that file content is staged - before delivery, so the client will not use this method to interrupt delivery of a - large message. - </doc> - - <rule name = "01"> - <doc> - The server SHOULD interpret this method as meaning that the client is unable to - process the message at this time. - </doc> - </rule> - - <!-- TODO: Rule split? --> - - <rule name = "02"> - <doc> - A client MUST NOT use this method as a means of selecting messages to process. A - rejected message MAY be discarded or dead-lettered, not necessarily passed to - another client. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "requeue" domain = "bit" label = "requeue the message"> - <doc> - If this field is zero, the message will be discarded. If this bit is 1, the - server will attempt to requeue the message. - </doc> - - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The server MUST NOT deliver the message to the same client within the - context of the current channel. The recommended strategy is to attempt to - deliver the message to an alternative consumer, and if that is not possible, - to move the message to a dead-letter queue. The server MAY use more - sophisticated tracking to hold the message on the queue and redeliver it to - the same client at a later stage. - </doc> - </rule> - </field> - </method> - </class> - - <!-- == STREAM =========================================================== --> - - <class name = "stream" handler = "channel" index = "80" label = "work with streaming content"> - <doc> - The stream class provides methods that support multimedia streaming. The stream class - uses the following semantics: one message is one packet of data; delivery is - unacknowleged and unreliable; the consumer can specify quality of service parameters - that the server can try to adhere to; lower-priority messages may be discarded in favour - of high priority messages. - </doc> - - <doc type = "grammar"> - stream = C:QOS S:QOS-OK - / C:CONSUME S:CONSUME-OK - / C:CANCEL S:CANCEL-OK - / C:PUBLISH content - / S:RETURN - / S:DELIVER content - </doc> - - <chassis name = "server" implement = "MAY" /> - <chassis name = "client" implement = "MAY" /> - - <rule name = "01"> - <doc> - The server SHOULD discard stream messages on a priority basis if the queue size - exceeds some configured limit. - </doc> - </rule> - - <rule name = "02"> - <!-- TODO: Rule split? --> - <doc> - The server MUST implement at least 2 priority levels for stream messages, where - priorities 0-4 and 5-9 are treated as two distinct levels. The server MAY implement - up to 10 priority levels. - </doc> - </rule> - - <rule name = "03"> - <doc> - The server MUST implement automatic acknowledgements on stream content. That is, as - soon as a message is delivered to a client via a Deliver method, the server must - remove it from the queue. - </doc> - </rule> - - <!-- These are the properties for a Stream content --> - - <field name = "content-type" domain = "shortstr" label = "MIME content type" /> - <field name = "content-encoding" domain = "shortstr" label = "MIME content encoding" /> - <field name = "headers" domain = "table" label = "message header field table" /> - <field name = "priority" domain = "octet" label = "message priority, 0 to 9" /> - <field name = "timestamp" domain = "timestamp" label = "message timestamp" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "qos" synchronous = "1" index = "10" label = "specify quality of service"> - <doc> - This method requests a specific quality of service. The QoS can be specified for the - current channel or for all channels on the connection. The particular properties and - semantics of a qos method always depend on the content class semantics. Though the - qos method could in principle apply to both peers, it is currently meaningful only - for the server. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <response name = "qos-ok" /> - - <field name = "prefetch-size" domain = "long" label = "prefetch window in octets"> - <doc> - The client can request that messages be sent in advance so that when the client - finishes processing a message, the following message is already held locally, - rather than needing to be sent down the channel. Prefetching gives a performance - improvement. This field specifies the prefetch window size in octets. May be set - to zero, meaning "no specific limit". Note that other prefetch limits may still - apply. - </doc> - </field> - - <field name = "prefetch-count" domain = "short" label = "prefetch window in messages"> - <doc> - Specifies a prefetch window in terms of whole messages. This field may be used - in combination with the prefetch-size field; a message will only be sent in - advance if both prefetch windows (and those at the channel and connection level) - allow it. - </doc> - </field> - - <field name = "consume-rate" domain = "long" label = "transfer rate in octets/second"> - <doc> - Specifies a desired transfer rate in octets per second. This is usually - determined by the application that uses the streaming data. A value of zero - means "no limit", i.e. as rapidly as possible. - </doc> - - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The server MAY ignore the prefetch values and consume rates, depending on - the type of stream and the ability of the server to queue and/or reply it. - The server MAY drop low-priority messages in favour of high-priority - messages. - </doc> - </rule> - </field> - - <field name = "global" domain = "bit" label = "apply to entire connection"> - <doc> - By default the QoS settings apply to the current channel only. If this field is - set, they are applied to the entire connection. - </doc> - </field> - </method> - - <method name = "qos-ok" synchronous = "1" index = "11" label = "confirm the requested qos"> - <doc> - This method tells the client that the requested QoS levels could be handled by the - server. The requested QoS applies to all active consumers until a new QoS is - defined. - </doc> - - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "consume" synchronous = "1" index = "20" label = "start a queue consumer"> - <doc> - This method asks the server to start a "consumer", which is a transient request for - messages from a specific queue. Consumers last as long as the channel they were - created on, or until the client cancels them. - </doc> - - <rule name = "01"> - <doc> - The server SHOULD support at least 16 consumers per queue, unless the queue was - declared as private, and ideally, impose no limit except as defined by available - resources. - </doc> - </rule> - - <rule name = "02"> - <doc> - Streaming applications SHOULD use different channels to select different - streaming resolutions. AMQP makes no provision for filtering and/or transforming - streams except on the basis of priority-based selective delivery of individual - messages. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - <response name = "consume-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "01"> - <doc> - The client MUST provide a valid access ticket giving "read" access rights to - the realm for the queue. - </doc> - </rule> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue to consume from. If the queue name is null, - refers to the current queue for the channel, which is the last declared queue. - </doc> - - <rule name = "01"> - <doc> - If the client did not previously declare a queue, and the queue name in this - method is empty, the server MUST raise a connection exception with reply - code 530 (not allowed). - </doc> - </rule> - </field> - - <field name = "consumer-tag" domain = "consumer-tag"> - <doc> - Specifies the identifier for the consumer. The consumer tag is local to a - connection, so two clients can use the same consumer tags. If this field is - empty the server will generate a unique tag. - </doc> - - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The tag MUST NOT refer to an existing consumer. If the client attempts to - create two consumers with the same non-empty tag the server MUST raise a - connection exception with reply code 530 (not allowed). - </doc> - </rule> - </field> - - <field name = "no-local" domain = "no-local" /> - - <field name = "exclusive" domain = "bit" label = "request exclusive access"> - <doc> - Request exclusive consumer access, meaning only this consumer can access the - queue. - </doc> - - - <!-- Rule test name: was "amq_file_00" --> - <rule name = "01"> - <doc> - If the server cannot grant exclusive access to the queue when asked, - - because there are other consumers active - it MUST raise a channel exception - with return code 405 (resource locked). - </doc> - </rule> - </field> - </method> - - <method name = "consume-ok" synchronous = "1" index = "21" label = "confirm a new consumer"> - <doc> - This method provides the client with a consumer tag which it may use in methods that - work with the consumer. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag"> - <doc>Holds the consumer tag specified by the client or provided by the server.</doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "cancel" synchronous = "1" index = "30" label = "end a queue consumer"> - <doc> - This method cancels a consumer. Since message delivery is asynchronous the client - may continue to receive messages for a short while after canceling a consumer. It - may process or discard these as appropriate. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <response name = "cancel-ok" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - </method> - - <method name = "cancel-ok" synchronous = "1" index = "31" label = "confirm a cancelled consumer"> - <doc>This method confirms that the cancellation was completed.</doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "publish" content = "1" index = "40" label = "publish a message"> - <doc> - This method publishes a message to a specific exchange. The message will be routed - to queues as defined by the exchange configuration and distributed to any active - consumers as appropriate. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "01"> - <doc> - The client MUST provide a valid access ticket giving "write" access rights - to the access realm for the exchange. - </doc> - </rule> - </field> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange to publish to. The exchange name can be - empty, meaning the default exchange. If the exchange name is specified, and that - exchange does not exist, the server will raise a channel exception. - </doc> - - <rule name = "01"> - <doc> - The server MUST accept a blank exchange name to mean the default exchange. - </doc> - </rule> - - <rule name = "02"> - <doc> - If the exchange was declared as an internal exchange, the server MUST - respond with a reply code 403 (access refused) and raise a channel - exception. - </doc> - </rule> - - <rule name = "03"> - <doc> - The exchange MAY refuse stream content in which case it MUST respond with a - reply code 540 (not implemented) and raise a channel exception. - </doc> - </rule> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc> - Specifies the routing key for the message. The routing key is used for routing - messages depending on the exchange configuration. - </doc> - </field> - - <field name = "mandatory" domain = "bit" label = "indicate mandatory routing"> - <doc> - This flag tells the server how to react if the message cannot be routed to a - queue. If this flag is set, the server will return an unroutable message with a - Return method. If this flag is zero, the server silently drops the message. - </doc> - - <!-- Rule test name: was "amq_stream_00" --> - <rule name = "01"> - <doc>The server SHOULD implement the mandatory flag.</doc> - </rule> - </field> - - <field name = "immediate" domain = "bit" label = "request immediate delivery"> - <doc> - This flag tells the server how to react if the message cannot be routed to a - queue consumer immediately. If this flag is set, the server will return an - undeliverable message with a Return method. If this flag is zero, the server - will queue the message, but with no guarantee that it will ever be consumed. - </doc> - - <!-- Rule test name: was "amq_stream_00" --> - <rule name = "01"> - <doc>The server SHOULD implement the immediate flag.</doc> - </rule> - </field> - </method> - - <method name = "return" content = "1" index = "50" label = "return a failed message"> - <doc> - This method returns an undeliverable message that was published with the "immediate" - flag set, or an unroutable message published with the "mandatory" flag set. The - reply code and text provide information about the reason that the message was - undeliverable. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "reply-code" domain = "reply-code" /> - - <field name = "reply-text" domain = "reply-text" /> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange that the message was originally published to. - </doc> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc>Specifies the routing key name specified when the message was published.</doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "deliver" content = "1" index = "60" - label = "notify the client of a consumer message"> - <doc> - This method delivers a message to the client, via a consumer. In the asynchronous - message delivery model, the client starts a consumer using the Consume method, then - the server responds with Deliver methods as and when messages arrive for that - consumer. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange that the message was originally published to. - </doc> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue that the message came from. Note that a single - channel can start many consumers on different queues. - </doc> - <assert check = "notnull" /> - </field> - </method> - </class> - - <!-- == TX =============================================================== --> - - <class name = "tx" handler = "channel" index = "90" label = "work with standard transactions"> - <doc> - Standard transactions provide so-called "1.5 phase commit". We can ensure that work is - never lost, but there is a chance of confirmations being lost, so that messages may be - resent. Applications that use standard transactions must be able to detect and ignore - duplicate messages. - </doc> - - <!-- TODO: Rule split? --> - - <rule name = "01"> - <doc> - An client using standard transactions SHOULD be able to track all messages received - within a reasonable period, and thus detect and reject duplicates of the same - message. It SHOULD NOT pass these to the application layer. - </doc> - </rule> - - <doc type = "grammar"> - tx = C:SELECT S:SELECT-OK - / C:COMMIT S:COMMIT-OK - / C:ROLLBACK S:ROLLBACK-OK - </doc> - - <chassis name = "server" implement = "SHOULD" /> - <chassis name = "client" implement = "MAY" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "select" synchronous = "1" index = "10" label = "select standard transaction mode"> - <doc> - This method sets the channel to use standard transactions. The client must use this - method at least once on a channel before using the Commit or Rollback methods. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "select-ok" /> - </method> - - <method name = "select-ok" synchronous = "1" index = "11" label = "confirm transaction mode"> - <doc> - This method confirms to the client that the channel was successfully set to use - standard transactions. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "commit" synchronous = "1" index = "20" label = "commit the current transaction"> - <doc> - This method commits all messages published and acknowledged in the current - transaction. A new transaction starts immediately after a commit. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "commit-ok" /> - </method> - - <method name = "commit-ok" synchronous = "1" index = "21" label = "confirm a successful commit"> - <doc> - This method confirms to the client that the commit succeeded. Note that if a commit - fails, the server raises a channel exception. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "rollback" synchronous = "1" index = "30" - label = "abandon the current transaction"> - <doc> - This method abandons all messages published and acknowledged in the current - transaction. A new transaction starts immediately after a rollback. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "rollback-ok" /> - </method> - - <method name = "rollback-ok" synchronous = "1" index = "31" label = "confirm successful rollback"> - <doc> - This method confirms to the client that the rollback succeeded. Note that if an - rollback fails, the server raises a channel exception. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - </class> - - <!-- == DTX ============================================================== --> - - <class name = "dtx" handler = "channel" index = "100" label = "work with distributed transactions"> - <doc> - Distributed transactions provide so-called "2-phase commit". The AMQP distributed - transaction model supports the X-Open XA architecture and other distributed transaction - implementations. The Dtx class assumes that the server has a private communications - channel (not AMQP) to a distributed transaction coordinator. - </doc> - - <doc type = "grammar"> - dtx = C:SELECT S:SELECT-OK - C:START S:START-OK - </doc> - - <chassis name = "server" implement = "MAY" /> - <chassis name = "client" implement = "MAY" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "select" synchronous = "1" index = "10" label = "select standard transaction mode"> - <doc> - This method sets the channel to use distributed transactions. The client must use - this method at least once on a channel before using the Start method. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "select-ok" /> - </method> - - <method name = "select-ok" synchronous = "1" index = "11" label = "confirm transaction mode"> - <doc> - This method confirms to the client that the channel was successfully set to use - distributed transactions. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "start" synchronous = "1" index = "20" - label = "start a new distributed transaction"> - <doc> - This method starts a new distributed transaction. This must be the first method on a - new channel that uses the distributed transaction mode, before any methods that - publish or consume messages. - </doc> - <chassis name = "server" implement = "MAY" /> - <response name = "start-ok" /> - <field name = "dtx-identifier" domain = "shortstr" label = "transaction identifier"> - <doc> - The distributed transaction key. This identifies the transaction so that the - AMQP server can coordinate with the distributed transaction coordinator. - </doc> - <assert check = "notnull" /> - </field> - </method> - - <method name = "start-ok" synchronous = "1" index = "21" - label = "confirm the start of a new distributed transaction"> - <doc> - This method confirms to the client that the transaction started. Note that if a - start fails, the server raises a channel exception. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - </class> - - <!-- == TUNNEL =========================================================== --> - - <class name = "tunnel" handler = "tunnel" index = "110" label = "methods for protocol tunneling"> - <doc> - The tunnel methods are used to send blocks of binary data - which can be serialised AMQP - methods or other protocol frames - between AMQP peers. - </doc> - - <doc type = "grammar"> - tunnel = C:REQUEST - / S:REQUEST - </doc> - - <chassis name = "server" implement = "MAY" /> - <chassis name = "client" implement = "MAY" /> - - <field name = "headers" domain = "table" label = "message header field table" /> - <field name = "proxy-name" domain = "shortstr" label = "identity of tunnelling proxy" /> - <field name = "data-name" domain = "shortstr" label = "name or type of message being tunnelled" /> - <field name = "durable" domain = "octet" label = "message durability indicator" /> - <field name = "broadcast" domain = "octet" label = "message broadcast mode" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "request" content = "1" index = "10" label = "sends a tunnelled method"> - <doc> - This method tunnels a block of binary data, which can be an encoded - AMQP method or other data. The binary data is sent as the content for - the Tunnel.Request method. - </doc> - <chassis name = "server" implement = "MUST" /> - <field name = "meta-data" domain = "table" label = "meta data for the tunnelled block"> - <doc> - This field table holds arbitrary meta-data that the sender needs to - pass to the recipient. - </doc> - </field> - </method> - </class> -</amqp> diff --git a/gentools/xml-src/amqp-0.8.test.xml b/gentools/xml-src/amqp-0.8.test.xml deleted file mode 100644 index b0adf31828..0000000000 --- a/gentools/xml-src/amqp-0.8.test.xml +++ /dev/null @@ -1,3959 +0,0 @@ -<?xml version="1.0"?> - -<!-- - Copyright Notice - ================ - (c) Copyright JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., - iMatix Corporation, IONA\ufffd Technologies, Red Hat, Inc., - TWIST Process Innovations, and 29West Inc. 2006. All rights reserved. - - License - ======= - JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., iMatix - Corporation, IONA\ufffd Technologies, Red Hat, Inc., TWIST Process Innovations, and - 29West Inc. (collectively, the "Authors") each hereby grants to you a worldwide, - perpetual, royalty-free, nontransferable, nonexclusive license to - (i) copy, display, and implement the Advanced Messaging Queue Protocol - ("AMQP") Specification and (ii) the Licensed Claims that are held by - the Authors, all for the purpose of implementing the Advanced Messaging - Queue Protocol Specification. Your license and any rights under this - Agreement will terminate immediately without notice from - any Author if you bring any claim, suit, demand, or action related to - the Advanced Messaging Queue Protocol Specification against any Author. - Upon termination, you shall destroy all copies of the Advanced Messaging - Queue Protocol Specification in your possession or control. - - As used hereunder, "Licensed Claims" means those claims of a patent or - patent application, throughout the world, excluding design patents and - design registrations, owned or controlled, or that can be sublicensed - without fee and in compliance with the requirements of this - Agreement, by an Author or its affiliates now or at any - future time and which would necessarily be infringed by implementation - of the Advanced Messaging Queue Protocol Specification. A claim is - necessarily infringed hereunder only when it is not possible to avoid - infringing it because there is no plausible non-infringing alternative - for implementing the required portions of the Advanced Messaging Queue - Protocol Specification. Notwithstanding the foregoing, Licensed Claims - shall not include any claims other than as set forth above even if - contained in the same patent as Licensed Claims; or that read solely - on any implementations of any portion of the Advanced Messaging Queue - Protocol Specification that are not required by the Advanced Messaging - Queue Protocol Specification, or that, if licensed, would require a - payment of royalties by the licensor to unaffiliated third parties. - Moreover, Licensed Claims shall not include (i) any enabling technologies - that may be necessary to make or use any Licensed Product but are not - themselves expressly set forth in the Advanced Messaging Queue Protocol - Specification (e.g., semiconductor manufacturing technology, compiler - technology, object oriented technology, networking technology, operating - system technology, and the like); or (ii) the implementation of other - published standards developed elsewhere and merely referred to in the - body of the Advanced Messaging Queue Protocol Specification, or - (iii) any Licensed Product and any combinations thereof the purpose or - function of which is not required for compliance with the Advanced - Messaging Queue Protocol Specification. For purposes of this definition, - the Advanced Messaging Queue Protocol Specification shall be deemed to - include both architectural and interconnection requirements essential - for interoperability and may also include supporting source code artifacts - where such architectural, interconnection requirements and source code - artifacts are expressly identified as being required or documentation to - achieve compliance with the Advanced Messaging Queue Protocol Specification. - - As used hereunder, "Licensed Products" means only those specific portions - of products (hardware, software or combinations thereof) that implement - and are compliant with all relevant portions of the Advanced Messaging - Queue Protocol Specification. - - The following disclaimers, which you hereby also acknowledge as to any - use you may make of the Advanced Messaging Queue Protocol Specification: - - THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION IS PROVIDED "AS IS," - AND THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR - IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE - CONTENTS OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION ARE - SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF THE ADVANCED - MESSAGING QUEUE PROTOCOL SPECIFICATION WILL NOT INFRINGE ANY THIRD PARTY - PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. - - THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, - INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY - USE, IMPLEMENTATION OR DISTRIBUTION OF THE ADVANCED MESSAGING QUEUE - PROTOCOL SPECIFICATION. - - The name and trademarks of the Authors may NOT be used in any manner, - including advertising or publicity pertaining to the Advanced Messaging - Queue Protocol Specification or its contents without specific, written - prior permission. Title to copyright in the Advanced Messaging Queue - Protocol Specification will at all times remain with the Authors. - - No other rights are granted by implication, estoppel or otherwise. - - Upon termination of your license or rights under this Agreement, you - shall destroy all copies of the Advanced Messaging Queue Protocol - Specification in your possession or control. - - Trademarks - ========== - "JPMorgan", "JPMorgan Chase", "Chase", the JPMorgan Chase logo and the - Octagon Symbol are trademarks of JPMorgan Chase & Co. - - IMATIX and the iMatix logo are trademarks of iMatix Corporation sprl. - - IONA, IONA Technologies, and the IONA logos are trademarks of IONA - Technologies PLC and/or its subsidiaries. - - LINUX is a trademark of Linus Torvalds. RED HAT and JBOSS are registered - trademarks of Red Hat, Inc. in the US and other countries. - - Java, all Java-based trademarks and OpenOffice.org are trademarks of - Sun Microsystems, Inc. in the United States, other countries, or both. - - Other company, product, or service names may be trademarks or service - marks of others. - - Links to full AMQP specification: - ================================= - http://www.envoytech.org/spec/amq/ - http://www.iona.com/opensource/amqp/ - http://www.redhat.com/solutions/specifications/amqp/ - http://www.twiststandards.org/tiki-index.php?page=AMQ - http://www.imatix.com/amqp - ---> - -<!-- -======================================================== -EDITORS: (PH) Pieter Hintjens <ph@imatix.com> - (KvdR) Kim van der Riet <kim.vdriet@redhat.com> - -NOTE: These editors have been assigned by the AMQP working group. Please do not -edit/commit this file without consulting with one of the above editors. -======================================================== - -Revision history: - 2006-06-07 (PH) - version number changed to 0.8 to conform to public - release documentation. - - 2006-05-15 (PH) - fixed comments on queue name in basic.get to clarify - use of current queue in this method. - - 2006-05-15 (PH) - fixed comments on routing key in queue.bind to clarify - how routing key is filled when empty (to allow asynch queue.declare). - - 2006-05-11 (PH) - reset version to 0.70 so that putatitive standards - group can release 2-3 major new versions before hitting 1.0 (again). - - 2006-05-11 (PH) - TODO in documentation: cycle field in frame header - has been removed. - - 2006-05-11 (PH) - added nowait option to exchange.declare, delete, - queue.declare, delete, bind, purge, basic.consume, cancel, - file.consume, cancel, stream.consume and cancel methods. - - 2006-05-11 (PH) - removed notnull rule and added explanations on queue - name in queue.bind, purge, delete, basic.consume, cancel, file.consume, - cancel, stream.consume and cancel methods. - - 2006-05-11 (PH) - added basic.qos, file.qos, and stream.qos methods that - regroup all prefetch options from the consume methods. Also removed the - prefetch option from channel.open. - - 2006-05-11 (PH) - renumbered method indexes to show request-response - nature of methods; requests are 10, 20, 30 while responses are 11, 21, - etc. - - 2006-05-11 (PH) - removed OpenAMQ extension methods from this definition - since these are maintained seperately. - - 2006-05-26 (RG) - added Basic.Recover method to allow replay of - unacknowledged messages on a channel. - - 2006-07-03 (PH) - cosmetic clean-up of Basic.Recover comments. ---> - -<amqp major="8" minor="0" port="5672" comment="AMQ protocol 0.80"> - AMQ Protocol 0.80 - -<!-- -====================================================== -== CONSTANTS -====================================================== ---> - <constant name="frame method" value="1"/> - <constant name="frame header" value="2"/> - <constant name="frame body" value="3"/> - <constant name="frame oob method" value="4"/> - <constant name="frame oob header" value="5"/> - <constant name="frame oob body" value="6"/> - <constant name="frame trace" value="7"/> - <constant name="frame heartbeat" value="8"/> - <constant name="frame min size" value="4096"/> - <constant name="frame end" value="206"/> - <constant name="reply success" value="200"> - Indicates that the method completed successfully. This reply code is - reserved for future use - the current protocol design does not use - positive confirmation and reply codes are sent only in case of an - error. -</constant> - <constant name="not delivered" value="310" class="soft error"> - The client asked for a specific message that is no longer available. - The message was delivered to another client, or was purged from the - queue for some other reason. -</constant> - <constant name="content too large" value="311" class="soft error"> - The client attempted to transfer content larger than the server - could accept at the present time. The client may retry at a later - time. -</constant> - <constant name="connection forced" value="320" class="hard error"> - An operator intervened to close the connection for some reason. - The client may retry at some later date. -</constant> - <constant name="invalid path" value="402" class="hard error"> - The client tried to work with an unknown virtual host or cluster. -</constant> - <constant name="access refused" value="403" class="soft error"> - The client attempted to work with a server entity to which it has - no due to security settings. -</constant> - <constant name="not found" value="404" class="soft error"> - The client attempted to work with a server entity that does not exist. -</constant> - <constant name="resource locked" value="405" class="soft error"> - The client attempted to work with a server entity to which it has - no access because another client is working with it. -</constant> - <constant name="frame error" value="501" class="hard error"> - The client sent a malformed frame that the server could not decode. - This strongly implies a programming error in the client. -</constant> - <constant name="syntax error" value="502" class="hard error"> - The client sent a frame that contained illegal values for one or more - fields. This strongly implies a programming error in the client. -</constant> - <constant name="command invalid" value="503" class="hard error"> - The client sent an invalid sequence of frames, attempting to perform - an operation that was considered invalid by the server. This usually - implies a programming error in the client. -</constant> - <constant name="channel error" value="504" class="hard error"> - The client attempted to work with a channel that had not been - correctly opened. This most likely indicates a fault in the client - layer. -</constant> - <constant name="resource error" value="506" class="hard error"> - The server could not complete the method because it lacked sufficient - resources. This may be due to the client creating too many of some - type of entity. -</constant> - <constant name="not allowed" value="530" class="hard error"> - The client tried to work with some entity in a manner that is - prohibited by the server, due to security settings or by some other - criteria. -</constant> - <constant name="not implemented" value="540" class="hard error"> - The client tried to use functionality that is not implemented in the - server. -</constant> - <constant name="internal error" value="541" class="hard error"> - The server could not complete the method because of an internal error. - The server may require intervention by an operator in order to resume - normal operations. -</constant> - <!-- -====================================================== -== DOMAIN TYPES -====================================================== ---> - <domain name="access ticket" type="short"> - access ticket granted by server - <doc> - An access ticket granted by the server for a certain set of access - rights within a specific realm. Access tickets are valid within the - channel where they were created, and expire when the channel closes. - </doc> - <assert check="ne" value="0"/> - </domain> - <domain name="class id" type="short"/> - <domain name="consumer tag" type="shortstr"> - consumer tag - <doc> - Identifier for the consumer, valid within the current connection. - </doc> - <rule implement="MUST"> - The consumer tag is valid only within the channel from which the - consumer was created. I.e. a client MUST NOT create a consumer in - one channel and then use it in another. - </rule> - </domain> - <domain name="delivery tag" type="longlong"> - server-assigned delivery tag - <doc> - The server-assigned and channel-specific delivery tag - </doc> - <rule implement="MUST"> - The delivery tag is valid only within the channel from which the - message was received. I.e. a client MUST NOT receive a message on - one channel and then acknowledge it on another. - </rule> - <rule implement="MUST"> - The server MUST NOT use a zero value for delivery tags. Zero is - reserved for client use, meaning "all messages so far received". - </rule> - </domain> - <domain name="exchange name" type="shortstr"> - exchange name - <doc> - The exchange name is a client-selected string that identifies - the exchange for publish methods. Exchange names may consist - of any mixture of digits, letters, and underscores. Exchange - names are scoped by the virtual host. - </doc> - <assert check="length" value="127"/> - </domain> - <domain name="known hosts" type="shortstr"> -list of known hosts -<doc> -Specifies the list of equivalent or alternative hosts that the server -knows about, which will normally include the current server itself. -Clients can cache this information and use it when reconnecting to a -server after a failure. -</doc> - <rule implement="MAY"> -The server MAY leave this field empty if it knows of no other -hosts than itself. -</rule> - </domain> - <domain name="method id" type="short"/> - <domain name="no ack" type="bit"> - no acknowledgement needed - <doc> - If this field is set the server does not expect acknowledgments - for messages. That is, when a message is delivered to the client - the server automatically and silently acknowledges it on behalf - of the client. This functionality increases performance but at - the cost of reliability. Messages can get lost if a client dies - before it can deliver them to the application. - </doc> - </domain> - <domain name="no local" type="bit"> - do not deliver own messages - <doc> - If the no-local field is set the server will not send messages to - the client that published them. - </doc> - </domain> - <domain name="path" type="shortstr"> - <doc> - Must start with a slash "/" and continue with path names - separated by slashes. A path name consists of any combination - of at least one of [A-Za-z0-9] plus zero or more of [.-_+!=:]. -</doc> - <assert check="notnull"/> - <assert check="syntax" rule="path"/> - <assert check="length" value="127"/> - </domain> - <domain name="peer properties" type="table"> - <doc> -This string provides a set of peer properties, used for -identification, debugging, and general information. -</doc> - <rule implement="SHOULD"> -The properties SHOULD contain these fields: -"product", giving the name of the peer product, "version", giving -the name of the peer version, "platform", giving the name of the -operating system, "copyright", if appropriate, and "information", -giving other general information. -</rule> - </domain> - <domain name="queue name" type="shortstr"> - queue name - <doc> - The queue name identifies the queue within the vhost. Queue - names may consist of any mixture of digits, letters, and - underscores. - </doc> - <assert check="length" value="127"/> - </domain> - <domain name="redelivered" type="bit"> - message is being redelivered - <doc> - This indicates that the message has been previously delivered to - this or another client. - </doc> - <rule implement="SHOULD"> - The server SHOULD try to signal redelivered messages when it can. - When redelivering a message that was not successfully acknowledged, - the server SHOULD deliver it to the original client if possible. - </rule> - <rule implement="MUST"> - The client MUST NOT rely on the redelivered field but MUST take it - as a hint that the message may already have been processed. A - fully robust client must be able to track duplicate received messages - on non-transacted, and locally-transacted channels. - </rule> - </domain> - <domain name="reply code" type="short"> -reply code from server -<doc> - The reply code. The AMQ reply codes are defined in AMQ RFC 011. -</doc> - <assert check="notnull"/> - </domain> - <domain name="reply text" type="shortstr"> -localised reply text -<doc> - The localised reply text. This text can be logged as an aid to - resolving issues. -</doc> - <assert check="notnull"/> - </domain> - <class name="connection" handler="connection" index="10"> - <!-- -====================================================== -== CONNECTION -====================================================== ---> - work with socket connections -<doc> - The connection class provides methods for a client to establish a - network connection to a server, and for both peers to operate the - connection thereafter. -</doc> - <doc name="grammar"> - connection = open-connection *use-connection close-connection - open-connection = C:protocol-header - S:START C:START-OK - *challenge - S:TUNE C:TUNE-OK - C:OPEN S:OPEN-OK | S:REDIRECT - challenge = S:SECURE C:SECURE-OK - use-connection = *channel - close-connection = C:CLOSE S:CLOSE-OK - / S:CLOSE C:CLOSE-OK -</doc> - <chassis name="server" implement="MUST"/> - <chassis name="client" implement="MUST"/> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="start" synchronous="1" index="10"> - start connection negotiation - <doc> - This method starts the connection negotiation process by telling - the client the protocol version that the server proposes, along - with a list of security mechanisms which the client can use for - authentication. - </doc> - <rule implement="MUST"> - If the client cannot handle the protocol version suggested by the - server it MUST close the socket connection. - </rule> - <rule implement="MUST"> - The server MUST provide a protocol version that is lower than or - equal to that requested by the client in the protocol header. If - the server cannot support the specified protocol it MUST NOT send - this method, but MUST close the socket connection. - </rule> - <chassis name="client" implement="MUST"/> - <response name="start-ok"/> - <field name="version major" type="octet"> - protocol major version - <doc> - The protocol major version that the server agrees to use, which - cannot be higher than the client's major version. - </doc> - </field> - <field name="version minor" type="octet"> - protocol major version - <doc> - The protocol minor version that the server agrees to use, which - cannot be higher than the client's minor version. - </doc> - </field> - <field name="server properties" domain="peer properties"> - server properties - </field> - <field name="mechanisms" type="longstr"> - available security mechanisms - <doc> - A list of the security mechanisms that the server supports, delimited - by spaces. Currently ASL supports these mechanisms: PLAIN. - </doc> - <see name="security mechanisms"/> - <assert check="notnull"/> - </field> - <field name="locales" type="longstr"> - available message locales - <doc> - A list of the message locales that the server supports, delimited - by spaces. The locale defines the language in which the server - will send reply texts. - </doc> - <rule implement="MUST"> - All servers MUST support at least the en_US locale. - </rule> - <assert check="notnull"/> - </field> - </method> - <method name="start-ok" synchronous="1" index="11"> - select security mechanism and locale - <doc> - This method selects a SASL security mechanism. ASL uses SASL - (RFC2222) to negotiate authentication and encryption. - </doc> - <chassis name="server" implement="MUST"/> - <field name="client properties" domain="peer properties"> - client properties - </field> - <field name="mechanism" type="shortstr"> - selected security mechanism - <doc> - A single security mechanisms selected by the client, which must be - one of those specified by the server. - </doc> - <rule implement="SHOULD"> - The client SHOULD authenticate using the highest-level security - profile it can handle from the list provided by the server. - </rule> - <rule implement="MUST"> - The mechanism field MUST contain one of the security mechanisms - proposed by the server in the Start method. If it doesn't, the - server MUST close the socket. - </rule> - <assert check="notnull"/> - </field> - <field name="response" type="longstr"> - security response data - <doc> - A block of opaque data passed to the security mechanism. The contents - of this data are defined by the SASL security mechanism. For the - PLAIN security mechanism this is defined as a field table holding - two fields, LOGIN and PASSWORD. - </doc> - <assert check="notnull"/> - </field> - <field name="locale" type="shortstr"> - selected message locale - <doc> - A single message local selected by the client, which must be one - of those specified by the server. - </doc> - <assert check="notnull"/> - </field> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="secure" synchronous="1" index="20"> - security mechanism challenge - <doc> - The SASL protocol works by exchanging challenges and responses until - both peers have received sufficient information to authenticate each - other. This method challenges the client to provide more information. - </doc> - <chassis name="client" implement="MUST"/> - <response name="secure-ok"/> - <field name="challenge" type="longstr"> - security challenge data - <doc> - Challenge information, a block of opaque binary data passed to - the security mechanism. - </doc> - <see name="security mechanisms"/> - </field> - </method> - <method name="secure-ok" synchronous="1" index="21"> - security mechanism response - <doc> - This method attempts to authenticate, passing a block of SASL data - for the security mechanism at the server side. - </doc> - <chassis name="server" implement="MUST"/> - <field name="response" type="longstr"> - security response data - <doc> - A block of opaque data passed to the security mechanism. The contents - of this data are defined by the SASL security mechanism. - </doc> - <assert check="notnull"/> - </field> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="tune" synchronous="1" index="30"> - propose connection tuning parameters - <doc> - This method proposes a set of connection configuration values - to the client. The client can accept and/or adjust these. - </doc> - <chassis name="client" implement="MUST"/> - <response name="tune-ok"/> - <field name="channel max" type="short"> - proposed maximum channels - <doc> - The maximum total number of channels that the server allows - per connection. Zero means that the server does not impose a - fixed limit, but the number of allowed channels may be limited - by available server resources. - </doc> - </field> - <field name="frame max" type="long"> - proposed maximum frame size - <doc> - The largest frame size that the server proposes for the - connection. The client can negotiate a lower value. Zero means - that the server does not impose any specific limit but may reject - very large frames if it cannot allocate resources for them. - </doc> - <rule implement="MUST"> - Until the frame-max has been negotiated, both peers MUST accept - frames of up to 4096 octets large. The minimum non-zero value for - the frame-max field is 4096. - </rule> - </field> - <field name="heartbeat" type="short"> - desired heartbeat delay - <doc> - The delay, in seconds, of the connection heartbeat that the server - wants. Zero means the server does not want a heartbeat. - </doc> - </field> - </method> - <method name="tune-ok" synchronous="1" index="31"> - negotiate connection tuning parameters - <doc> - This method sends the client's connection tuning parameters to the - server. Certain fields are negotiated, others provide capability - information. - </doc> - <chassis name="server" implement="MUST"/> - <field name="channel max" type="short"> - negotiated maximum channels - <doc> - The maximum total number of channels that the client will use - per connection. May not be higher than the value specified by - the server. - </doc> - <rule implement="MAY"> - The server MAY ignore the channel-max value or MAY use it for - tuning its resource allocation. - </rule> - <assert check="notnull"/> - <assert check="le" method="tune" field="channel max"/> - </field> - <field name="frame max" type="long"> - negotiated maximum frame size - <doc> - The largest frame size that the client and server will use for - the connection. Zero means that the client does not impose any - specific limit but may reject very large frames if it cannot - allocate resources for them. Note that the frame-max limit - applies principally to content frames, where large contents - can be broken into frames of arbitrary size. - </doc> - <rule implement="MUST"> - Until the frame-max has been negotiated, both peers must accept - frames of up to 4096 octets large. The minimum non-zero value for - the frame-max field is 4096. - </rule> - </field> - <field name="heartbeat" type="short"> - desired heartbeat delay - <doc> - The delay, in seconds, of the connection heartbeat that the client - wants. Zero means the client does not want a heartbeat. - </doc> - </field> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="open" synchronous="1" index="40"> - open connection to virtual host - <doc> - This method opens a connection to a virtual host, which is a - collection of resources, and acts to separate multiple application - domains within a server. - </doc> - <rule implement="MUST"> - The client MUST open the context before doing any work on the - connection. - </rule> - <chassis name="server" implement="MUST"/> - <response name="open-ok"/> - <response name="redirect"/> - <field name="virtual host" domain="path"> - virtual host name - <assert check="regexp" value="^[a-zA-Z0-9/-_]+$"/> - <doc> - The name of the virtual host to work with. - </doc> - <rule implement="MUST"> - If the server supports multiple virtual hosts, it MUST enforce a - full separation of exchanges, queues, and all associated entities - per virtual host. An application, connected to a specific virtual - host, MUST NOT be able to access resources of another virtual host. - </rule> - <rule implement="SHOULD"> - The server SHOULD verify that the client has permission to access - the specified virtual host. - </rule> - <rule implement="MAY"> - The server MAY configure arbitrary limits per virtual host, such - as the number of each type of entity that may be used, per - connection and/or in total. - </rule> - </field> - <field name="capabilities" type="shortstr"> - required capabilities - <doc> - The client may specify a number of capability names, delimited by - spaces. The server can use this string to how to process the - client's connection request. - </doc> - </field> - <field name="insist" type="bit"> - insist on connecting to server - <doc> - In a configuration with multiple load-sharing servers, the server - may respond to a Connection.Open method with a Connection.Redirect. - The insist option tells the server that the client is insisting on - a connection to the specified server. - </doc> - <rule implement="SHOULD"> - When the client uses the insist option, the server SHOULD accept - the client connection unless it is technically unable to do so. - </rule> - </field> - </method> - <method name="open-ok" synchronous="1" index="41"> - signal that the connection is ready - <doc> - This method signals to the client that the connection is ready for - use. - </doc> - <chassis name="client" implement="MUST"/> - <field name="known hosts" domain="known hosts"/> - </method> - <method name="redirect" synchronous="1" index="50"> - asks the client to use a different server - <doc> - This method redirects the client to another server, based on the - requested virtual host and/or capabilities. - </doc> - <rule implement="SHOULD"> - When getting the Connection.Redirect method, the client SHOULD - reconnect to the host specified, and if that host is not present, - to any of the hosts specified in the known-hosts list. - </rule> - <chassis name="client" implement="MAY"/> - <field name="host" type="shortstr"> - server to connect to - <doc> - Specifies the server to connect to. This is an IP address or a - DNS name, optionally followed by a colon and a port number. If - no port number is specified, the client should use the default - port number for the protocol. - </doc> - <assert check="notnull"/> - </field> - <field name="known hosts" domain="known hosts"/> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="close" synchronous="1" index="60"> - request a connection close - <doc> - This method indicates that the sender wants to close the connection. - This may be due to internal conditions (e.g. a forced shut-down) or - due to an error handling a specific method, i.e. an exception. When - a close is due to an exception, the sender provides the class and - method id of the method which caused the exception. - </doc> - <rule implement="MUST"> - After sending this method any received method except the Close-OK - method MUST be discarded. - </rule> - <rule implement="MAY"> - The peer sending this method MAY use a counter or timeout to - detect failure of the other peer to respond correctly with - the Close-OK method. - </rule> - <rule implement="MUST"> - When a server receives the Close method from a client it MUST - delete all server-side resources associated with the client's - context. A client CANNOT reconnect to a context after sending - or receiving a Close method. - </rule> - <chassis name="client" implement="MUST"/> - <chassis name="server" implement="MUST"/> - <response name="close-ok"/> - <field name="reply code" domain="reply code"/> - <field name="reply text" domain="reply text"/> - <field name="class id" domain="class id"> - failing method class - <doc> - When the close is provoked by a method exception, this is the - class of the method. - </doc> - </field> - <field name="method id" domain="class id"> - failing method ID - <doc> - When the close is provoked by a method exception, this is the - ID of the method. - </doc> - </field> - </method> - <method name="close-ok" synchronous="1" index="61"> - confirm a connection close - <doc> - This method confirms a Connection.Close method and tells the - recipient that it is safe to release resources for the connection - and close the socket. - </doc> - <rule implement="SHOULD"> - A peer that detects a socket closure without having received a - Close-Ok handshake method SHOULD log the error. - </rule> - <chassis name="client" implement="MUST"/> - <chassis name="server" implement="MUST"/> - </method> - </class> - <class name="channel" handler="channel" index="20"> - <!-- -====================================================== -== CHANNEL -====================================================== ---> - work with channels -<doc> - The channel class provides methods for a client to establish a virtual - connection - a channel - to a server and for both peers to operate the - virtual connection thereafter. -</doc> - <doc name="grammar"> - channel = open-channel *use-channel close-channel - open-channel = C:OPEN S:OPEN-OK - use-channel = C:FLOW S:FLOW-OK - / S:FLOW C:FLOW-OK - / S:ALERT - / functional-class - close-channel = C:CLOSE S:CLOSE-OK - / S:CLOSE C:CLOSE-OK -</doc> - <chassis name="server" implement="MUST"/> - <chassis name="client" implement="MUST"/> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="open" synchronous="1" index="10"> - open a channel for use - <doc> - This method opens a virtual connection (a channel). - </doc> - <rule implement="MUST"> - This method MUST NOT be called when the channel is already open. - </rule> - <chassis name="server" implement="MUST"/> - <response name="open-ok"/> - <field name="out of band" type="shortstr"> - out-of-band settings - <doc> - Configures out-of-band transfers on this channel. The syntax and - meaning of this field will be formally defined at a later date. - </doc> - <assert check="null"/> - </field> - </method> - <method name="open-ok" synchronous="1" index="11"> - signal that the channel is ready - <doc> - This method signals to the client that the channel is ready for use. - </doc> - <chassis name="client" implement="MUST"/> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="flow" synchronous="1" index="20"> - enable/disable flow from peer - <doc> - This method asks the peer to pause or restart the flow of content - data. This is a simple flow-control mechanism that a peer can use - to avoid oveflowing its queues or otherwise finding itself receiving - more messages than it can process. Note that this method is not - intended for window control. The peer that receives a request to - stop sending content should finish sending the current content, if - any, and then wait until it receives a Flow restart method. - </doc> - <rule implement="MAY"> - When a new channel is opened, it is active. Some applications - assume that channels are inactive until started. To emulate this - behaviour a client MAY open the channel, then pause it. - </rule> - <rule implement="SHOULD"> - When sending content data in multiple frames, a peer SHOULD monitor - the channel for incoming methods and respond to a Channel.Flow as - rapidly as possible. - </rule> - <rule implement="MAY"> - A peer MAY use the Channel.Flow method to throttle incoming content - data for internal reasons, for example, when exchangeing data over a - slower connection. - </rule> - <rule implement="MAY"> - The peer that requests a Channel.Flow method MAY disconnect and/or - ban a peer that does not respect the request. - </rule> - <chassis name="server" implement="MUST"/> - <chassis name="client" implement="MUST"/> - <response name="flow-ok"/> - <field name="active" type="bit"> - start/stop content frames - <doc> - If 1, the peer starts sending content frames. If 0, the peer - stops sending content frames. - </doc> - </field> - </method> - <method name="flow-ok" index="21"> - confirm a flow method - <doc> - Confirms to the peer that a flow command was received and processed. - </doc> - <chassis name="server" implement="MUST"/> - <chassis name="client" implement="MUST"/> - <field name="active" type="bit"> - current flow setting - <doc> - Confirms the setting of the processed flow method: 1 means the - peer will start sending or continue to send content frames; 0 - means it will not. - </doc> - </field> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="alert" index="30"> - send a non-fatal warning message - <doc> - This method allows the server to send a non-fatal warning to the - client. This is used for methods that are normally asynchronous - and thus do not have confirmations, and for which the server may - detect errors that need to be reported. Fatal errors are handled - as channel or connection exceptions; non-fatal errors are sent - through this method. - </doc> - <chassis name="client" implement="MUST"/> - <field name="reply code" domain="reply code"/> - <field name="reply text" domain="reply text"/> - <field name="details" type="table"> - detailed information for warning - <doc> - A set of fields that provide more information about the - problem. The meaning of these fields are defined on a - per-reply-code basis (TO BE DEFINED). - </doc> - </field> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="close" synchronous="1" index="40"> - request a channel close - <doc> - This method indicates that the sender wants to close the channel. - This may be due to internal conditions (e.g. a forced shut-down) or - due to an error handling a specific method, i.e. an exception. When - a close is due to an exception, the sender provides the class and - method id of the method which caused the exception. - </doc> - <rule implement="MUST"> - After sending this method any received method except - Channel.Close-OK MUST be discarded. - </rule> - <rule implement="MAY"> - The peer sending this method MAY use a counter or timeout to detect - failure of the other peer to respond correctly with Channel.Close-OK.. - </rule> - <chassis name="client" implement="MUST"/> - <chassis name="server" implement="MUST"/> - <response name="close-ok"/> - <field name="reply code" domain="reply code"/> - <field name="reply text" domain="reply text"/> - <field name="class id" domain="class id"> - failing method class - <doc> - When the close is provoked by a method exception, this is the - class of the method. - </doc> - </field> - <field name="method id" domain="method id"> - failing method ID - <doc> - When the close is provoked by a method exception, this is the - ID of the method. - </doc> - </field> - </method> - <method name="close-ok" synchronous="1" index="41"> - confirm a channel close - <doc> - This method confirms a Channel.Close method and tells the recipient - that it is safe to release resources for the channel and close the - socket. - </doc> - <rule implement="SHOULD"> - A peer that detects a socket closure without having received a - Channel.Close-Ok handshake method SHOULD log the error. - </rule> - <chassis name="client" implement="MUST"/> - <chassis name="server" implement="MUST"/> - </method> - </class> - <class name="access" handler="connection" index="30"> - <!-- -====================================================== -== ACCESS CONTROL -====================================================== ---> - work with access tickets -<doc> - The protocol control access to server resources using access tickets. - A client must explicitly request access tickets before doing work. - An access ticket grants a client the right to use a specific set of - resources - called a "realm" - in specific ways. -</doc> - <doc name="grammar"> - access = C:REQUEST S:REQUEST-OK -</doc> - <chassis name="server" implement="MUST"/> - <chassis name="client" implement="MUST"/> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="request" synchronous="1" index="10"> - request an access ticket - <doc> - This method requests an access ticket for an access realm. - The server responds by granting the access ticket. If the - client does not have access rights to the requested realm - this causes a connection exception. Access tickets are a - per-channel resource. - </doc> - <rule implement="MUST"> - The realm name MUST start with either "/data" (for application - resources) or "/admin" (for server administration resources). - If the realm starts with any other path, the server MUST raise - a connection exception with reply code 403 (access refused). - </rule> - <rule implement="MUST"> - The server MUST implement the /data realm and MAY implement the - /admin realm. The mapping of resources to realms is not - defined in the protocol - this is a server-side configuration - issue. - </rule> - <chassis name="server" implement="MUST"/> - <response name="request-ok"/> - <field name="realm" domain="path"> - name of requested realm - <rule implement="MUST"> - If the specified realm is not known to the server, the server - must raise a channel exception with reply code 402 (invalid - path). - </rule> - </field> - <field name="exclusive" type="bit"> - request exclusive access - <doc> - Request exclusive access to the realm. If the server cannot grant - this - because there are other active tickets for the realm - it - raises a channel exception. - </doc> - </field> - <field name="passive" type="bit"> - request passive access - <doc> - Request message passive access to the specified access realm. - Passive access lets a client get information about resources in - the realm but not to make any changes to them. - </doc> - </field> - <field name="active" type="bit"> - request active access - <doc> - Request message active access to the specified access realm. - Acvtive access lets a client get create and delete resources in - the realm. - </doc> - </field> - <field name="write" type="bit"> - request write access - <doc> - Request write access to the specified access realm. Write access - lets a client publish messages to all exchanges in the realm. - </doc> - </field> - <field name="read" type="bit"> - request read access - <doc> - Request read access to the specified access realm. Read access - lets a client consume messages from queues in the realm. - </doc> - </field> - </method> - <method name="request-ok" synchronous="1" index="11"> - grant access to server resources - <doc> - This method provides the client with an access ticket. The access - ticket is valid within the current channel and for the lifespan of - the channel. - </doc> - <rule implement="MUST"> - The client MUST NOT use access tickets except within the same - channel as originally granted. - </rule> - <rule implement="MUST"> - The server MUST isolate access tickets per channel and treat an - attempt by a client to mix these as a connection exception. - </rule> - <chassis name="client" implement="MUST"/> - <field name="ticket" domain="access ticket"/> - </method> - </class> - <class name="exchange" handler="channel" index="40"> - <!-- -====================================================== -== EXCHANGES (or "routers", if you prefer) -== (Or matchers, plugins, extensions, agents,... Routing is just one of -== the many fun things an exchange can do.) -====================================================== ---> - work with exchanges -<doc> - Exchanges match and distribute messages across queues. Exchanges can be - configured in the server or created at runtime. -</doc> - <doc name="grammar"> - exchange = C:DECLARE S:DECLARE-OK - / C:DELETE S:DELETE-OK -</doc> - <chassis name="server" implement="MUST"/> - <chassis name="client" implement="MUST"/> - <rule implement="MUST"> - <test>amq_exchange_19</test> - The server MUST implement the direct and fanout exchange types, and - predeclare the corresponding exchanges named amq.direct and amq.fanout - in each virtual host. The server MUST also predeclare a direct - exchange to act as the default exchange for content Publish methods - and for default queue bindings. -</rule> - <rule implement="SHOULD"> - <test>amq_exchange_20</test> - The server SHOULD implement the topic exchange type, and predeclare - the corresponding exchange named amq.topic in each virtual host. -</rule> - <rule implement="MAY"> - <test>amq_exchange_21</test> - The server MAY implement the system exchange type, and predeclare the - corresponding exchanges named amq.system in each virtual host. If the - client attempts to bind a queue to the system exchange, the server - MUST raise a connection exception with reply code 507 (not allowed). -</rule> - <rule implement="MUST"> - <test>amq_exchange_22</test> - The default exchange MUST be defined as internal, and be inaccessible - to the client except by specifying an empty exchange name in a content - Publish method. That is, the server MUST NOT let clients make explicit - bindings to this exchange. -</rule> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="declare" synchronous="1" index="10"> - declare exchange, create if needed - <doc> - This method creates an exchange if it does not already exist, and if the - exchange exists, verifies that it is of the correct and expected class. - </doc> - <rule implement="SHOULD"> - <test>amq_exchange_23</test> - The server SHOULD support a minimum of 16 exchanges per virtual host - and ideally, impose no limit except as defined by available resources. - </rule> - <chassis name="server" implement="MUST"/> - <response name="declare-ok"/> - <field name="ticket" domain="access ticket"> - <doc> - When a client defines a new exchange, this belongs to the access realm - of the ticket used. All further work done with that exchange must be - done with an access ticket for the same realm. - </doc> - <rule implement="MUST"> - The client MUST provide a valid access ticket giving "active" access - to the realm in which the exchange exists or will be created, or - "passive" access if the if-exists flag is set. - </rule> - </field> - <field name="exchange" domain="exchange name"> - <rule implement="MUST"> - <test>amq_exchange_15</test> - Exchange names starting with "amq." are reserved for predeclared - and standardised exchanges. If the client attempts to create an - exchange starting with "amq.", the server MUST raise a channel - exception with reply code 403 (access refused). - </rule> - <assert check="regexp" value="^[a-zA-Z0-9-_.:]+$"/> - </field> - <field name="type" type="shortstr"> - exchange type - <doc> - Each exchange belongs to one of a set of exchange types implemented - by the server. The exchange types define the functionality of the - exchange - i.e. how messages are routed through it. It is not valid - or meaningful to attempt to change the type of an existing exchange. - </doc> - <rule implement="MUST"> - <test>amq_exchange_16</test> - If the exchange already exists with a different type, the server - MUST raise a connection exception with a reply code 507 (not allowed). - </rule> - <rule implement="MUST"> - <test>amq_exchange_18</test> - If the server does not support the requested exchange type it MUST - raise a connection exception with a reply code 503 (command invalid). - </rule> - <assert check="regexp" value="^[a-zA-Z0-9-_.:]+$"/> - </field> - <field name="passive" type="bit"> - do not create exchange - <doc> - If set, the server will not create the exchange. The client can use - this to check whether an exchange exists without modifying the server - state. - </doc> - <rule implement="MUST"> - <test>amq_exchange_05</test> - If set, and the exchange does not already exist, the server MUST - raise a channel exception with reply code 404 (not found). - </rule> - </field> - <field name="durable" type="bit"> - request a durable exchange - <doc> - If set when creating a new exchange, the exchange will be marked as - durable. Durable exchanges remain active when a server restarts. - Non-durable exchanges (transient exchanges) are purged if/when a - server restarts. - </doc> - <rule implement="MUST"> - <test>amq_exchange_24</test> - The server MUST support both durable and transient exchanges. - </rule> - <rule implement="MUST"> - The server MUST ignore the durable field if the exchange already - exists. - </rule> - </field> - <field name="auto delete" type="bit"> - auto-delete when unused - <doc> - If set, the exchange is deleted when all queues have finished - using it. - </doc> - <rule implement="SHOULD"> - <test>amq_exchange_02</test> - The server SHOULD allow for a reasonable delay between the point - when it determines that an exchange is not being used (or no longer - used), and the point when it deletes the exchange. At the least it - must allow a client to create an exchange and then bind a queue to - it, with a small but non-zero delay between these two actions. - </rule> - <rule implement="MUST"> - <test>amq_exchange_25</test> - The server MUST ignore the auto-delete field if the exchange already - exists. - </rule> - </field> - <field name="internal" type="bit"> - create internal exchange - <doc> - If set, the exchange may not be used directly by publishers, but - only when bound to other exchanges. Internal exchanges are used to - construct wiring that is not visible to applications. - </doc> - </field> - - <field name = "nowait" type = "bit"> - do not send a reply method - <doc> - If set, the server will not respond to the method. The client should - not wait for a reply method. If the server could not complete the - method it will raise a channel or connection exception. - </doc> - </field> - - <field name="arguments" type="table"> - arguments for declaration - <doc> - A set of arguments for the declaration. The syntax and semantics - of these arguments depends on the server implementation. This - field is ignored if passive is 1. - </doc> - </field> - </method> - <method name="declare-ok" synchronous="1" index="11"> - confirms an exchange declaration - <doc> - This method confirms a Declare method and confirms the name of the - exchange, essential for automatically-named exchanges. - </doc> - <chassis name="client" implement="MUST"/> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="delete" synchronous="1" index="20"> - delete an exchange - <doc> - This method deletes an exchange. When an exchange is deleted all queue - bindings on the exchange are cancelled. - </doc> - <chassis name="server" implement="MUST"/> - <response name="delete-ok"/> - <field name="ticket" domain="access ticket"> - <rule implement="MUST"> - The client MUST provide a valid access ticket giving "active" - access rights to the exchange's access realm. - </rule> - </field> - <field name="exchange" domain="exchange name"> - <rule implement="MUST"> - <test>amq_exchange_11</test> - The exchange MUST exist. Attempting to delete a non-existing exchange - causes a channel exception. - </rule> - <assert check="notnull"/> - </field> - <field name="if unused" type="bit"> - delete only if unused - <doc> - If set, the server will only delete the exchange if it has no queue - bindings. If the exchange has queue bindings the server does not - delete it but raises a channel exception instead. - </doc> - <rule implement="SHOULD"> - <test>amq_exchange_12</test> - If set, the server SHOULD delete the exchange but only if it has - no queue bindings. - </rule> - <rule implement="SHOULD"> - <test>amq_exchange_13</test> - If set, the server SHOULD raise a channel exception if the exchange is in - use. - </rule> - </field> - - <field name = "nowait" type = "bit"> - do not send a reply method - <doc> - If set, the server will not respond to the method. The client should - not wait for a reply method. If the server could not complete the - method it will raise a channel or connection exception. - </doc> - </field> - - </method> - <method name="delete-ok" synchronous="1" index="21"> - confirm deletion of an exchange - <doc> - This method confirms the deletion of an exchange. - </doc> - <chassis name="client" implement="MUST"/> - </method> - </class> - <class name="queue" handler="channel" index="50"> - <!-- -====================================================== -== QUEUES -====================================================== ---> - work with queues - -<doc> - Queues store and forward messages. Queues can be configured in the server - or created at runtime. Queues must be attached to at least one exchange - in order to receive messages from publishers. -</doc> - <doc name="grammar"> - queue = C:DECLARE S:DECLARE-OK - / C:BIND S:BIND-OK - / C:PURGE S:PURGE-OK - / C:DELETE S:DELETE-OK -</doc> - <chassis name="server" implement="MUST"/> - <chassis name="client" implement="MUST"/> - <rule implement="MUST"> - <test>amq_queue_33</test> - A server MUST allow any content class to be sent to any queue, in any - mix, and queue and delivery these content classes independently. Note - that all methods that fetch content off queues are specific to a given - content class. -</rule> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="declare" synchronous="1" index="10"> - declare queue, create if needed - <doc> - This method creates or checks a queue. When creating a new queue - the client can specify various properties that control the durability - of the queue and its contents, and the level of sharing for the queue. - </doc> - <rule implement="MUST"> - <test>amq_queue_34</test> - The server MUST create a default binding for a newly-created queue - to the default exchange, which is an exchange of type 'direct'. - </rule> - <rule implement="SHOULD"> - <test>amq_queue_35</test> - The server SHOULD support a minimum of 256 queues per virtual host - and ideally, impose no limit except as defined by available resources. - </rule> - <chassis name="server" implement="MUST"/> - <response name="declare-ok"/> - <field name="ticket" domain="access ticket"> - <doc> - When a client defines a new queue, this belongs to the access realm - of the ticket used. All further work done with that queue must be - done with an access ticket for the same realm. - </doc> - <doc> - The client provides a valid access ticket giving "active" access - to the realm in which the queue exists or will be created, or - "passive" access if the if-exists flag is set. - </doc> - </field> - <field name="queue" domain="queue name"> - <rule implement="MAY"> - <test>amq_queue_10</test> - The queue name MAY be empty, in which case the server MUST create - a new queue with a unique generated name and return this to the - client in the Declare-Ok method. - </rule> - <rule implement="MUST"> - <test>amq_queue_32</test> - Queue names starting with "amq." are reserved for predeclared and - standardised server queues. If the queue name starts with "amq." - and the passive option is zero, the server MUST raise a connection - exception with reply code 403 (access refused). - </rule> - <assert check="regexp" value="^[a-zA-Z0-9-_.:]*$"/> - </field> - <field name="passive" type="bit"> - do not create queue - <doc> - If set, the server will not create the queue. The client can use - this to check whether a queue exists without modifying the server - state. - </doc> - <rule implement="MUST"> - <test>amq_queue_05</test> - If set, and the queue does not already exist, the server MUST - respond with a reply code 404 (not found) and raise a channel - exception. - </rule> - </field> - <field name="durable" type="bit"> - request a durable queue - <doc> - If set when creating a new queue, the queue will be marked as - durable. Durable queues remain active when a server restarts. - Non-durable queues (transient queues) are purged if/when a - server restarts. Note that durable queues do not necessarily - hold persistent messages, although it does not make sense to - send persistent messages to a transient queue. - </doc> - <rule implement="MUST"> - <test>amq_queue_03</test> - The server MUST recreate the durable queue after a restart. - </rule> - <rule implement="MUST"> - <test>amq_queue_36</test> - The server MUST support both durable and transient queues. - </rule> - <rule implement="MUST"> - <test>amq_queue_37</test> - The server MUST ignore the durable field if the queue already - exists. - </rule> - </field> - <field name="exclusive" type="bit"> - request an exclusive queue - <doc> - Exclusive queues may only be consumed from by the current connection. - Setting the 'exclusive' flag always implies 'auto-delete'. - </doc> - <rule implement="MUST"> - <test>amq_queue_38</test> - The server MUST support both exclusive (private) and non-exclusive - (shared) queues. - </rule> - <rule implement="MUST"> - <test>amq_queue_04</test> - The server MUST raise a channel exception if 'exclusive' is specified - and the queue already exists and is owned by a different connection. - </rule> - </field> - <field name="auto delete" type="bit"> - auto-delete queue when unused - <doc> - If set, the queue is deleted when all consumers have finished - using it. Last consumer can be cancelled either explicitly or because - its channel is closed. If there was no consumer ever on the queue, it - won't be deleted. - </doc> - <rule implement="SHOULD"> - <test>amq_queue_02</test> - The server SHOULD allow for a reasonable delay between the point - when it determines that a queue is not being used (or no longer - used), and the point when it deletes the queue. At the least it - must allow a client to create a queue and then create a consumer - to read from it, with a small but non-zero delay between these - two actions. The server should equally allow for clients that may - be disconnected prematurely, and wish to re-consume from the same - queue without losing messages. We would recommend a configurable - timeout, with a suitable default value being one minute. - </rule> - <rule implement="MUST"> - <test>amq_queue_31</test> - The server MUST ignore the auto-delete field if the queue already - exists. - </rule> - </field> - <field name = "nowait" type = "bit"> - do not send a reply method - <doc> - If set, the server will not respond to the method. The client should - not wait for a reply method. If the server could not complete the - method it will raise a channel or connection exception. - </doc> - </field> - - <field name="arguments" type="table"> - arguments for declaration - <doc> - A set of arguments for the declaration. The syntax and semantics - of these arguments depends on the server implementation. This - field is ignored if passive is 1. - </doc> - </field> - </method> - <method name="declare-ok" synchronous="1" index="11"> - confirms a queue definition - <doc> - This method confirms a Declare method and confirms the name of the - queue, essential for automatically-named queues. - </doc> - <chassis name="client" implement="MUST"/> - <field name="queue" domain="queue name"> - <doc> - Reports the name of the queue. If the server generated a queue - name, this field contains that name. - </doc> - <assert check="notnull"/> - </field> - <field name="message count" type="long"> - number of messages in queue - <doc> - Reports the number of messages in the queue, which will be zero - for newly-created queues. - </doc> - </field> - <field name="consumer count" type="long"> - number of consumers - <doc> - Reports the number of active consumers for the queue. Note that - consumers can suspend activity (Channel.Flow) in which case they - do not appear in this count. - </doc> - </field> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="bind" synchronous="1" index="20"> - bind queue to an exchange - <doc> - This method binds a queue to an exchange. Until a queue is - bound it will not receive any messages. In a classic messaging - model, store-and-forward queues are bound to a dest exchange - and subscription queues are bound to a dest_wild exchange. - </doc> - <rule implement="MUST"> - <test>amq_queue_25</test> - A server MUST allow ignore duplicate bindings - that is, two or - more bind methods for a specific queue, with identical arguments - - without treating these as an error. - </rule> - <rule implement="MUST"> - <test>amq_queue_39</test> - If a bind fails, the server MUST raise a connection exception. - </rule> - <rule implement="MUST"> - <test>amq_queue_12</test> - The server MUST NOT allow a durable queue to bind to a transient - exchange. If the client attempts this the server MUST raise a - channel exception. - </rule> - <rule implement="SHOULD"> - <test>amq_queue_13</test> - Bindings for durable queues are automatically durable and the - server SHOULD restore such bindings after a server restart. - </rule> - <rule implement="MUST"> - <test>amq_queue_17</test> - If the client attempts to an exchange that was declared as internal, - the server MUST raise a connection exception with reply code 530 - (not allowed). - </rule> - <rule implement="SHOULD"> - <test>amq_queue_40</test> - The server SHOULD support at least 4 bindings per queue, and - ideally, impose no limit except as defined by available resources. - </rule> - <chassis name="server" implement="MUST"/> - <response name="bind-ok"/> - <field name="ticket" domain="access ticket"> - <doc> - The client provides a valid access ticket giving "active" - access rights to the queue's access realm. - </doc> - </field> - - <field name = "queue" domain = "queue name"> - <doc> - Specifies the name of the queue to bind. If the queue name is - empty, refers to the current queue for the channel, which is - the last declared queue. - </doc> - <doc name = "rule"> - If the client did not previously declare a queue, and the queue - name in this method is empty, the server MUST raise a connection - exception with reply code 530 (not allowed). - </doc> - <doc name = "rule" test = "amq_queue_26"> - If the queue does not exist the server MUST raise a channel exception - with reply code 404 (not found). - </doc> - </field> - - <field name="exchange" domain="exchange name"> - The name of the exchange to bind to. - <rule implement="MUST"> - <test>amq_queue_14</test> - If the exchange does not exist the server MUST raise a channel - exception with reply code 404 (not found). - </rule> - </field> - <field name="routing key" type="shortstr"> - message routing key - <doc> - Specifies the routing key for the binding. The routing key is - used for routing messages depending on the exchange configuration. - Not all exchanges use a routing key - refer to the specific - exchange documentation. If the routing key is empty and the queue - name is empty, the routing key will be the current queue for the - channel, which is the last declared queue. - </doc> - </field> - - <field name = "nowait" type = "bit"> - do not send a reply method - <doc> - If set, the server will not respond to the method. The client should - not wait for a reply method. If the server could not complete the - method it will raise a channel or connection exception. - </doc> - </field> - - <field name="arguments" type="table"> - arguments for binding - <doc> - A set of arguments for the binding. The syntax and semantics of - these arguments depends on the exchange class. - </doc> - </field> - </method> - <method name="bind-ok" synchronous="1" index="21"> - confirm bind successful - <doc> - This method confirms that the bind was successful. - </doc> - <chassis name="client" implement="MUST"/> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="purge" synchronous="1" index="30"> - purge a queue - <doc> - This method removes all messages from a queue. It does not cancel - consumers. Purged messages are deleted without any formal "undo" - mechanism. - </doc> - <rule implement="MUST"> - <test>amq_queue_15</test> - A call to purge MUST result in an empty queue. - </rule> - <rule implement="MUST"> - <test>amq_queue_41</test> - On transacted channels the server MUST not purge messages that have - already been sent to a client but not yet acknowledged. - </rule> - <rule implement="MAY"> - <test>amq_queue_42</test> - The server MAY implement a purge queue or log that allows system - administrators to recover accidentally-purged messages. The server - SHOULD NOT keep purged messages in the same storage spaces as the - live messages since the volumes of purged messages may get very - large. - </rule> - <chassis name="server" implement="MUST"/> - <response name="purge-ok"/> - <field name="ticket" domain="access ticket"> - <doc> - The access ticket must be for the access realm that holds the - queue. - </doc> - <rule implement="MUST"> - The client MUST provide a valid access ticket giving "read" access - rights to the queue's access realm. Note that purging a queue is - equivalent to reading all messages and discarding them. - </rule> - </field> - <field name = "queue" domain = "queue name"> - <doc> - Specifies the name of the queue to purge. If the queue name is - empty, refers to the current queue for the channel, which is - the last declared queue. - </doc> - <doc name = "rule"> - If the client did not previously declare a queue, and the queue - name in this method is empty, the server MUST raise a connection - exception with reply code 530 (not allowed). - </doc> - <doc name = "rule" test = "amq_queue_16"> - The queue must exist. Attempting to purge a non-existing queue - causes a channel exception. - </doc> - </field> - - <field name = "nowait" type = "bit"> - do not send a reply method - <doc> - If set, the server will not respond to the method. The client should - not wait for a reply method. If the server could not complete the - method it will raise a channel or connection exception. - </doc> - </field> - </method> - <method name="purge-ok" synchronous="1" index="31"> - confirms a queue purge - <doc> - This method confirms the purge of a queue. - </doc> - <chassis name="client" implement="MUST"/> - <field name="message count" type="long"> - number of messages purged - <doc> - Reports the number of messages purged. - </doc> - </field> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="delete" synchronous="1" index="40"> - delete a queue - <doc> - This method deletes a queue. When a queue is deleted any pending - messages are sent to a dead-letter queue if this is defined in the - server configuration, and all consumers on the queue are cancelled. - </doc> - <rule implement="SHOULD"> - <test>amq_queue_43</test> - The server SHOULD use a dead-letter queue to hold messages that - were pending on a deleted queue, and MAY provide facilities for - a system administrator to move these messages back to an active - queue. - </rule> - <chassis name="server" implement="MUST"/> - <response name="delete-ok"/> - <field name="ticket" domain="access ticket"> - <doc> - The client provides a valid access ticket giving "active" - access rights to the queue's access realm. - </doc> - </field> - - <field name = "queue" domain = "queue name"> - <doc> - Specifies the name of the queue to delete. If the queue name is - empty, refers to the current queue for the channel, which is the - last declared queue. - </doc> - <doc name = "rule"> - If the client did not previously declare a queue, and the queue - name in this method is empty, the server MUST raise a connection - exception with reply code 530 (not allowed). - </doc> - <doc name = "rule" test = "amq_queue_21"> - The queue must exist. Attempting to delete a non-existing queue - causes a channel exception. - </doc> - </field> - - <field name="if unused" type="bit"> - delete only if unused - <doc> - If set, the server will only delete the queue if it has no - consumers. If the queue has consumers the server does does not - delete it but raises a channel exception instead. - </doc> - <rule implement="MUST"> - <test>amq_queue_29</test> - <test>amq_queue_30</test> - The server MUST respect the if-unused flag when deleting a queue. - </rule> - </field> - <field name="if empty" type="bit"> - delete only if empty - <test>amq_queue_27</test> - <doc> - If set, the server will only delete the queue if it has no - messages. If the queue is not empty the server raises a channel - exception. - </doc> - </field> - <field name = "nowait" type = "bit"> - do not send a reply method - <doc> - If set, the server will not respond to the method. The client should - not wait for a reply method. If the server could not complete the - method it will raise a channel or connection exception. - </doc> - </field> - </method> - - <method name="delete-ok" synchronous="1" index="41"> - confirm deletion of a queue - <doc> - This method confirms the deletion of a queue. - </doc> - <chassis name="client" implement="MUST"/> - <field name="message count" type="long"> - number of messages purged - <doc> - Reports the number of messages purged. - </doc> - </field> - </method> - </class> - <class name="basic" handler="channel" index="60"> - <!-- -====================================================== -== BASIC MIDDLEWARE -====================================================== ---> - work with basic content -<doc> - The Basic class provides methods that support an industry-standard - messaging model. -</doc> - -<doc name = "grammar"> - basic = C:QOS S:QOS-OK - / C:CONSUME S:CONSUME-OK - / C:CANCEL S:CANCEL-OK - / C:PUBLISH content - / S:RETURN content - / S:DELIVER content - / C:GET ( S:GET-OK content / S:GET-EMPTY ) - / C:ACK - / C:REJECT -</doc> - -<chassis name = "server" implement = "MUST" /> -<chassis name = "client" implement = "MAY" /> - -<doc name = "rule" test = "amq_basic_08"> - The server SHOULD respect the persistent property of basic messages - and SHOULD make a best-effort to hold persistent basic messages on a - reliable storage mechanism. -</doc> -<doc name = "rule" test = "amq_basic_09"> - The server MUST NOT discard a persistent basic message in case of a - queue overflow. The server MAY use the Channel.Flow method to slow - or stop a basic message publisher when necessary. -</doc> -<doc name = "rule" test = "amq_basic_10"> - The server MAY overflow non-persistent basic messages to persistent - storage and MAY discard or dead-letter non-persistent basic messages - on a priority basis if the queue size exceeds some configured limit. -</doc> -<doc name = "rule" test = "amq_basic_11"> - The server MUST implement at least 2 priority levels for basic - messages, where priorities 0-4 and 5-9 are treated as two distinct - levels. The server MAY implement up to 10 priority levels. -</doc> -<doc name = "rule" test = "amq_basic_12"> - The server MUST deliver messages of the same priority in order - irrespective of their individual persistence. -</doc> -<doc name = "rule" test = "amq_basic_13"> - The server MUST support both automatic and explicit acknowledgements - on Basic content. -</doc> - -<!-- These are the properties for a Basic content --> - -<field name = "content type" type = "shortstr"> - MIME content type -</field> -<field name = "content encoding" type = "shortstr"> - MIME content encoding -</field> -<field name = "headers" type = "table"> - Message header field table -</field> -<field name = "delivery mode" type = "octet"> - Non-persistent (1) or persistent (2) -</field> -<field name = "priority" type = "octet"> - The message priority, 0 to 9 -</field> -<field name = "correlation id" type = "shortstr"> - The application correlation identifier -</field> -<field name = "reply to" type = "shortstr"> - The destination to reply to -</field> -<field name = "expiration" type = "shortstr"> - Message expiration specification -</field> -<field name = "message id" type = "shortstr"> - The application message identifier -</field> -<field name = "timestamp" type = "timestamp"> - The message timestamp -</field> -<field name = "type" type = "shortstr"> - The message type name -</field> -<field name = "user id" type = "shortstr"> - The creating user id -</field> -<field name = "app id" type = "shortstr"> - The creating application id -</field> -<field name = "cluster id" type = "shortstr"> - Intra-cluster routing identifier -</field> - - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "qos" synchronous = "1" index = "10"> - specify quality of service - <doc> - This method requests a specific quality of service. The QoS can - be specified for the current channel or for all channels on the - connection. The particular properties and semantics of a qos method - always depend on the content class semantics. Though the qos method - could in principle apply to both peers, it is currently meaningful - only for the server. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "qos-ok" /> - - <field name = "prefetch size" type = "long"> - prefetch window in octets - <doc> - The client can request that messages be sent in advance so that - when the client finishes processing a message, the following - message is already held locally, rather than needing to be sent - down the channel. Prefetching gives a performance improvement. - This field specifies the prefetch window size in octets. The - server will send a message in advance if it is equal to or - smaller in size than the available prefetch size (and also falls - into other prefetch limits). May be set to zero, meaning "no - specific limit", although other prefetch limits may still apply. - The prefetch-size is ignored if the no-ack option is set. - </doc> - <doc name = "rule" test = "amq_basic_17"> - The server MUST ignore this setting when the client is not - processing any messages - i.e. the prefetch size does not limit - the transfer of single messages to a client, only the sending in - advance of more messages while the client still has one or more - unacknowledged messages. - </doc> - </field> - - <field name = "prefetch count" type = "short"> - prefetch window in messages - <doc> - Specifies a prefetch window in terms of whole messages. This - field may be used in combination with the prefetch-size field; - a message will only be sent in advance if both prefetch windows - (and those at the channel and connection level) allow it. - The prefetch-count is ignored if the no-ack option is set. - </doc> - <doc name = "rule" test = "amq_basic_18"> - The server MAY send less data in advance than allowed by the - client's specified prefetch windows but it MUST NOT send more. - </doc> - </field> - - <field name = "global" type = "bit"> - apply to entire connection - <doc> - By default the QoS settings apply to the current channel only. If - this field is set, they are applied to the entire connection. - </doc> - </field> -</method> - -<method name = "qos-ok" synchronous = "1" index = "11"> - confirm the requested qos - <doc> - This method tells the client that the requested QoS levels could - be handled by the server. The requested QoS applies to all active - consumers until a new QoS is defined. - </doc> - <chassis name = "client" implement = "MUST" /> -</method> - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "consume" synchronous = "1" index = "20"> - start a queue consumer - <doc> - This method asks the server to start a "consumer", which is a - transient request for messages from a specific queue. Consumers - last as long as the channel they were created on, or until the - client cancels them. - </doc> - <doc name = "rule" test = "amq_basic_01"> - The server SHOULD support at least 16 consumers per queue, unless - the queue was declared as private, and ideally, impose no limit - except as defined by available resources. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "consume-ok" /> - - <field name = "ticket" domain = "access ticket"> - <doc name = "rule"> - The client MUST provide a valid access ticket giving "read" access - rights to the realm for the queue. - </doc> - </field> - - <field name = "queue" domain = "queue name"> - <doc> - Specifies the name of the queue to consume from. If the queue name - is null, refers to the current queue for the channel, which is the - last declared queue. - </doc> - <doc name = "rule"> - If the client did not previously declare a queue, and the queue name - in this method is empty, the server MUST raise a connection exception - with reply code 530 (not allowed). - </doc> - </field> - - <field name = "consumer tag" domain = "consumer tag"> - <doc> - Specifies the identifier for the consumer. The consumer tag is - local to a connection, so two clients can use the same consumer - tags. If this field is empty the server will generate a unique - tag. - </doc> - <doc name = "rule" test = "todo"> - The tag MUST NOT refer to an existing consumer. If the client - attempts to create two consumers with the same non-empty tag - the server MUST raise a connection exception with reply code - 530 (not allowed). - </doc> - </field> - - <field name = "no local" domain = "no local" /> - - <field name = "no ack" domain = "no ack" /> - - <field name = "exclusive" type = "bit"> - request exclusive access - <doc> - Request exclusive consumer access, meaning only this consumer can - access the queue. - </doc> - <doc name = "rule" test = "amq_basic_02"> - If the server cannot grant exclusive access to the queue when asked, - - because there are other consumers active - it MUST raise a channel - exception with return code 403 (access refused). - </doc> - </field> - - <field name = "nowait" type = "bit"> - do not send a reply method - <doc> - If set, the server will not respond to the method. The client should - not wait for a reply method. If the server could not complete the - method it will raise a channel or connection exception. - </doc> - </field> -</method> - -<method name = "consume-ok" synchronous = "1" index = "21"> - confirm a new consumer - <doc> - The server provides the client with a consumer tag, which is used - by the client for methods called on the consumer at a later stage. - </doc> - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer tag" domain = "consumer tag"> - <doc> - Holds the consumer tag specified by the client or provided by - the server. - </doc> - </field> -</method> - - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "cancel" synchronous = "1" index = "30"> - end a queue consumer - <doc test = "amq_basic_04"> - This method cancels a consumer. This does not affect already - delivered messages, but it does mean the server will not send any - more messages for that consumer. The client may receive an - abitrary number of messages in between sending the cancel method - and receiving the cancel-ok reply. - </doc> - <doc name = "rule" test = "todo"> - If the queue no longer exists when the client sends a cancel command, - or the consumer has been cancelled for other reasons, this command - has no effect. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "cancel-ok" /> - - <field name = "consumer tag" domain = "consumer tag" /> - - <field name = "nowait" type = "bit"> - do not send a reply method - <doc> - If set, the server will not respond to the method. The client should - not wait for a reply method. If the server could not complete the - method it will raise a channel or connection exception. - </doc> - </field> -</method> - -<method name = "cancel-ok" synchronous = "1" index = "31"> - confirm a cancelled consumer - <doc> - This method confirms that the cancellation was completed. - </doc> - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer tag" domain = "consumer tag" /> -</method> - - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "publish" content = "1" index = "40"> - publish a message - <doc> - This method publishes a message to a specific exchange. The message - will be routed to queues as defined by the exchange configuration - and distributed to any active consumers when the transaction, if any, - is committed. - </doc> - <chassis name = "server" implement = "MUST" /> - - <field name = "ticket" domain = "access ticket"> - <doc name = "rule"> - The client MUST provide a valid access ticket giving "write" - access rights to the access realm for the exchange. - </doc> - </field> - - <field name = "exchange" domain = "exchange name"> - <doc> - Specifies the name of the exchange to publish to. The exchange - name can be empty, meaning the default exchange. If the exchange - name is specified, and that exchange does not exist, the server - will raise a channel exception. - </doc> - <doc name = "rule" test = "amq_basic_06"> - The server MUST accept a blank exchange name to mean the default - exchange. - </doc> - <doc name = "rule" test = "amq_basic_14"> - If the exchange was declared as an internal exchange, the server - MUST raise a channel exception with a reply code 403 (access - refused). - </doc> - <doc name = "rule" test = "amq_basic_15"> - The exchange MAY refuse basic content in which case it MUST raise - a channel exception with reply code 540 (not implemented). - </doc> - </field> - - <field name = "routing key" type = "shortstr"> - Message routing key - <doc> - Specifies the routing key for the message. The routing key is - used for routing messages depending on the exchange configuration. - </doc> - </field> - - <field name = "mandatory" type = "bit"> - indicate mandatory routing - <doc> - This flag tells the server how to react if the message cannot be - routed to a queue. If this flag is set, the server will return an - unroutable message with a Return method. If this flag is zero, the - server silently drops the message. - </doc> - <doc name = "rule" test = "amq_basic_07"> - The server SHOULD implement the mandatory flag. - </doc> - </field> - - <field name = "immediate" type = "bit"> - request immediate delivery - <doc> - This flag tells the server how to react if the message cannot be - routed to a queue consumer immediately. If this flag is set, the - server will return an undeliverable message with a Return method. - If this flag is zero, the server will queue the message, but with - no guarantee that it will ever be consumed. - </doc> - <doc name = "rule" test = "amq_basic_16"> - The server SHOULD implement the immediate flag. - </doc> - </field> -</method> - -<method name = "return" content = "1" index = "50"> - return a failed message - <doc> - This method returns an undeliverable message that was published - with the "immediate" flag set, or an unroutable message published - with the "mandatory" flag set. The reply code and text provide - information about the reason that the message was undeliverable. - </doc> - <chassis name = "client" implement = "MUST" /> - - <field name = "reply code" domain = "reply code" /> - <field name = "reply text" domain = "reply text" /> - - <field name = "exchange" domain = "exchange name"> - <doc> - Specifies the name of the exchange that the message was - originally published to. - </doc> - </field> - - <field name = "routing key" type = "shortstr"> - Message routing key - <doc> - Specifies the routing key name specified when the message was - published. - </doc> - </field> -</method> - - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "deliver" content = "1" index = "60"> - notify the client of a consumer message - <doc> - This method delivers a message to the client, via a consumer. In - the asynchronous message delivery model, the client starts a - consumer using the Consume method, then the server responds with - Deliver methods as and when messages arrive for that consumer. - </doc> - <doc name = "rule" test = "amq_basic_19"> - The server SHOULD track the number of times a message has been - delivered to clients and when a message is redelivered a certain - number of times - e.g. 5 times - without being acknowledged, the - server SHOULD consider the message to be unprocessable (possibly - causing client applications to abort), and move the message to a - dead letter queue. - </doc> - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer tag" domain = "consumer tag" /> - - <field name = "delivery tag" domain = "delivery tag" /> - - <field name = "redelivered" domain = "redelivered" /> - - <field name = "exchange" domain = "exchange name"> - <doc> - Specifies the name of the exchange that the message was - originally published to. - </doc> - </field> - - <field name = "routing key" type = "shortstr"> - Message routing key - <doc> - Specifies the routing key name specified when the message was - published. - </doc> - </field> -</method> - - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "get" synchronous = "1" index = "70"> - direct access to a queue - <doc> - This method provides a direct access to the messages in a queue - using a synchronous dialogue that is designed for specific types of - application where synchronous functionality is more important than - performance. - </doc> - <response name = "get-ok" /> - <response name = "get-empty" /> - <chassis name = "server" implement = "MUST" /> - - <field name = "ticket" domain = "access ticket"> - <doc name = "rule"> - The client MUST provide a valid access ticket giving "read" - access rights to the realm for the queue. - </doc> - </field> - - <field name = "queue" domain = "queue name"> - <doc> - Specifies the name of the queue to consume from. If the queue name - is null, refers to the current queue for the channel, which is the - last declared queue. - </doc> - <doc name = "rule"> - If the client did not previously declare a queue, and the queue name - in this method is empty, the server MUST raise a connection exception - with reply code 530 (not allowed). - </doc> - </field> - - <field name = "no ack" domain = "no ack" /> -</method> - -<method name = "get-ok" synchronous = "1" content = "1" index = "71"> - provide client with a message - <doc> - This method delivers a message to the client following a get - method. A message delivered by 'get-ok' must be acknowledged - unless the no-ack option was set in the get method. - </doc> - <chassis name = "client" implement = "MAY" /> - - <field name = "delivery tag" domain = "delivery tag" /> - - <field name = "redelivered" domain = "redelivered" /> - - <field name = "exchange" domain = "exchange name"> - <doc> - Specifies the name of the exchange that the message was originally - published to. If empty, the message was published to the default - exchange. - </doc> - </field> - - <field name = "routing key" type = "shortstr"> - Message routing key - <doc> - Specifies the routing key name specified when the message was - published. - </doc> - </field> - - <field name = "message count" type = "long" > - number of messages pending - <doc> - This field reports the number of messages pending on the queue, - excluding the message being delivered. Note that this figure is - indicative, not reliable, and can change arbitrarily as messages - are added to the queue and removed by other clients. - </doc> - </field> -</method> - - -<method name = "get-empty" synchronous = "1" index = "72"> - indicate no messages available - <doc> - This method tells the client that the queue has no messages - available for the client. - </doc> - <chassis name = "client" implement = "MAY" /> - - <field name = "cluster id" type = "shortstr"> - Cluster id - <doc> - For use by cluster applications, should not be used by - client applications. - </doc> - </field> -</method> - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "ack" index = "80"> - acknowledge one or more messages - <doc> - This method acknowledges one or more messages delivered via the - Deliver or Get-Ok methods. The client can ask to confirm a - single message or a set of messages up to and including a specific - message. - </doc> - <chassis name = "server" implement = "MUST" /> - <field name = "delivery tag" domain = "delivery tag" /> - - <field name = "multiple" type = "bit"> - acknowledge multiple messages - <doc> - If set to 1, the delivery tag is treated as "up to and including", - so that the client can acknowledge multiple messages with a single - method. If set to zero, the delivery tag refers to a single - message. If the multiple field is 1, and the delivery tag is zero, - tells the server to acknowledge all outstanding mesages. - </doc> - <doc name = "rule" test = "amq_basic_20"> - The server MUST validate that a non-zero delivery-tag refers to an - delivered message, and raise a channel exception if this is not the - case. - </doc> - </field> -</method> - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "reject" index = "90"> - reject an incoming message - <doc> - This method allows a client to reject a message. It can be used to - interrupt and cancel large incoming messages, or return untreatable - messages to their original queue. - </doc> - <doc name = "rule" test = "amq_basic_21"> - The server SHOULD be capable of accepting and process the Reject - method while sending message content with a Deliver or Get-Ok - method. I.e. the server should read and process incoming methods - while sending output frames. To cancel a partially-send content, - the server sends a content body frame of size 1 (i.e. with no data - except the frame-end octet). - </doc> - <doc name = "rule" test = "amq_basic_22"> - The server SHOULD interpret this method as meaning that the client - is unable to process the message at this time. - </doc> - <doc name = "rule"> - A client MUST NOT use this method as a means of selecting messages - to process. A rejected message MAY be discarded or dead-lettered, - not necessarily passed to another client. - </doc> - <chassis name = "server" implement = "MUST" /> - - <field name = "delivery tag" domain = "delivery tag" /> - - <field name = "requeue" type = "bit"> - requeue the message - <doc> - If this field is zero, the message will be discarded. If this bit - is 1, the server will attempt to requeue the message. - </doc> - <doc name = "rule" test = "amq_basic_23"> - The server MUST NOT deliver the message to the same client within - the context of the current channel. The recommended strategy is - to attempt to deliver the message to an alternative consumer, and - if that is not possible, to move the message to a dead-letter - queue. The server MAY use more sophisticated tracking to hold - the message on the queue and redeliver it to the same client at - a later stage. - </doc> - </field> -</method> - -<method name = "recover" index = "100"> - redeliver unacknowledged messages - <doc> - This method asks the broker to redeliver all unacknowledged messages on a - specified channel. Zero or more messages may be redelivered. This method - is only allowed on non-transacted channels. - </doc> - <chassis name = "server" implement = "MUST" /> - - <field name = "requeue" type = "bit"> - requeue the message - <doc> - If this field is zero, the message will be redelivered to the original - recipient. If this bit is 1, the server will attempt to requeue the - message, potentially then delivering it to an alternative subscriber. - </doc> - </field> - <doc name="rule"> - The server MUST set the redelivered flag on all messages that are resent. - </doc> - <doc name="rule"> - The server MUST raise a channel exception if this is called on a - transacted channel. - </doc> -</method> - -</class> - - - <class name="file" handler="channel" index="70"> - <!-- -====================================================== -== FILE TRANSFER -====================================================== ---> - work with file content -<doc> - The file class provides methods that support reliable file transfer. - File messages have a specific set of properties that are required for - interoperability with file transfer applications. File messages and - acknowledgements are subject to channel transactions. Note that the - file class does not provide message browsing methods; these are not - compatible with the staging model. Applications that need browsable - file transfer should use Basic content and the Basic class. -</doc> - -<doc name = "grammar"> - file = C:QOS S:QOS-OK - / C:CONSUME S:CONSUME-OK - / C:CANCEL S:CANCEL-OK - / C:OPEN S:OPEN-OK C:STAGE content - / S:OPEN C:OPEN-OK S:STAGE content - / C:PUBLISH - / S:DELIVER - / S:RETURN - / C:ACK - / C:REJECT -</doc> - -<chassis name = "server" implement = "MAY" /> -<chassis name = "client" implement = "MAY" /> - -<doc name = "rule"> - The server MUST make a best-effort to hold file messages on a - reliable storage mechanism. -</doc> -<doc name = "rule"> - The server MUST NOT discard a file message in case of a queue - overflow. The server MUST use the Channel.Flow method to slow or stop - a file message publisher when necessary. -</doc> -<doc name = "rule"> - The server MUST implement at least 2 priority levels for file - messages, where priorities 0-4 and 5-9 are treated as two distinct - levels. The server MAY implement up to 10 priority levels. -</doc> -<doc name = "rule"> - The server MUST support both automatic and explicit acknowledgements - on file content. -</doc> - -<!-- These are the properties for a File content --> - -<field name = "content type" type = "shortstr"> - MIME content type -</field> -<field name = "content encoding" type = "shortstr"> - MIME content encoding -</field> -<field name = "headers" type = "table"> - Message header field table -</field> -<field name = "priority" type = "octet"> - The message priority, 0 to 9 -</field> -<field name = "reply to" type = "shortstr"> - The destination to reply to -</field> -<field name = "message id" type = "shortstr"> - The application message identifier -</field> -<field name = "filename" type = "shortstr"> - The message filename -</field> -<field name = "timestamp" type = "timestamp"> - The message timestamp -</field> -<field name = "cluster id" type = "shortstr"> - Intra-cluster routing identifier -</field> - - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "qos" synchronous = "1" index = "10"> - specify quality of service - <doc> - This method requests a specific quality of service. The QoS can - be specified for the current channel or for all channels on the - connection. The particular properties and semantics of a qos method - always depend on the content class semantics. Though the qos method - could in principle apply to both peers, it is currently meaningful - only for the server. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "qos-ok" /> - - <field name = "prefetch size" type = "long"> - prefetch window in octets - <doc> - The client can request that messages be sent in advance so that - when the client finishes processing a message, the following - message is already held locally, rather than needing to be sent - down the channel. Prefetching gives a performance improvement. - This field specifies the prefetch window size in octets. May be - set to zero, meaning "no specific limit". Note that other - prefetch limits may still apply. The prefetch-size is ignored - if the no-ack option is set. - </doc> - </field> - - <field name = "prefetch count" type = "short"> - prefetch window in messages - <doc> - Specifies a prefetch window in terms of whole messages. This - is compatible with some file API implementations. This field - may be used in combination with the prefetch-size field; a - message will only be sent in advance if both prefetch windows - (and those at the channel and connection level) allow it. - The prefetch-count is ignored if the no-ack option is set. - </doc> - <doc name = "rule"> - The server MAY send less data in advance than allowed by the - client's specified prefetch windows but it MUST NOT send more. - </doc> - </field> - - <field name = "global" type = "bit"> - apply to entire connection - <doc> - By default the QoS settings apply to the current channel only. If - this field is set, they are applied to the entire connection. - </doc> - </field> -</method> - -<method name = "qos-ok" synchronous = "1" index = "11"> - confirm the requested qos - <doc> - This method tells the client that the requested QoS levels could - be handled by the server. The requested QoS applies to all active - consumers until a new QoS is defined. - </doc> - <chassis name = "client" implement = "MUST" /> -</method> - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "consume" synchronous = "1" index = "20"> - start a queue consumer - <doc> - This method asks the server to start a "consumer", which is a - transient request for messages from a specific queue. Consumers - last as long as the channel they were created on, or until the - client cancels them. - </doc> - <doc name = "rule"> - The server SHOULD support at least 16 consumers per queue, unless - the queue was declared as private, and ideally, impose no limit - except as defined by available resources. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "consume-ok" /> - - <field name = "ticket" domain = "access ticket"> - <doc name = "rule"> - The client MUST provide a valid access ticket giving "read" access - rights to the realm for the queue. - </doc> - </field> - - <field name = "queue" domain = "queue name"> - <doc> - Specifies the name of the queue to consume from. If the queue name - is null, refers to the current queue for the channel, which is the - last declared queue. - </doc> - <doc name = "rule"> - If the client did not previously declare a queue, and the queue name - in this method is empty, the server MUST raise a connection exception - with reply code 530 (not allowed). - </doc> - </field> - - <field name = "consumer tag" domain = "consumer tag"> - <doc> - Specifies the identifier for the consumer. The consumer tag is - local to a connection, so two clients can use the same consumer - tags. If this field is empty the server will generate a unique - tag. - </doc> - <doc name = "rule" test = "todo"> - The tag MUST NOT refer to an existing consumer. If the client - attempts to create two consumers with the same non-empty tag - the server MUST raise a connection exception with reply code - 530 (not allowed). - </doc> - </field> - - <field name = "no local" domain = "no local" /> - - <field name = "no ack" domain = "no ack" /> - - <field name = "exclusive" type = "bit"> - request exclusive access - <doc> - Request exclusive consumer access, meaning only this consumer can - access the queue. - </doc> - <doc name = "rule" test = "amq_file_00"> - If the server cannot grant exclusive access to the queue when asked, - - because there are other consumers active - it MUST raise a channel - exception with return code 405 (resource locked). - </doc> - </field> - - <field name = "nowait" type = "bit"> - do not send a reply method - <doc> - If set, the server will not respond to the method. The client should - not wait for a reply method. If the server could not complete the - method it will raise a channel or connection exception. - </doc> - </field> -</method> - -<method name = "consume-ok" synchronous = "1" index = "21"> - confirm a new consumer - <doc> - This method provides the client with a consumer tag which it MUST - use in methods that work with the consumer. - </doc> - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer tag" domain = "consumer tag"> - <doc> - Holds the consumer tag specified by the client or provided by - the server. - </doc> - </field> -</method> - - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "cancel" synchronous = "1" index = "30"> - end a queue consumer - <doc> - This method cancels a consumer. This does not affect already - delivered messages, but it does mean the server will not send any - more messages for that consumer. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "cancel-ok" /> - - <field name = "consumer tag" domain = "consumer tag" /> - - <field name = "nowait" type = "bit"> - do not send a reply method - <doc> - If set, the server will not respond to the method. The client should - not wait for a reply method. If the server could not complete the - method it will raise a channel or connection exception. - </doc> - </field> -</method> - -<method name = "cancel-ok" synchronous = "1" index = "31"> - confirm a cancelled consumer - <doc> - This method confirms that the cancellation was completed. - </doc> - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer tag" domain = "consumer tag" /> -</method> - - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "open" synchronous = "1" index = "40"> - request to start staging - <doc> - This method requests permission to start staging a message. Staging - means sending the message into a temporary area at the recipient end - and then delivering the message by referring to this temporary area. - Staging is how the protocol handles partial file transfers - if a - message is partially staged and the connection breaks, the next time - the sender starts to stage it, it can restart from where it left off. - </doc> - <response name = "open-ok" /> - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <field name = "identifier" type = "shortstr"> - staging identifier - <doc> - This is the staging identifier. This is an arbitrary string chosen - by the sender. For staging to work correctly the sender must use - the same staging identifier when staging the same message a second - time after recovery from a failure. A good choice for the staging - identifier would be the SHA1 hash of the message properties data - (including the original filename, revised time, etc.). - </doc> - </field> - - <field name = "content size" type = "longlong"> - message content size - <doc> - The size of the content in octets. The recipient may use this - information to allocate or check available space in advance, to - avoid "disk full" errors during staging of very large messages. - </doc> - <doc name = "rule"> - The sender MUST accurately fill the content-size field. - Zero-length content is permitted. - </doc> - </field> -</method> - -<method name = "open-ok" synchronous = "1" index = "41"> - confirm staging ready - <doc> - This method confirms that the recipient is ready to accept staged - data. If the message was already partially-staged at a previous - time the recipient will report the number of octets already staged. - </doc> - <response name = "stage" /> - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <field name = "staged size" type = "longlong"> - already staged amount - <doc> - The amount of previously-staged content in octets. For a new - message this will be zero. - </doc> - <doc name = "rule"> - The sender MUST start sending data from this octet offset in the - message, counting from zero. - </doc> - <doc name = "rule"> - The recipient MAY decide how long to hold partially-staged content - and MAY implement staging by always discarding partially-staged - content. However if it uses the file content type it MUST support - the staging methods. - </doc> - </field> -</method> - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "stage" content = "1" index = "50"> - stage message content - <doc> - This method stages the message, sending the message content to the - recipient from the octet offset specified in the Open-Ok method. - </doc> - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> -</method> - - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "publish" index = "60"> - publish a message - <doc> - This method publishes a staged file message to a specific exchange. - The file message will be routed to queues as defined by the exchange - configuration and distributed to any active consumers when the - transaction, if any, is committed. - </doc> - <chassis name = "server" implement = "MUST" /> - - <field name = "ticket" domain = "access ticket"> - <doc name = "rule"> - The client MUST provide a valid access ticket giving "write" - access rights to the access realm for the exchange. - </doc> - </field> - - <field name = "exchange" domain = "exchange name"> - <doc> - Specifies the name of the exchange to publish to. The exchange - name can be empty, meaning the default exchange. If the exchange - name is specified, and that exchange does not exist, the server - will raise a channel exception. - </doc> - <doc name = "rule"> - The server MUST accept a blank exchange name to mean the default - exchange. - </doc> - <doc name = "rule"> - If the exchange was declared as an internal exchange, the server - MUST respond with a reply code 403 (access refused) and raise a - channel exception. - </doc> - <doc name = "rule"> - The exchange MAY refuse file content in which case it MUST respond - with a reply code 540 (not implemented) and raise a channel - exception. - </doc> - </field> - - <field name = "routing key" type = "shortstr"> - Message routing key - <doc> - Specifies the routing key for the message. The routing key is - used for routing messages depending on the exchange configuration. - </doc> - </field> - - <field name = "mandatory" type = "bit"> - indicate mandatory routing - <doc> - This flag tells the server how to react if the message cannot be - routed to a queue. If this flag is set, the server will return an - unroutable message with a Return method. If this flag is zero, the - server silently drops the message. - </doc> - <doc name = "rule" test = "amq_file_00"> - The server SHOULD implement the mandatory flag. - </doc> - </field> - - <field name = "immediate" type = "bit"> - request immediate delivery - <doc> - This flag tells the server how to react if the message cannot be - routed to a queue consumer immediately. If this flag is set, the - server will return an undeliverable message with a Return method. - If this flag is zero, the server will queue the message, but with - no guarantee that it will ever be consumed. - </doc> - <doc name = "rule" test = "amq_file_00"> - The server SHOULD implement the immediate flag. - </doc> - </field> - - <field name = "identifier" type = "shortstr"> - staging identifier - <doc> - This is the staging identifier of the message to publish. The - message must have been staged. Note that a client can send the - Publish method asynchronously without waiting for staging to - finish. - </doc> - </field> -</method> - -<method name = "return" content = "1" index = "70"> - return a failed message - <doc> - This method returns an undeliverable message that was published - with the "immediate" flag set, or an unroutable message published - with the "mandatory" flag set. The reply code and text provide - information about the reason that the message was undeliverable. - </doc> - <chassis name = "client" implement = "MUST" /> - - <field name = "reply code" domain = "reply code" /> - <field name = "reply text" domain = "reply text" /> - - <field name = "exchange" domain = "exchange name"> - <doc> - Specifies the name of the exchange that the message was - originally published to. - </doc> - </field> - - <field name = "routing key" type = "shortstr"> - Message routing key - <doc> - Specifies the routing key name specified when the message was - published. - </doc> - </field> -</method> - - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "deliver" index = "80"> - notify the client of a consumer message - <doc> - This method delivers a staged file message to the client, via a - consumer. In the asynchronous message delivery model, the client - starts a consumer using the Consume method, then the server - responds with Deliver methods as and when messages arrive for - that consumer. - </doc> - <doc name = "rule"> - The server SHOULD track the number of times a message has been - delivered to clients and when a message is redelivered a certain - number of times - e.g. 5 times - without being acknowledged, the - server SHOULD consider the message to be unprocessable (possibly - causing client applications to abort), and move the message to a - dead letter queue. - </doc> - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer tag" domain = "consumer tag" /> - - <field name = "delivery tag" domain = "delivery tag" /> - - <field name = "redelivered" domain = "redelivered" /> - - <field name = "exchange" domain = "exchange name"> - <doc> - Specifies the name of the exchange that the message was originally - published to. - </doc> - </field> - - <field name = "routing key" type = "shortstr"> - Message routing key - <doc> - Specifies the routing key name specified when the message was - published. - </doc> - </field> - - <field name = "identifier" type = "shortstr"> - staging identifier - <doc> - This is the staging identifier of the message to deliver. The - message must have been staged. Note that a server can send the - Deliver method asynchronously without waiting for staging to - finish. - </doc> - </field> -</method> - - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "ack" index = "90"> - acknowledge one or more messages - <doc> - This method acknowledges one or more messages delivered via the - Deliver method. The client can ask to confirm a single message or - a set of messages up to and including a specific message. - </doc> - <chassis name = "server" implement = "MUST" /> - <field name = "delivery tag" domain = "delivery tag" /> - - <field name = "multiple" type = "bit"> - acknowledge multiple messages - <doc> - If set to 1, the delivery tag is treated as "up to and including", - so that the client can acknowledge multiple messages with a single - method. If set to zero, the delivery tag refers to a single - message. If the multiple field is 1, and the delivery tag is zero, - tells the server to acknowledge all outstanding mesages. - </doc> - <doc name = "rule"> - The server MUST validate that a non-zero delivery-tag refers to an - delivered message, and raise a channel exception if this is not the - case. - </doc> - </field> -</method> - - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "reject" index = "100"> - reject an incoming message - <doc> - This method allows a client to reject a message. It can be used to - return untreatable messages to their original queue. Note that file - content is staged before delivery, so the client will not use this - method to interrupt delivery of a large message. - </doc> - <doc name = "rule"> - The server SHOULD interpret this method as meaning that the client - is unable to process the message at this time. - </doc> - <doc name = "rule"> - A client MUST NOT use this method as a means of selecting messages - to process. A rejected message MAY be discarded or dead-lettered, - not necessarily passed to another client. - </doc> - <chassis name = "server" implement = "MUST" /> - - <field name = "delivery tag" domain = "delivery tag" /> - - <field name = "requeue" type = "bit"> - requeue the message - <doc> - If this field is zero, the message will be discarded. If this bit - is 1, the server will attempt to requeue the message. - </doc> - <doc name = "rule"> - The server MUST NOT deliver the message to the same client within - the context of the current channel. The recommended strategy is - to attempt to deliver the message to an alternative consumer, and - if that is not possible, to move the message to a dead-letter - queue. The server MAY use more sophisticated tracking to hold - the message on the queue and redeliver it to the same client at - a later stage. - </doc> - </field> -</method> - -</class> - - <class name="stream" handler="channel" index="80"> - <!-- -====================================================== -== STREAMING -====================================================== ---> - work with streaming content - -<doc> - The stream class provides methods that support multimedia streaming. - The stream class uses the following semantics: one message is one - packet of data; delivery is unacknowleged and unreliable; the consumer - can specify quality of service parameters that the server can try to - adhere to; lower-priority messages may be discarded in favour of high - priority messages. -</doc> - -<doc name = "grammar"> - stream = C:QOS S:QOS-OK - / C:CONSUME S:CONSUME-OK - / C:CANCEL S:CANCEL-OK - / C:PUBLISH content - / S:RETURN - / S:DELIVER content -</doc> - -<chassis name = "server" implement = "MAY" /> -<chassis name = "client" implement = "MAY" /> - -<doc name = "rule"> - The server SHOULD discard stream messages on a priority basis if - the queue size exceeds some configured limit. -</doc> -<doc name = "rule"> - The server MUST implement at least 2 priority levels for stream - messages, where priorities 0-4 and 5-9 are treated as two distinct - levels. The server MAY implement up to 10 priority levels. -</doc> -<doc name = "rule"> - The server MUST implement automatic acknowledgements on stream - content. That is, as soon as a message is delivered to a client - via a Deliver method, the server must remove it from the queue. -</doc> - - -<!-- These are the properties for a Stream content --> - -<field name = "content type" type = "shortstr"> - MIME content type -</field> -<field name = "content encoding" type = "shortstr"> - MIME content encoding -</field> -<field name = "headers" type = "table"> - Message header field table -</field> -<field name = "priority" type = "octet"> - The message priority, 0 to 9 -</field> -<field name = "timestamp" type = "timestamp"> - The message timestamp -</field> - - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "qos" synchronous = "1" index = "10"> - specify quality of service - <doc> - This method requests a specific quality of service. The QoS can - be specified for the current channel or for all channels on the - connection. The particular properties and semantics of a qos method - always depend on the content class semantics. Though the qos method - could in principle apply to both peers, it is currently meaningful - only for the server. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "qos-ok" /> - - <field name = "prefetch size" type = "long"> - prefetch window in octets - <doc> - The client can request that messages be sent in advance so that - when the client finishes processing a message, the following - message is already held locally, rather than needing to be sent - down the channel. Prefetching gives a performance improvement. - This field specifies the prefetch window size in octets. May be - set to zero, meaning "no specific limit". Note that other - prefetch limits may still apply. - </doc> - </field> - - <field name = "prefetch count" type = "short"> - prefetch window in messages - <doc> - Specifies a prefetch window in terms of whole messages. This - field may be used in combination with the prefetch-size field; - a message will only be sent in advance if both prefetch windows - (and those at the channel and connection level) allow it. - </doc> - </field> - - <field name = "consume rate" type = "long"> - transfer rate in octets/second - <doc> - Specifies a desired transfer rate in octets per second. This is - usually determined by the application that uses the streaming - data. A value of zero means "no limit", i.e. as rapidly as - possible. - </doc> - <doc name = "rule"> - The server MAY ignore the prefetch values and consume rates, - depending on the type of stream and the ability of the server - to queue and/or reply it. The server MAY drop low-priority - messages in favour of high-priority messages. - </doc> - </field> - - <field name = "global" type = "bit"> - apply to entire connection - <doc> - By default the QoS settings apply to the current channel only. If - this field is set, they are applied to the entire connection. - </doc> - </field> -</method> - -<method name = "qos-ok" synchronous = "1" index = "11"> - confirm the requested qos - <doc> - This method tells the client that the requested QoS levels could - be handled by the server. The requested QoS applies to all active - consumers until a new QoS is defined. - </doc> - <chassis name = "client" implement = "MUST" /> -</method> - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "consume" synchronous = "1" index = "20"> - start a queue consumer - <doc> - This method asks the server to start a "consumer", which is a - transient request for messages from a specific queue. Consumers - last as long as the channel they were created on, or until the - client cancels them. - </doc> - <doc name = "rule"> - The server SHOULD support at least 16 consumers per queue, unless - the queue was declared as private, and ideally, impose no limit - except as defined by available resources. - </doc> - <doc name = "rule"> - Streaming applications SHOULD use different channels to select - different streaming resolutions. AMQP makes no provision for - filtering and/or transforming streams except on the basis of - priority-based selective delivery of individual messages. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "consume-ok" /> - - <field name = "ticket" domain = "access ticket"> - <doc name = "rule"> - The client MUST provide a valid access ticket giving "read" access - rights to the realm for the queue. - </doc> - </field> - - <field name = "queue" domain = "queue name"> - <doc> - Specifies the name of the queue to consume from. If the queue name - is null, refers to the current queue for the channel, which is the - last declared queue. - </doc> - <doc name = "rule"> - If the client did not previously declare a queue, and the queue name - in this method is empty, the server MUST raise a connection exception - with reply code 530 (not allowed). - </doc> - </field> - - <field name = "consumer tag" domain = "consumer tag"> - <doc> - Specifies the identifier for the consumer. The consumer tag is - local to a connection, so two clients can use the same consumer - tags. If this field is empty the server will generate a unique - tag. - </doc> - <doc name = "rule" test = "todo"> - The tag MUST NOT refer to an existing consumer. If the client - attempts to create two consumers with the same non-empty tag - the server MUST raise a connection exception with reply code - 530 (not allowed). - </doc> - </field> - - <field name = "no local" domain = "no local" /> - - <field name = "exclusive" type = "bit"> - request exclusive access - <doc> - Request exclusive consumer access, meaning only this consumer can - access the queue. - </doc> - <doc name = "rule" test = "amq_file_00"> - If the server cannot grant exclusive access to the queue when asked, - - because there are other consumers active - it MUST raise a channel - exception with return code 405 (resource locked). - </doc> - </field> - - <field name = "nowait" type = "bit"> - do not send a reply method - <doc> - If set, the server will not respond to the method. The client should - not wait for a reply method. If the server could not complete the - method it will raise a channel or connection exception. - </doc> - </field> -</method> - - -<method name = "consume-ok" synchronous = "1" index = "21"> - confirm a new consumer - <doc> - This method provides the client with a consumer tag which it may - use in methods that work with the consumer. - </doc> - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer tag" domain = "consumer tag"> - <doc> - Holds the consumer tag specified by the client or provided by - the server. - </doc> - </field> -</method> - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "cancel" synchronous = "1" index = "30"> - end a queue consumer - <doc> - This method cancels a consumer. Since message delivery is - asynchronous the client may continue to receive messages for - a short while after canceling a consumer. It may process or - discard these as appropriate. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "cancel-ok" /> - - <field name = "consumer tag" domain = "consumer tag" /> - - <field name = "nowait" type = "bit"> - do not send a reply method - <doc> - If set, the server will not respond to the method. The client should - not wait for a reply method. If the server could not complete the - method it will raise a channel or connection exception. - </doc> - </field> -</method> - -<method name = "cancel-ok" synchronous = "1" index = "31"> - confirm a cancelled consumer - <doc> - This method confirms that the cancellation was completed. - </doc> - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer tag" domain = "consumer tag" /> -</method> - - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "publish" content = "1" index = "40"> - publish a message - <doc> - This method publishes a message to a specific exchange. The message - will be routed to queues as defined by the exchange configuration - and distributed to any active consumers as appropriate. - </doc> - <chassis name = "server" implement = "MUST" /> - - <field name = "ticket" domain = "access ticket"> - <doc name = "rule"> - The client MUST provide a valid access ticket giving "write" - access rights to the access realm for the exchange. - </doc> - </field> - - <field name = "exchange" domain = "exchange name"> - <doc> - Specifies the name of the exchange to publish to. The exchange - name can be empty, meaning the default exchange. If the exchange - name is specified, and that exchange does not exist, the server - will raise a channel exception. - </doc> - <doc name = "rule"> - The server MUST accept a blank exchange name to mean the default - exchange. - </doc> - <doc name = "rule"> - If the exchange was declared as an internal exchange, the server - MUST respond with a reply code 403 (access refused) and raise a - channel exception. - </doc> - <doc name = "rule"> - The exchange MAY refuse stream content in which case it MUST - respond with a reply code 540 (not implemented) and raise a - channel exception. - </doc> - </field> - - <field name = "routing key" type = "shortstr"> - Message routing key - <doc> - Specifies the routing key for the message. The routing key is - used for routing messages depending on the exchange configuration. - </doc> - </field> - - <field name = "mandatory" type = "bit"> - indicate mandatory routing - <doc> - This flag tells the server how to react if the message cannot be - routed to a queue. If this flag is set, the server will return an - unroutable message with a Return method. If this flag is zero, the - server silently drops the message. - </doc> - <doc name = "rule" test = "amq_stream_00"> - The server SHOULD implement the mandatory flag. - </doc> - </field> - - <field name = "immediate" type = "bit"> - request immediate delivery - <doc> - This flag tells the server how to react if the message cannot be - routed to a queue consumer immediately. If this flag is set, the - server will return an undeliverable message with a Return method. - If this flag is zero, the server will queue the message, but with - no guarantee that it will ever be consumed. - </doc> - <doc name = "rule" test = "amq_stream_00"> - The server SHOULD implement the immediate flag. - </doc> - </field> -</method> - -<method name = "return" content = "1" index = "50"> - return a failed message - <doc> - This method returns an undeliverable message that was published - with the "immediate" flag set, or an unroutable message published - with the "mandatory" flag set. The reply code and text provide - information about the reason that the message was undeliverable. - </doc> - <chassis name = "client" implement = "MUST" /> - - <field name = "reply code" domain = "reply code" /> - <field name = "reply text" domain = "reply text" /> - - <field name = "exchange" domain = "exchange name"> - <doc> - Specifies the name of the exchange that the message was - originally published to. - </doc> - </field> - - <field name = "routing key" type = "shortstr"> - Message routing key - <doc> - Specifies the routing key name specified when the message was - published. - </doc> - </field> -</method> - - -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - -<method name = "deliver" content = "1" index = "60"> - notify the client of a consumer message - <doc> - This method delivers a message to the client, via a consumer. In - the asynchronous message delivery model, the client starts a - consumer using the Consume method, then the server responds with - Deliver methods as and when messages arrive for that consumer. - </doc> - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer tag" domain = "consumer tag" /> - - <field name = "delivery tag" domain = "delivery tag" /> - - <field name = "exchange" domain = "exchange name"> - <doc> - Specifies the name of the exchange that the message was originally - published to. - </doc> - </field> - - <field name = "queue" domain = "queue name"> - <doc> - Specifies the name of the queue that the message came from. Note - that a single channel can start many consumers on different - queues. - </doc> - <assert check = "notnull" /> - </field> -</method> - </class> - - <class name="tx" handler="channel" index="90"> - <!-- -====================================================== -== TRANSACTIONS -====================================================== ---> - work with standard transactions - -<doc> - Standard transactions provide so-called "1.5 phase commit". We can - ensure that work is never lost, but there is a chance of confirmations - being lost, so that messages may be resent. Applications that use - standard transactions must be able to detect and ignore duplicate - messages. -</doc> - <rule implement="SHOULD"> - An client using standard transactions SHOULD be able to track all - messages received within a reasonable period, and thus detect and - reject duplicates of the same message. It SHOULD NOT pass these to - the application layer. -</rule> - <doc name="grammar"> - tx = C:SELECT S:SELECT-OK - / C:COMMIT S:COMMIT-OK - / C:ROLLBACK S:ROLLBACK-OK -</doc> - <chassis name="server" implement="SHOULD"/> - <chassis name="client" implement="MAY"/> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="select" synchronous="1" index="10"> -select standard transaction mode - <doc> - This method sets the channel to use standard transactions. The - client must use this method at least once on a channel before - using the Commit or Rollback methods. - </doc> - <chassis name="server" implement="MUST"/> - <response name="select-ok"/> - </method> - <method name="select-ok" synchronous="1" index="11"> -confirm transaction mode - <doc> - This method confirms to the client that the channel was successfully - set to use standard transactions. - </doc> - <chassis name="client" implement="MUST"/> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="commit" synchronous="1" index="20"> -commit the current transaction - <doc> - This method commits all messages published and acknowledged in - the current transaction. A new transaction starts immediately - after a commit. - </doc> - <chassis name="server" implement="MUST"/> - <response name="commit-ok"/> - </method> - <method name="commit-ok" synchronous="1" index="21"> -confirm a successful commit - <doc> - This method confirms to the client that the commit succeeded. - Note that if a commit fails, the server raises a channel exception. - </doc> - <chassis name="client" implement="MUST"/> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="rollback" synchronous="1" index="30"> -abandon the current transaction - <doc> - This method abandons all messages published and acknowledged in - the current transaction. A new transaction starts immediately - after a rollback. - </doc> - <chassis name="server" implement="MUST"/> - <response name="rollback-ok"/> - </method> - <method name="rollback-ok" synchronous="1" index="31"> -confirm a successful rollback - <doc> - This method confirms to the client that the rollback succeeded. - Note that if an rollback fails, the server raises a channel exception. - </doc> - <chassis name="client" implement="MUST"/> - </method> - </class> - <class name="dtx" handler="channel" index="100"> - <!-- -====================================================== -== DISTRIBUTED TRANSACTIONS -====================================================== ---> - work with distributed transactions - -<doc> - Distributed transactions provide so-called "2-phase commit". The - AMQP distributed transaction model supports the X-Open XA - architecture and other distributed transaction implementations. - The Dtx class assumes that the server has a private communications - channel (not AMQP) to a distributed transaction coordinator. -</doc> - <doc name="grammar"> - dtx = C:SELECT S:SELECT-OK - C:START S:START-OK -</doc> - <chassis name="server" implement="MAY"/> - <chassis name="client" implement="MAY"/> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="select" synchronous="1" index="10"> -select standard transaction mode - <doc> - This method sets the channel to use distributed transactions. The - client must use this method at least once on a channel before - using the Start method. - </doc> - <chassis name="server" implement="MUST"/> - <response name="select-ok"/> - </method> - <method name="select-ok" synchronous="1" index="11"> -confirm transaction mode - <doc> - This method confirms to the client that the channel was successfully - set to use distributed transactions. - </doc> - <chassis name="client" implement="MUST"/> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="start" synchronous="1" index="20"> - start a new distributed transaction - <doc> - This method starts a new distributed transaction. This must be - the first method on a new channel that uses the distributed - transaction mode, before any methods that publish or consume - messages. - </doc> - <chassis name="server" implement="MAY"/> - <response name="start-ok"/> - <field name="dtx identifier" type="shortstr"> - transaction identifier - <doc> - The distributed transaction key. This identifies the transaction - so that the AMQP server can coordinate with the distributed - transaction coordinator. - </doc> - <assert check="notnull"/> - </field> - </method> - <method name="start-ok" synchronous="1" index="21"> - confirm the start of a new distributed transaction - <doc> - This method confirms to the client that the transaction started. - Note that if a start fails, the server raises a channel exception. - </doc> - <chassis name="client" implement="MUST"/> - </method> - </class> - <class name="tunnel" handler="tunnel" index="110"> - <!-- -====================================================== -== TUNNEL -====================================================== ---> - methods for protocol tunneling. - -<doc> - The tunnel methods are used to send blocks of binary data - which - can be serialised AMQP methods or other protocol frames - between - AMQP peers. -</doc> - <doc name="grammar"> - tunnel = C:REQUEST - / S:REQUEST -</doc> - <chassis name="server" implement="MAY"/> - <chassis name="client" implement="MAY"/> - <field name="headers" type="table"> - Message header field table -</field> - <field name="proxy name" type="shortstr"> - The identity of the tunnelling proxy -</field> - <field name="data name" type="shortstr"> - The name or type of the message being tunnelled -</field> - <field name="durable" type="octet"> - The message durability indicator -</field> - <field name="broadcast" type="octet"> - The message broadcast mode -</field> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="request" content="1" index="10"> - sends a tunnelled method - <doc> - This method tunnels a block of binary data, which can be an - encoded AMQP method or other data. The binary data is sent - as the content for the Tunnel.Request method. - </doc> - <chassis name="server" implement="MUST"/> - <field name="meta data" type="table"> - meta data for the tunnelled block - <doc> - This field table holds arbitrary meta-data that the sender needs - to pass to the recipient. - </doc> - </field> - </method> - </class> - <class name="test" handler="channel" index="120"> - <!-- -====================================================== -== TEST - CHECK FUNCTIONAL CAPABILITIES OF AN IMPLEMENTATION -====================================================== ---> - test functional primitives of the implementation - -<doc> - The test class provides methods for a peer to test the basic - operational correctness of another peer. The test methods are - intended to ensure that all peers respect at least the basic - elements of the protocol, such as frame and content organisation - and field types. We assume that a specially-designed peer, a - "monitor client" would perform such tests. -</doc> - <doc name="grammar"> - test = C:INTEGER S:INTEGER-OK - / S:INTEGER C:INTEGER-OK - / C:STRING S:STRING-OK - / S:STRING C:STRING-OK - / C:TABLE S:TABLE-OK - / S:TABLE C:TABLE-OK - / C:CONTENT S:CONTENT-OK - / S:CONTENT C:CONTENT-OK -</doc> - <chassis name="server" implement="MUST"/> - <chassis name="client" implement="SHOULD"/> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="integer" synchronous="1" index="10"> - test integer handling - <doc> - This method tests the peer's capability to correctly marshal integer - data. - </doc> - <chassis name="client" implement="MUST"/> - <chassis name="server" implement="MUST"/> - <response name="integer-ok"/> - <field name="integer 1" type="octet"> - octet test value - <doc> - An octet integer test value. - </doc> - </field> - <field name="integer 2" type="short"> - short test value - <doc> - A short integer test value. - </doc> - </field> - <field name="integer 3" type="long"> - long test value - <doc> - A long integer test value. - </doc> - </field> - <field name="integer 4" type="longlong"> - long-long test value - <doc> - A long long integer test value. - </doc> - </field> - <field name="operation" type="octet"> - operation to test - <doc> - The client must execute this operation on the provided integer - test fields and return the result. - </doc> - <assert check="enum"> - <value name="add">return sum of test values</value> - <value name="min">return lowest of test values</value> - <value name="max">return highest of test values</value> - </assert> - </field> - </method> - <method name="integer-ok" synchronous="1" index="11"> - report integer test result - <doc> - This method reports the result of an Integer method. - </doc> - <chassis name="client" implement="MUST"/> - <chassis name="server" implement="MUST"/> - <field name="result" type="longlong"> - result value - <doc> - The result of the tested operation. - </doc> - </field> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="string" synchronous="1" index="20"> - test string handling - <doc> - This method tests the peer's capability to correctly marshal string - data. - </doc> - <chassis name="client" implement="MUST"/> - <chassis name="server" implement="MUST"/> - <response name="string-ok"/> - <field name="string 1" type="shortstr"> - short string test value - <doc> - An short string test value. - </doc> - </field> - <field name="string 2" type="longstr"> - long string test value - <doc> - A long string test value. - </doc> - </field> - <field name="operation" type="octet"> - operation to test - <doc> - The client must execute this operation on the provided string - test fields and return the result. - </doc> - <assert check="enum"> - <value name="add">return concatentation of test strings</value> - <value name="min">return shortest of test strings</value> - <value name="max">return longest of test strings</value> - </assert> - </field> - </method> - <method name="string-ok" synchronous="1" index="21"> - report string test result - <doc> - This method reports the result of a String method. - </doc> - <chassis name="client" implement="MUST"/> - <chassis name="server" implement="MUST"/> - <field name="result" type="longstr"> - result value - <doc> - The result of the tested operation. - </doc> - </field> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="table" synchronous="1" index="30"> - test field table handling - <doc> - This method tests the peer's capability to correctly marshal field - table data. - </doc> - <chassis name="client" implement="MUST"/> - <chassis name="server" implement="MUST"/> - <response name="table-ok"/> - <field name="table" type="table"> - field table of test values - <doc> - A field table of test values. - </doc> - </field> - <field name="integer op" type="octet"> - operation to test on integers - <doc> - The client must execute this operation on the provided field - table integer values and return the result. - </doc> - <assert check="enum"> - <value name="add">return sum of numeric field values</value> - <value name="min">return min of numeric field values</value> - <value name="max">return max of numeric field values</value> - </assert> - </field> - <field name="string op" type="octet"> - operation to test on strings - <doc> - The client must execute this operation on the provided field - table string values and return the result. - </doc> - <assert check="enum"> - <value name="add">return concatenation of string field values</value> - <value name="min">return shortest of string field values</value> - <value name="max">return longest of string field values</value> - </assert> - </field> - </method> - <method name="table-ok" synchronous="1" index="31"> - report table test result - <doc> - This method reports the result of a Table method. - </doc> - <chassis name="client" implement="MUST"/> - <chassis name="server" implement="MUST"/> - <field name="integer result" type="longlong"> - integer result value - <doc> - The result of the tested integer operation. - </doc> - </field> - <field name="string result" type="longstr"> - string result value - <doc> - The result of the tested string operation. - </doc> - </field> - </method> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <method name="content" synchronous="1" content="1" index="40"> - test content handling - <doc> - This method tests the peer's capability to correctly marshal content. - </doc> - <chassis name="client" implement="MUST"/> - <chassis name="server" implement="MUST"/> - <response name="content-ok"/> - </method> - <method name="content-ok" synchronous="1" content="1" index="41"> - report content test result - <doc> - This method reports the result of a Content method. It contains the - content checksum and echoes the original content as provided. - </doc> - <chassis name="client" implement="MUST"/> - <chassis name="server" implement="MUST"/> - <field name="content checksum" type="long"> - content hash - <doc> - The 32-bit checksum of the content, calculated by adding the - content into a 32-bit accumulator. - </doc> - </field> - </method> - </class> -</amqp> diff --git a/gentools/xml-src/amqp-0.9.test.xml b/gentools/xml-src/amqp-0.9.test.xml deleted file mode 100644 index e12e9c787a..0000000000 --- a/gentools/xml-src/amqp-0.9.test.xml +++ /dev/null @@ -1,4282 +0,0 @@ -<?xml version = "1.0"?> - -<!-- - EDITORS: (PH) Pieter Hintjens <ph@imatix.com> - (KvdR) Kim van der Riet <kim.vdriet@redhat.com> - - These editors have been assigned by the AMQP working group. - Please do not edit/commit this file without consulting with - one of the above editors. - ======================================================== - - TODOs - - see TODO comments in the text ---> - -<!-- - Copyright Notice - ================ - (c) Copyright JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., - iMatix Corporation, IONA\ufffd Technologies, Red Hat, Inc., - TWIST Process Innovations, and 29West Inc. 2006. All rights reserved. - - License - ======= - JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., iMatix - Corporation, IONA\ufffd Technologies, Red Hat, Inc., TWIST Process Innovations, and - 29West Inc. (collectively, the "Authors") each hereby grants to you a worldwide, - perpetual, royalty-free, nontransferable, nonexclusive license to - (i) copy, display, and implement the Advanced Messaging Queue Protocol - ("AMQP") Specification and (ii) the Licensed Claims that are held by - the Authors, all for the purpose of implementing the Advanced Messaging - Queue Protocol Specification. Your license and any rights under this - Agreement will terminate immediately without notice from - any Author if you bring any claim, suit, demand, or action related to - the Advanced Messaging Queue Protocol Specification against any Author. - Upon termination, you shall destroy all copies of the Advanced Messaging - Queue Protocol Specification in your possession or control. - - As used hereunder, "Licensed Claims" means those claims of a patent or - patent application, throughout the world, excluding design patents and - design registrations, owned or controlled, or that can be sublicensed - without fee and in compliance with the requirements of this - Agreement, by an Author or its affiliates now or at any - future time and which would necessarily be infringed by implementation - of the Advanced Messaging Queue Protocol Specification. A claim is - necessarily infringed hereunder only when it is not possible to avoid - infringing it because there is no plausible non-infringing alternative - for implementing the required portions of the Advanced Messaging Queue - Protocol Specification. Notwithstanding the foregoing, Licensed Claims - shall not include any claims other than as set forth above even if - contained in the same patent as Licensed Claims; or that read solely - on any implementations of any portion of the Advanced Messaging Queue - Protocol Specification that are not required by the Advanced Messaging - Queue Protocol Specification, or that, if licensed, would require a - payment of royalties by the licensor to unaffiliated third parties. - Moreover, Licensed Claims shall not include (i) any enabling technologies - that may be necessary to make or use any Licensed Product but are not - themselves expressly set forth in the Advanced Messaging Queue Protocol - Specification (e.g., semiconductor manufacturing technology, compiler - technology, object oriented technology, networking technology, operating - system technology, and the like); or (ii) the implementation of other - published standards developed elsewhere and merely referred to in the - body of the Advanced Messaging Queue Protocol Specification, or - (iii) any Licensed Product and any combinations thereof the purpose or - function of which is not required for compliance with the Advanced - Messaging Queue Protocol Specification. For purposes of this definition, - the Advanced Messaging Queue Protocol Specification shall be deemed to - include both architectural and interconnection requirements essential - for interoperability and may also include supporting source code artifacts - where such architectural, interconnection requirements and source code - artifacts are expressly identified as being required or documentation to - achieve compliance with the Advanced Messaging Queue Protocol Specification. - - As used hereunder, "Licensed Products" means only those specific portions - of products (hardware, software or combinations thereof) that implement - and are compliant with all relevant portions of the Advanced Messaging - Queue Protocol Specification. - - The following disclaimers, which you hereby also acknowledge as to any - use you may make of the Advanced Messaging Queue Protocol Specification: - - THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION IS PROVIDED "AS IS," - AND THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR - IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE - CONTENTS OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION ARE - SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF THE ADVANCED - MESSAGING QUEUE PROTOCOL SPECIFICATION WILL NOT INFRINGE ANY THIRD PARTY - PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. - - THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, - INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY - USE, IMPLEMENTATION OR DISTRIBUTION OF THE ADVANCED MESSAGING QUEUE - PROTOCOL SPECIFICATION. - - The name and trademarks of the Authors may NOT be used in any manner, - including advertising or publicity pertaining to the Advanced Messaging - Queue Protocol Specification or its contents without specific, written - prior permission. Title to copyright in the Advanced Messaging Queue - Protocol Specification will at all times remain with the Authors. - - No other rights are granted by implication, estoppel or otherwise. - - Upon termination of your license or rights under this Agreement, you - shall destroy all copies of the Advanced Messaging Queue Protocol - Specification in your possession or control. - - Trademarks - ========== - "JPMorgan", "JPMorgan Chase", "Chase", the JPMorgan Chase logo and the - Octagon Symbol are trademarks of JPMorgan Chase & Co. - - IMATIX and the iMatix logo are trademarks of iMatix Corporation sprl. - - IONA, IONA Technologies, and the IONA logos are trademarks of IONA - Technologies PLC and/or its subsidiaries. - - LINUX is a trademark of Linus Torvalds. RED HAT and JBOSS are registered - trademarks of Red Hat, Inc. in the US and other countries. - - Java, all Java-based trademarks and OpenOffice.org are trademarks of - Sun Microsystems, Inc. in the United States, other countries, or both. - - Other company, product, or service names may be trademarks or service - marks of others. - - Links to full AMQP specification: - ================================= - http://www.envoytech.org/spec/amq/ - http://www.iona.com/opensource/amqp/ - http://www.redhat.com/solutions/specifications/amqp/ - http://www.twiststandards.org/tiki-index.php?page=AMQ - http://www.imatix.com/amqp ---> - -<!-- - <!DOCTYPE amqp SYSTEM "amqp.dtd"> ---> - -<!-- XML Notes - - We use entities to indicate repetition; attributes to indicate properties. - - We use the 'name' attribute as an identifier, usually within the context - of the surrounding entities. - - We use spaces to seperate words in names, so that we can print names in - their natural form depending on the context - underlines for source code, - hyphens for written text, etc. - - We do not enforce any particular validation mechanism but we support all - mechanisms. The protocol definition conforms to a formal grammar that is - published seperately in several technologies. - - --> - -<amqp major = "0" minor = "9" port = "5672" comment = "AMQ Protocol"> - <!-- - ====================================================== - == CONSTANTS - ====================================================== - --> - <!-- Frame types --> - <constant name = "frame-method" value = "1" /> - <constant name = "frame-header" value = "2" /> - <constant name = "frame-body" value = "3" /> - <constant name = "frame-oob-method" value = "4" /> - <constant name = "frame-oob-header" value = "5" /> - <constant name = "frame-oob-body" value = "6" /> - <constant name = "frame-trace" value = "7" /> - <constant name = "frame-heartbeat" value = "8" /> - - <!-- Protocol constants --> - <constant name = "frame-min-size" value = "4096" /> - <constant name = "frame-end" value = "206" /> - - <!-- Reply codes --> - <constant name = "reply-success" value = "200"> - <doc> - Indicates that the method completed successfully. This reply code is - reserved for future use - the current protocol design does not use positive - confirmation and reply codes are sent only in case of an error. - </doc> - </constant> - - <constant name = "not-delivered" value = "310" class = "soft-error"> - <doc> - The client asked for a specific message that is no longer available. - The message was delivered to another client, or was purged from the queue - for some other reason. - </doc> - </constant> - - <constant name = "content-too-large" value = "311" class = "soft-error"> - <doc> - The client attempted to transfer content larger than the server could accept - at the present time. The client may retry at a later time. - </doc> - </constant> - - <constant name = "connection-forced" value = "320" class = "hard-error"> - <doc> - An operator intervened to close the connection for some reason. The client - may retry at some later date. - </doc> - </constant> - - <constant name = "invalid-path" value = "402" class = "hard-error"> - <doc> - The client tried to work with an unknown virtual host. - </doc> - </constant> - - <constant name = "access-refused" value = "403" class = "soft-error"> - <doc> - The client attempted to work with a server entity to which it has no - access due to security settings. - </doc> - </constant> - - <constant name = "not-found" value = "404" class = "soft-error"> - <doc>The client attempted to work with a server entity that does not exist.</doc> - </constant> - - <constant name = "resource-locked" value = "405" class = "soft-error"> - <doc> - The client attempted to work with a server entity to which it has no - access because another client is working with it. - </doc> - </constant> - - <constant name = "precondition-failed" value = "406" class = "soft-error"> - <doc> - The client requested a method that was not allowed because some precondition - failed. - </doc> - </constant> - - <constant name = "frame-error" value = "501" class = "hard-error"> - <doc> - The client sent a malformed frame that the server could not decode. This - strongly implies a programming error in the client. - </doc> - </constant> - - <constant name = "syntax-error" value = "502" class = "hard-error"> - <doc> - The client sent a frame that contained illegal values for one or more - fields. This strongly implies a programming error in the client. - </doc> - </constant> - - <constant name = "command-invalid" value = "503" class = "hard-error"> - <doc> - The client sent an invalid sequence of frames, attempting to perform an - operation that was considered invalid by the server. This usually implies - a programming error in the client. - </doc> - </constant> - - <constant name = "channel-error" value = "504" class = "hard-error"> - <doc> - The client attempted to work with a channel that had not been correctly - opened. This most likely indicates a fault in the client layer. - </doc> - </constant> - - <constant name = "resource-error" value = "506" class = "hard-error"> - <doc> - The server could not complete the method because it lacked sufficient - resources. This may be due to the client creating too many of some type - of entity. - </doc> - </constant> - - <constant name = "not-allowed" value = "530" class = "hard-error"> - <doc> - The client tried to work with some entity in a manner that is prohibited - by the server, due to security settings or by some other criteria. - </doc> - </constant> - - <constant name = "not-implemented" value = "540" class = "hard-error"> - <doc> - The client tried to use functionality that is not implemented in the - server. - </doc> - </constant> - - <constant name = "internal-error" value = "541" class = "hard-error"> - <doc> - The server could not complete the method because of an internal error. - The server may require intervention by an operator in order to resume - normal operations. - </doc> - </constant> - - <constant name = "test-str2" value = "1.2.3.3"/> - - <!-- - ====================================================== - == DOMAIN TYPES - ====================================================== - --> - - <domain name = "access-ticket" type = "short" label = "access ticket granted by server"> - <doc> - An access ticket granted by the server for a certain set of access rights - within a specific realm. Access tickets are valid within the channel where - they were created, and expire when the channel closes. - </doc> - <assert check = "ne" value = "0" /> - </domain> - - <domain name = "class-id" type = "short" /> - - <domain name = "consumer-tag" type = "shortstr" label = "consumer tag"> - <doc> - Identifier for the consumer, valid within the current connection. - </doc> - </domain> - - <domain name = "delivery-tag" type = "longlong" label = "server-assigned delivery tag"> - <doc> - The server-assigned and channel-specific delivery tag - </doc> - <rule name = "channel-local"> - <doc> - The delivery tag is valid only within the channel from which the message was - received. I.e. a client MUST NOT receive a message on one channel and then - acknowledge it on another. - </doc> - </rule> - <rule name = "non-zero"> - <doc> - The server MUST NOT use a zero value for delivery tags. Zero is reserved - for client use, meaning "all messages so far received". - </doc> - </rule> - </domain> - - <domain name = "exchange-name" type = "shortstr" label = "exchange name"> - <doc> - The exchange name is a client-selected string that identifies the exchange for publish - methods. Exchange names may consist of any mixture of digits, letters, and underscores. - Exchange names are scoped by the virtual host. - </doc> - <assert check = "length" value = "127" /> - </domain> - - <domain name = "known-hosts" type = "shortstr" label = "list of known hosts"> - <doc> - Specifies the list of equivalent or alternative hosts that the server knows about, - which will normally include the current server itself. Clients can cache this - information and use it when reconnecting to a server after a failure. This field - may be empty. - </doc> - </domain> - - <domain name = "method-id" type = "short" /> - - <domain name = "no-ack" type = "bit" label = "no acknowledgement needed"> - <doc> - If this field is set the server does not expect acknowledgments for - messages. That is, when a message is delivered to the client the server - automatically and silently acknowledges it on behalf of the client. This - functionality increases performance but at the cost of reliability. - Messages can get lost if a client dies before it can deliver them to the - application. - </doc> - </domain> - - <domain name = "no-local" type = "bit" label = "do not deliver own messages"> - <doc> - If the no-local field is set the server will not send messages to the client that - published them. - </doc> - </domain> - - <domain name = "path" type = "shortstr"> - <doc> - Must start with a slash "/" and continue with path names separated by slashes. A path - name consists of any combination of at least one of [A-Za-z0-9] plus zero or more of - [.-_+!=:]. - </doc> - - <assert check = "notnull" /> - <assert check = "syntax" rule = "path" /> - <assert check = "length" value = "127" /> - </domain> - - <domain name = "peer-properties" type = "table"> - <doc> - This string provides a set of peer properties, used for identification, debugging, and - general information. - </doc> - </domain> - - <domain name = "queue-name" type = "shortstr" label = "queue name"> - <doc> - The queue name identifies the queue within the vhost. Queue names may consist of any - mixture of digits, letters, and underscores. - </doc> - <assert check = "length" value = "127" /> - </domain> - - <domain name = "redelivered" type = "bit" label = "message is being redelivered"> - <doc> - This indicates that the message has been previously delivered to this or - another client. - </doc> - <rule name = "implementation"> - <doc> - The server SHOULD try to signal redelivered messages when it can. When - redelivering a message that was not successfully acknowledged, the server - SHOULD deliver it to the original client if possible. - </doc> - <doc type = "scenario"> - Create a shared queue and publish a message to the queue. Consume the - message using explicit acknowledgements, but do not acknowledge the - message. Close the connection, reconnect, and consume from the queue - again. The message should arrive with the redelivered flag set. - </doc> - </rule> - <rule name = "hinting"> - <doc> - The client MUST NOT rely on the redelivered field but should take it as a - hint that the message may already have been processed. A fully robust - client must be able to track duplicate received messages on non-transacted, - and locally-transacted channels. - </doc> - </rule> - </domain> - - <domain name = "reply-code" type = "short" label = "reply code from server"> - <doc> - The reply code. The AMQ reply codes are defined as constants at the start - of this formal specification. - </doc> - <assert check = "notnull" /> - </domain> - - <domain name = "reply-text" type = "shortstr" label = "localised reply text"> - <doc> - The localised reply text. This text can be logged as an aid to resolving - issues. - </doc> - <assert check = "notnull" /> - </domain> - - <!-- Elementary domains --> - <domain name = "bit" type = "bit" label = "single bit" /> - <domain name = "octet" type = "octet" label = "single octet" /> - <domain name = "short" type = "short" label = "16-bit integer" /> - <domain name = "long" type = "long" label = "32-bit integer" /> - <domain name = "longlong" type = "longlong" label = "64-bit integer" /> - <domain name = "shortstr" type = "shortstr" label = "short string" /> - <domain name = "longstr" type = "longstr" label = "long string" /> - <domain name = "timestamp" type = "timestamp" label = "64-bit timestamp" /> - <domain name = "table" type = "table" label = "field table" /> - - <!-- == CONNECTION ======================================================= --> - - <!-- TODO 0.81 - the 'handler' attribute of methods needs to be reviewed, and if - no current implementations use it, removed. /PH 2006/07/20 - --> - - <class name = "connection" handler = "connection" index = "10" label = "work with socket connections"> - <doc> - The connection class provides methods for a client to establish a network connection to - a server, and for both peers to operate the connection thereafter. - </doc> - - <doc type = "grammar"> - connection = open-connection *use-connection close-connection - open-connection = C:protocol-header - S:START C:START-OK - *challenge - S:TUNE C:TUNE-OK - C:OPEN S:OPEN-OK | S:REDIRECT - challenge = S:SECURE C:SECURE-OK - use-connection = *channel - close-connection = C:CLOSE S:CLOSE-OK - / S:CLOSE C:CLOSE-OK - </doc> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "start" synchronous = "1" index = "10" label = "start connection negotiation"> - <doc> - This method starts the connection negotiation process by telling the client the - protocol version that the server proposes, along with a list of security mechanisms - which the client can use for authentication. - </doc> - - <rule name = "protocol-name"> - <doc> - If the server cannot support the protocol specified in the protocol header, - it MUST close the socket connection without sending any response method. - </doc> - <doc type = "scenario"> - The client sends a protocol header containing an invalid protocol name. - The server must respond by closing the connection. - </doc> - </rule> - <rule name = "server-support"> - <doc> - The server MUST provide a protocol version that is lower than or equal to - that requested by the client in the protocol header. - </doc> - <doc type = "scenario"> - The client requests a protocol version that is higher than any valid - implementation, e.g. 9.0. The server must respond with a current - protocol version, e.g. 1.0. - </doc> - </rule> - <rule name = "client-support"> - <doc> - If the client cannot handle the protocol version suggested by the server - it MUST close the socket connection. - </doc> - <doc type = "scenario"> - The server sends a protocol version that is lower than any valid - implementation, e.g. 0.1. The client must respond by closing the - connection. - </doc> - </rule> - - <chassis name = "client" implement = "MUST" /> - <response name = "start-ok" /> - - <field name = "version-major" domain = "octet" label = "protocol major version"> - <doc> - The version of the protocol, expressed in protocol units of 0.1 public - versions and properly printed as two digits with a leading zero. I.e. a - protocol version of "09" represents a public version "0.9". The decimal - shift allows the correct expression of pre-1.0 protocol releases. - </doc> - <doc type = "todo"> - This field should be renamed to "protocol version". - </doc> - </field> - - <field name = "version-minor" domain = "octet" label = "protocol major version"> - <doc> - The protocol revision, expressed as an integer from 0 to 9. The use of more - than ten revisions is discouraged. The public version string is constructed - from the protocol version and revision as follows: we print the protocol - version with one decimal position, and we append the protocol revision. A - version=10 and revision=2 are printed as "1.02". - </doc> - <doc type = "todo"> - This field should be renamed to "protocol revision". - </doc> - </field> - - <field name = "server-properties" domain = "peer-properties" label = "server properties"> - <rule name = "required-fields"> - <doc> - The properties SHOULD contain at least these fields: "host", specifying the - server host name or address, "product", giving the name of the server product, - "version", giving the name of the server version, "platform", giving the name - of the operating system, "copyright", if appropriate, and "information", giving - other general information. - </doc> - <doc type = "scenario"> - Client connects to server and inspects the server properties. It checks for - the presence of the required fields. - </doc> - </rule> - </field> - - <field name = "mechanisms" domain = "longstr" label = "available security mechanisms"> - <doc> - A list of the security mechanisms that the server supports, delimited by spaces. - Currently ASL supports these mechanisms: PLAIN. - </doc> - <assert check = "notnull" /> - </field> - - <field name = "locales" domain = "longstr" label = "available message locales"> - <doc> - A list of the message locales that the server supports, delimited by spaces. The - locale defines the language in which the server will send reply texts. - </doc> - <rule name = "required-support"> - <doc> - The server MUST support at least the en_US locale. - </doc> - <doc type = "scenario"> - Client connects to server and inspects the locales field. It checks for - the presence of the required locale(s). - </doc> - </rule> - <assert check = "notnull" /> - </field> - </method> - - <method name = "start-ok" synchronous = "1" index = "11" - label = "select security mechanism and locale"> - <doc> - This method selects a SASL security mechanism. ASL uses SASL (RFC2222) to - negotiate authentication and encryption. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "client-properties" domain = "peer-properties" label = "client properties"> - <rule name = "required-fields"> - <!-- This rule is not testable from the client side --> - <doc> - The properties SHOULD contain at least these fields: "product", giving the name - of the client product, "version", giving the name of the client version, "platform", - giving the name of the operating system, "copyright", if appropriate, and - "information", giving other general information. - </doc> - </rule> - </field> - - <field name = "mechanism" domain = "shortstr" label = "selected security mechanism"> - <doc> - A single security mechanisms selected by the client, which must be one of those - specified by the server. - </doc> - <rule name = "security"> - <doc> - The client SHOULD authenticate using the highest-level security profile it - can handle from the list provided by the server. - </doc> - </rule> - <rule name = "validity"> - <doc> - If the mechanism field does not contain one of the security mechanisms - proposed by the server in the Start method, the server MUST close the - connection without sending any further data. - </doc> - <doc type = "scenario"> - Client connects to server and sends an invalid security mechanism. The - server must respond by closing the connection (a socket close, with no - connection close negotiation). - </doc> - </rule> - <assert check = "notnull" /> - </field> - - <field name = "response" domain = "longstr" label = "security response data"> - <doc> - A block of opaque data passed to the security mechanism. The contents of this - data are defined by the SASL security mechanism. - </doc> - <assert check = "notnull" /> - </field> - - <field name = "locale" domain = "shortstr" label = "selected message locale"> - <doc> - A single message local selected by the client, which must be one of those - specified by the server. - </doc> - <assert check = "notnull" /> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "secure" synchronous = "1" index = "20" label = "security mechanism challenge"> - <doc> - The SASL protocol works by exchanging challenges and responses until both peers have - received sufficient information to authenticate each other. This method challenges - the client to provide more information. - </doc> - - <chassis name = "client" implement = "MUST" /> - <response name = "secure-ok" /> - - <field name = "challenge" domain = "longstr" label = "security challenge data"> - <doc> - Challenge information, a block of opaque binary data passed to the security - mechanism. - </doc> - </field> - </method> - - <method name = "secure-ok" synchronous = "1" index = "21" label = "security mechanism response"> - <doc> - This method attempts to authenticate, passing a block of SASL data for the security - mechanism at the server side. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "response" domain = "longstr" label = "security response data"> - <doc> - A block of opaque data passed to the security mechanism. The contents of this - data are defined by the SASL security mechanism. - </doc> - <assert check = "notnull" /> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "tune" synchronous = "1" index = "30" - label = "propose connection tuning parameters"> - <doc> - This method proposes a set of connection configuration values to the client. The - client can accept and/or adjust these. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <response name = "tune-ok" /> - - <field name = "channel-max" domain = "short" label = "proposed maximum channels"> - <doc> - The maximum total number of channels that the server allows per connection. Zero - means that the server does not impose a fixed limit, but the number of allowed - channels may be limited by available server resources. - </doc> - </field> - - <field name = "frame-max" domain = "long" label = "proposed maximum frame size"> - <doc> - The largest frame size that the server proposes for the connection. The client - can negotiate a lower value. Zero means that the server does not impose any - specific limit but may reject very large frames if it cannot allocate resources - for them. - </doc> - <rule name = "minimum"> - <doc> - Until the frame-max has been negotiated, both peers MUST accept frames of up - to frame-min-size octets large, and the minimum negotiated value for frame-max - is also frame-min-size. - </doc> - <doc type = "scenario"> - Client connects to server and sends a large properties field, creating a frame - of frame-min-size octets. The server must accept this frame. - </doc> - </rule> - </field> - - <field name = "heartbeat" domain = "short" label = "desired heartbeat delay"> - <!-- TODO 0.82 - the heartbeat negotiation mechanism was changed during - implementation because the model documented here does not actually - work properly. The best model we found is that the server proposes - a heartbeat value to the client; the client can reply with zero, meaning - 'do not use heartbeats (as documented here), or can propose its own - heartbeat value, which the server should then accept. This is different - from the model here which is disconnected - e.g. each side requests a - heartbeat independently. Basically a connection is heartbeated in - both ways, or not at all, depending on whether both peers support - heartbeating or not, and the heartbeat value should itself be chosen - by the client so that remote links can get a higher value. Also, the - actual heartbeat mechanism needs documentation, and is as follows: so - long as there is activity on a connection - in or out - both peers - assume the connection is active. When there is no activity, each peer - must send heartbeat frames. When no heartbeat frame is received after - N cycles (where N is at least 2), the connection can be considered to - have died. /PH 2006/07/19 - --> - <doc> - The delay, in seconds, of the connection heartbeat that the server wants. - Zero means the server does not want a heartbeat. - </doc> - </field> - </method> - - <method name = "tune-ok" synchronous = "1" index = "31" - label = "negotiate connection tuning parameters"> - <doc> - This method sends the client's connection tuning parameters to the server. - Certain fields are negotiated, others provide capability information. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "channel-max" domain = "short" label = "negotiated maximum channels"> - <doc> - The maximum total number of channels that the client will use per connection. - </doc> - <rule name = "upper-limit"> - <doc> - If the client specifies a channel max that is higher than the value provided - by the server, the server MUST close the connection without attempting a - negotiated close. The server may report the error in some fashion to assist - implementors. - </doc> - </rule> - <assert check = "notnull" /> - <assert check = "le" method = "tune" field = "channel-max" /> - </field> - - <field name = "frame-max" domain = "long" label = "negotiated maximum frame size"> - <doc> - The largest frame size that the client and server will use for the connection. - Zero means that the client does not impose any specific limit but may reject - very large frames if it cannot allocate resources for them. Note that the - frame-max limit applies principally to content frames, where large contents can - be broken into frames of arbitrary size. - </doc> - <rule name = "minimum"> - <doc> - Until the frame-max has been negotiated, both peers MUST accept frames of up - to frame-min-size octets large, and the minimum negotiated value for frame-max - is also frame-min-size. - </doc> - </rule> - <rule name = "upper-limit"> - <doc> - If the client specifies a frame max that is higher than the value provided - by the server, the server MUST close the connection without attempting a - negotiated close. The server may report the error in some fashion to assist - implementors. - </doc> - </rule> - </field> - - <field name = "heartbeat" domain = "short" label = "desired heartbeat delay"> - <doc> - The delay, in seconds, of the connection heartbeat that the client wants. Zero - means the client does not want a heartbeat. - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "open" synchronous = "1" index = "40" label = "open connection to virtual host"> - <doc> - This method opens a connection to a virtual host, which is a collection of - resources, and acts to separate multiple application domains within a server. - The server may apply arbitrary limits per virtual host, such as the number - of each type of entity that may be used, per connection and/or in total. - </doc> - - <chassis name = "server" implement = "MUST" /> - <response name = "open-ok" /> - <response name = "redirect" /> - - <field name = "virtual-host" domain = "path" label = "virtual host name"> - <!-- TODO 0.82 - the entire vhost model needs review. This concept was - prompted by the HTTP vhost concept but does not fit very well into - AMQP. Currently we use the vhost as a "cluster identifier" which is - inaccurate usage. /PH 2006/07/19 - --> - <assert check = "regexp" value = "^[a-zA-Z0-9/-_]+$" /> - <doc> - The name of the virtual host to work with. - </doc> - <rule name = "separation"> - <doc> - If the server supports multiple virtual hosts, it MUST enforce a full - separation of exchanges, queues, and all associated entities per virtual - host. An application, connected to a specific virtual host, MUST NOT be able - to access resources of another virtual host. - </doc> - </rule> - <rule name = "security"> - <doc> - The server SHOULD verify that the client has permission to access the - specified virtual host. - </doc> - </rule> - </field> - - <field name = "capabilities" domain = "shortstr" label = "required capabilities"> - <doc> - The client can specify zero or more capability names, delimited by spaces. - The server can use this string to how to process the client's connection - request. - </doc> - </field> - - <field name = "insist" domain = "bit" label = "insist on connecting to server"> - <doc> - In a configuration with multiple collaborating servers, the server may respond - to a Connection.Open method with a Connection.Redirect. The insist option tells - the server that the client is insisting on a connection to the specified server. - </doc> - <rule name = "behaviour"> - <doc> - When the client uses the insist option, the server MUST NOT respond with a - Connection.Redirect method. If it cannot accept the client's connection - request it should respond by closing the connection with a suitable reply - code. - </doc> - </rule> - </field> - </method> - - <method name = "open-ok" synchronous = "1" index = "41" label = "signal that connection is ready"> - <doc> - This method signals to the client that the connection is ready for use. - </doc> - <chassis name = "client" implement = "MUST" /> - <field name = "known-hosts" domain = "known-hosts" /> - </method> - - <method name = "redirect" synchronous = "1" index = "42" label = "redirects client to other server"> - <doc> - This method redirects the client to another server, based on the requested virtual - host and/or capabilities. - </doc> - <rule name = "usage"> - <doc> - When getting the Connection.Redirect method, the client SHOULD reconnect to - the host specified, and if that host is not present, to any of the hosts - specified in the known-hosts list. - </doc> - </rule> - <chassis name = "client" implement = "MUST" /> - <field name = "host" domain = "shortstr" label = "server to connect to"> - <doc> - Specifies the server to connect to. This is an IP address or a DNS name, - optionally followed by a colon and a port number. If no port number is - specified, the client should use the default port number for the protocol. - </doc> - <assert check = "notnull" /> - </field> - <field name = "known-hosts" domain = "known-hosts" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "close" synchronous = "1" index = "50" label = "request a connection close"> - <doc> - This method indicates that the sender wants to close the connection. This may be - due to internal conditions (e.g. a forced shut-down) or due to an error handling - a specific method, i.e. an exception. When a close is due to an exception, the - sender provides the class and method id of the method which caused the exception. - </doc> - <!-- TODO: the connection close mechanism needs to be reviewed from the ODF - documentation and better expressed as rules here. /PH 2006/07/20 - --> - <rule name = "stability"> - <doc> - After sending this method any received method except the Close-OK method MUST - be discarded. - </doc> - </rule> - - <chassis name = "client" implement = "MUST" /> - <chassis name = "server" implement = "MUST" /> - <response name = "close-ok" /> - - <field name = "reply-code" domain = "reply-code" /> - <field name = "reply-text" domain = "reply-text" /> - - <field name = "class-id" domain = "class-id" label = "failing method class"> - <doc> - When the close is provoked by a method exception, this is the class of the - method. - </doc> - </field> - - <field name = "method-id" domain = "method-id" label = "failing method ID"> - <doc> - When the close is provoked by a method exception, this is the ID of the method. - </doc> - </field> - </method> - - <method name = "close-ok" synchronous = "1" index = "51" label = "confirm a connection close"> - <doc> - This method confirms a Connection.Close method and tells the recipient that it is - safe to release resources for the connection and close the socket. - </doc> - <rule name = "reporting"> - <doc> - A peer that detects a socket closure without having received a Close-Ok - handshake method SHOULD log the error. - </doc> - </rule> - <chassis name = "client" implement = "MUST" /> - <chassis name = "server" implement = "MUST" /> - </method> - </class> - - <!-- == CHANNEL ========================================================== --> - - <class name = "channel" handler = "channel" index = "20" label = "work with channels"> - <doc> - The channel class provides methods for a client to establish a channel to a - server and for both peers to operate the channel thereafter. - </doc> - - <doc type = "grammar"> - channel = open-channel *use-channel close-channel - open-channel = C:OPEN S:OPEN-OK - use-channel = C:FLOW S:FLOW-OK - / S:FLOW C:FLOW-OK - / S:ALERT - / functional-class - close-channel = C:CLOSE S:CLOSE-OK - / S:CLOSE C:CLOSE-OK - </doc> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "open" synchronous = "1" index = "10" label = "open a channel for use"> - <doc> - This method opens a channel to the server. - </doc> - <rule name = "state" on-failure = "channel-error"> - <doc> - The client MUST NOT use this method on an alread-opened channel. - </doc> - <doc type = "scenario"> - Client opens a channel and then reopens the same channel. - </doc> - </rule> - <chassis name = "server" implement = "MUST" /> - <response name = "open-ok" /> - <field name = "out of band" domain = "shortstr" label = "out-of-band settings"> - <doc> - Configures out-of-band transfers on this channel. The syntax and meaning of this - field will be formally defined at a later date. - </doc> - <assert check = "null" /> - </field> - </method> - - <method name = "open-ok" synchronous = "1" index = "11" label = "signal that the channel is ready"> - <doc> - This method signals to the client that the channel is ready for use. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "flow" synchronous = "1" index = "20" label = "enable/disable flow from peer"> - <doc> - This method asks the peer to pause or restart the flow of content data. This is a - simple flow-control mechanism that a peer can use to avoid oveflowing its queues or - otherwise finding itself receiving more messages than it can process. Note that this - method is not intended for window control. The peer that receives a disable flow - method should finish sending the current content frame, if any, then pause. - </doc> - - <rule name = "initial-state"> - <doc> - When a new channel is opened, it is active (flow is active). Some applications - assume that channels are inactive until started. To emulate this behaviour a - client MAY open the channel, then pause it. - </doc> - </rule> - - <rule name = "bidirectional"> - <doc> - When sending content frames, a peer SHOULD monitor the channel for incoming - methods and respond to a Channel.Flow as rapidly as possible. - </doc> - </rule> - - <rule name = "throttling"> - <doc> - A peer MAY use the Channel.Flow method to throttle incoming content data for - internal reasons, for example, when exchanging data over a slower connection. - </doc> - </rule> - - <rule name = "expected-behaviour"> - <doc> - The peer that requests a Channel.Flow method MAY disconnect and/or ban a peer - that does not respect the request. This is to prevent badly-behaved clients - from overwhelming a broker. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <response name = "flow-ok" /> - - <field name = "active" domain = "bit" label = "start/stop content frames"> - <doc> - If 1, the peer starts sending content frames. If 0, the peer stops sending - content frames. - </doc> - </field> - </method> - - <method name = "flow-ok" index = "21" label = "confirm a flow method"> - <doc> - Confirms to the peer that a flow command was received and processed. - </doc> - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - <field name = "active" domain = "bit" label = "current flow setting"> - <doc> - Confirms the setting of the processed flow method: 1 means the peer will start - sending or continue to send content frames; 0 means it will not. - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <!-- TODO 0.82 - remove this method entirely - /PH 2006/07/20 - --> - <method name = "alert" index = "30" label = "send a non-fatal warning message"> - <doc> - This method allows the server to send a non-fatal warning to the client. This is - used for methods that are normally asynchronous and thus do not have confirmations, - and for which the server may detect errors that need to be reported. Fatal errors - are handled as channel or connection exceptions; non-fatal errors are sent through - this method. - </doc> - <chassis name = "client" implement = "MUST" /> - <field name = "reply-code" domain = "reply-code" /> - <field name = "reply-text" domain = "reply-text" /> - <field name = "details" domain = "table" label = "detailed information for warning"> - <doc> - A set of fields that provide more information about the problem. The meaning of - these fields are defined on a per-reply-code basis (TO BE DEFINED). - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "close" synchronous = "1" index = "40" label = "request a channel close"> - <doc> - This method indicates that the sender wants to close the channel. This may be due to - internal conditions (e.g. a forced shut-down) or due to an error handling a specific - method, i.e. an exception. When a close is due to an exception, the sender provides - the class and method id of the method which caused the exception. - </doc> - - <!-- TODO: the channel close behaviour needs to be reviewed from the ODF - documentation and better expressed as rules here. /PH 2006/07/20 - --> - <rule name = "stability"> - <doc> - After sending this method any received method except the Close-OK method MUST - be discarded. - </doc> - </rule> - - <chassis name = "client" implement = "MUST" /> - <chassis name = "server" implement = "MUST" /> - <response name = "close-ok" /> - - <field name = "reply-code" domain = "reply-code" /> - <field name = "reply-text" domain = "reply-text" /> - - <field name = "class-id" domain = "class-id" label = "failing method class"> - <doc> - When the close is provoked by a method exception, this is the class of the - method. - </doc> - </field> - - <field name = "method-id" domain = "method-id" label = "failing method ID"> - <doc> - When the close is provoked by a method exception, this is the ID of the method. - </doc> - </field> - </method> - - <method name = "close-ok" synchronous = "1" index = "41" label = "confirm a channel close"> - <doc> - This method confirms a Channel.Close method and tells the recipient that it is safe - to release resources for the channel and close the socket. - </doc> - <rule name = "reporting"> - <doc> - A peer that detects a socket closure without having received a Channel.Close-Ok - handshake method SHOULD log the error. - </doc> - </rule> - <chassis name = "client" implement = "MUST" /> - <chassis name = "server" implement = "MUST" /> - </method> - </class> - - <!-- == ACCESS =========================================================== --> - - <!-- TODO 0.82 - this class must be implemented by two teams before we can - consider it matured. - --> - - <class name = "access" handler = "connection" index = "30" label = "work with access tickets"> - <doc> - The protocol control access to server resources using access tickets. A - client must explicitly request access tickets before doing work. An access - ticket grants a client the right to use a specific set of resources - - called a "realm" - in specific ways. - </doc> - - <doc type = "grammar"> - access = C:REQUEST S:REQUEST-OK - </doc> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "request" synchronous = "1" index = "10" label = "request an access ticket"> - <doc> - This method requests an access ticket for an access realm. The server - responds by granting the access ticket. If the client does not have - access rights to the requested realm this causes a connection exception. - Access tickets are a per-channel resource. - </doc> - - <chassis name = "server" implement = "MUST" /> - <response name = "request-ok" /> - - <field name = "realm" domain = "shortstr" label = "name of requested realm"> - <doc> - Specifies the name of the realm to which the client is requesting access. - The realm is a configured server-side object that collects a set of - resources (exchanges, queues, etc.). If the channel has already requested - an access ticket onto this realm, the previous ticket is destroyed and a - new ticket is created with the requested access rights, if allowed. - </doc> - <rule name = "validity" on-failure = "access-refused"> - <doc> - The client MUST specify a realm that is known to the server. The server - makes an identical response for undefined realms as it does for realms - that are defined but inaccessible to this client. - </doc> - <doc type = "scenario"> - Client specifies an undefined realm. - </doc> - </rule> - </field> - - <field name = "exclusive" domain = "bit" label = "request exclusive access"> - <doc> - Request exclusive access to the realm, meaning that this will be the only - channel that uses the realm's resources. - </doc> - <rule name = "validity" on-failure = "access-refused"> - <doc> - The client MAY NOT request exclusive access to a realm that has active - access tickets, unless the same channel already had the only access - ticket onto that realm. - </doc> - <doc type = "scenario"> - Client opens two channels and requests exclusive access to the same realm. - </doc> - </rule> - </field> - <field name = "passive" domain = "bit" label = "request passive access"> - <doc> - Request message passive access to the specified access realm. Passive - access lets a client get information about resources in the realm but - not to make any changes to them. - </doc> - </field> - <field name = "active" domain = "bit" label = "request active access"> - <doc> - Request message active access to the specified access realm. Active access lets - a client get create and delete resources in the realm. - </doc> - </field> - <field name = "write" domain = "bit" label = "request write access"> - <doc> - Request write access to the specified access realm. Write access lets a client - publish messages to all exchanges in the realm. - </doc> - </field> - <field name = "read" domain = "bit" label = "request read access"> - <doc> - Request read access to the specified access realm. Read access lets a client - consume messages from queues in the realm. - </doc> - </field> - </method> - - <method name = "request-ok" synchronous = "1" index = "11" label = "grant access to server resources"> - <doc> - This method provides the client with an access ticket. The access ticket is valid - within the current channel and for the lifespan of the channel. - </doc> - <rule name = "per-channel" on-failure = "not-allowed"> - <doc> - The client MUST NOT use access tickets except within the same channel as - originally granted. - </doc> - <doc type = "scenario"> - Client opens two channels, requests a ticket on one channel, and then - tries to use that ticket in a seconc channel. - </doc> - </rule> - <chassis name = "client" implement = "MUST" /> - <field name = "ticket" domain = "access-ticket" /> - </method> - </class> - - <!-- == EXCHANGE ========================================================= --> - - <class name = "exchange" handler = "channel" index = "40" label = "work with exchanges"> - <doc> - Exchanges match and distribute messages across queues. Exchanges can be configured in - the server or created at runtime. - </doc> - - <doc type = "grammar"> - exchange = C:DECLARE S:DECLARE-OK - / C:DELETE S:DELETE-OK - </doc> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <rule name = "required-types"> - <doc> - The server MUST implement these standard exchange types: fanout, direct. - </doc> - <doc type = "scenario"> - Client attempts to declare an exchange with each of these standard types. - </doc> - </rule> - <rule name = "recommended-types"> - <doc> - The server SHOULD implement these standard exchange types: topic, headers. - </doc> - <doc type = "scenario"> - Client attempts to declare an exchange with each of these standard types. - </doc> - </rule> - <rule name = "required-instances"> - <doc> - The server MUST, in each virtual host, pre-declare an exchange instance - for each standard exchange type that it implements, where the name of the - exchange instance is "amq." followed by the exchange type name. - </doc> - <doc type = "scenario"> - Client creates a temporary queue and attempts to bind to each required - exchange instance (amq.fanout, amq.direct, and amq.topic, amq.headers if - those types are defined). - </doc> - </rule> - <rule name = "default-exchange"> - <doc> - The server MUST predeclare a direct exchange to act as the default exchange - for content Publish methods and for default queue bindings. - </doc> - <doc type = "scenario"> - Client checks that the default exchange is active by specifying a queue - binding with no exchange name, and publishing a message with a suitable - routing key but without specifying the exchange name, then ensuring that - the message arrives in the queue correctly. - </doc> - </rule> - <rule name = "default-access"> - <doc> - The server MUST NOT allow clients to access the default exchange except - by specifying an empty exchange name in the Queue.Bind and content Publish - methods. - </doc> - </rule> - <rule name = "extensions"> - <doc> - The server MAY implement other exchange types as wanted. - </doc> - </rule> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "declare" synchronous = "1" index = "10" label = "declare exchange, create if needed"> - <doc> - This method creates an exchange if it does not already exist, and if the exchange - exists, verifies that it is of the correct and expected class. - </doc> - <rule name = "minimum"> - <doc> - The server SHOULD support a minimum of 16 exchanges per virtual host and - ideally, impose no limit except as defined by available resources. - </doc> - <doc type = "scenario"> - The client creates as many exchanges as it can until the server reports - an error; the number of exchanges successfuly created must be at least - sixteen. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - <response name = "declare-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <doc> - When a client defines a new exchange, this belongs to the access realm of the - ticket used. All further work done with that exchange must be done with an - access ticket for the same realm. - </doc> - <rule name = "validity" on-failure = "access-refused"> - <doc> - The client MUST provide a valid access ticket giving "active" access to - the realm in which the exchange exists or will be created, or "passive" - access if the if-exists flag is set. - </doc> - <doc type = "scenario"> - Client creates access ticket with wrong access rights and attempts to use - in this method. - </doc> - </rule> - </field> - - <field name = "exchange" domain = "exchange-name"> - <rule name = "reserved" on-failure = "access-refused"> - <doc> - Exchange names starting with "amq." are reserved for predeclared and - standardised exchanges. The client MUST NOT attempt to create an exchange - starting with "amq.". - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - <assert check = "regexp" value = "^[a-zA-Z0-9-_.:]+$" /> - </field> - - <field name = "type" domain = "shortstr" label = "exchange type"> - <doc> - Each exchange belongs to one of a set of exchange types implemented by the - server. The exchange types define the functionality of the exchange - i.e. how - messages are routed through it. It is not valid or meaningful to attempt to - change the type of an existing exchange. - </doc> - <rule name = "typed" on-failure = "not-allowed"> - <doc> - Exchanges cannot be redeclared with different types. The client MUST not - attempt to redeclare an existing exchange with a different type than used - in the original Exchange.Declare method. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - <rule name = "support" on-failure = "command-invalid"> - <doc> - The client MUST NOT attempt to create an exchange with a type that the - server does not support. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - <assert check = "regexp" value = "^[a-zA-Z0-9-_.:]+$" /> - </field> - - <field name = "passive" domain = "bit" label = "do not create exchange"> - <doc> - If set, the server will not create the exchange. The client can use this to - check whether an exchange exists without modifying the server state. - </doc> - <rule name = "not-found"> - <doc> - If set, and the exchange does not already exist, the server MUST raise a - channel exception with reply code 404 (not found). - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <field name = "durable" domain = "bit" label = "request a durable exchange"> - <doc> - If set when creating a new exchange, the exchange will be marked as durable. - Durable exchanges remain active when a server restarts. Non-durable exchanges - (transient exchanges) are purged if/when a server restarts. - </doc> - <rule name = "support"> - <doc> - The server MUST support both durable and transient exchanges. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - <rule name = "sticky"> - <doc> - The server MUST ignore the durable field if the exchange already exists. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <!-- TODO 0.82 - clarify how this works; there is no way to cancel a binding - except by deleting a queue. - --> - <field name = "auto-delete" domain = "bit" label = "auto-delete when unused"> - <doc> - If set, the exchange is deleted when all queues have finished using it. - </doc> - <rule name = "sticky"> - <doc> - The server MUST ignore the auto-delete field if the exchange already - exists. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <field name = "internal" domain = "bit" label = "create internal exchange"> - <doc> - If set, the exchange may not be used directly by publishers, but only when bound - to other exchanges. Internal exchanges are used to construct wiring that is not - visible to applications. - </doc> - </field> - - <field name = "nowait" domain = "bit" label = "do not send reply method"> - <doc> - If set, the server will not respond to the method. The client should not wait - for a reply method. If the server could not complete the method it will raise a - channel or connection exception. - </doc> - </field> - - <field name = "arguments" domain = "table" label = "arguments for declaration"> - <doc> - A set of arguments for the declaration. The syntax and semantics of these - arguments depends on the server implementation. This field is ignored if passive - is 1. - </doc> - </field> - </method> - - <method name = "declare-ok" synchronous = "1" index = "11" label = "confirm exchange declaration"> - <doc> - This method confirms a Declare method and confirms the name of the exchange, - essential for automatically-named exchanges. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "delete" synchronous = "1" index = "20" label = "delete an exchange"> - <doc> - This method deletes an exchange. When an exchange is deleted all queue bindings on - the exchange are cancelled. - </doc> - - <chassis name = "server" implement = "MUST" /> - <response name = "delete-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "validity" on-failure = "access-refused"> - <doc> - The client MUST provide a valid access ticket giving "active" access - rights to the exchange's access realm. - </doc> - <doc type = "scenario"> - Client creates access ticket with wrong access rights and attempts to use - in this method. - </doc> - </rule> - </field> - - <field name = "exchange" domain = "exchange-name"> - <rule name = "exists" on-failure = "not-found"> - <doc> - The client MUST NOT attempt to delete an exchange that does not exist. - </doc> - </rule> - <assert check = "notnull" /> - </field> - - <!-- TODO 0.82 - discuss whether this option is useful or not. I don't have - any real use case for it. /PH 2006-07-23. - --> - <field name = "if-unused" domain = "bit" label = "delete only if unused"> - <doc> - If set, the server will only delete the exchange if it has no queue bindings. If - the exchange has queue bindings the server does not delete it but raises a - channel exception instead. - </doc> - </field> - - <field name = "nowait" domain = "bit" label = "do not send a reply method"> - <doc> - If set, the server will not respond to the method. The client should not wait - for a reply method. If the server could not complete the method it will raise a - channel or connection exception. - </doc> - </field> - </method> - - <method name = "delete-ok" synchronous = "1" index = "21" - label = "confirm deletion of an exchange"> - <doc>This method confirms the deletion of an exchange.</doc> - <chassis name = "client" implement = "MUST" /> - </method> - </class> - - <!-- == QUEUE ============================================================ --> - - <class name = "queue" handler = "channel" index = "50" label = "work with queues"> - <doc> - Queues store and forward messages. Queues can be configured in the server or created at - runtime. Queues must be attached to at least one exchange in order to receive messages - from publishers. - </doc> - - <doc type = "grammar"> - queue = C:DECLARE S:DECLARE-OK - / C:BIND S:BIND-OK - / C:PURGE S:PURGE-OK - / C:DELETE S:DELETE-OK - </doc> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <rule name = "any-content"> - <doc> - A server MUST allow any content class to be sent to any queue, in any mix, and - queue and deliver these content classes independently. Note that all methods - that fetch content off queues are specific to a given content class. - </doc> - <doc type = "scenario"> - Client creates an exchange of each standard type and several queues that - it binds to each exchange. It must then sucessfully send each of the standard - content types to each of the available queues. - </doc> - </rule> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "declare" synchronous = "1" index = "10" label = "declare queue, create if needed"> - <doc> - This method creates or checks a queue. When creating a new queue the client can - specify various properties that control the durability of the queue and its - contents, and the level of sharing for the queue. - </doc> - - <rule name = "default-binding"> - <doc> - The server MUST create a default binding for a newly-created queue to the - default exchange, which is an exchange of type 'direct'. - </doc> - <doc type = "scenario"> - Client creates a new queue, and then without explicitly binding it to an - exchange, attempts to send a message through the default exchange binding, - i.e. publish a message to the empty exchange, with the queue name as routing - key. - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_35" --> - <rule name = "minimum-queues"> - <doc> - The server SHOULD support a minimum of 256 queues per virtual host and ideally, - impose no limit except as defined by available resources. - </doc> - <doc type = "scenario"> - Client attempts to create as many queues as it can until the server reports - an error. The resulting count must at least be 256. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - <response name = "declare-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <doc> - When a client defines a new queue, this belongs to the access realm of the - ticket used. All further work done with that queue must be done with an access - ticket for the same realm. - </doc> - <rule name = "validity" on-failure = "access-refused"> - <doc> - The client MUST provide a valid access ticket giving "active" access to - the realm in which the queue exists or will be created. - </doc> - <doc type = "scenario"> - Client creates access ticket with wrong access rights and attempts to use - in this method. - </doc> - </rule> - </field> - - <field name = "queue" domain = "queue-name"> - <rule name = "default-name"> - <doc> - The queue name MAY be empty, in which case the server MUST create a new - queue with a unique generated name and return this to the client in the - Declare-Ok method. - </doc> - <doc type = "scenario"> - Client attempts to create several queues with an empty name. The client then - verifies that the server-assigned names are unique and different. - </doc> - </rule> - <rule name = "reserved-prefix" on-failure = "not-allowed"> - <doc> - Queue names starting with "amq." are reserved for predeclared and - standardised server queues. A client MAY NOT attempt to declare a queue with a - name that starts with "amq." and the passive option set to zero. - </doc> - <doc type = "scenario"> - A client attempts to create a queue with a name starting with "amq." and with - the passive option set to zero. - </doc> - </rule> - <assert check = "regexp" value = "^[a-zA-Z0-9-_.:]*$" /> - </field> - - <field name = "passive" domain = "bit" label = "do not create queue"> - <doc> - If set, the server will not create the queue. This field allows the client - to assert the presence of a queue without modifying the server state. - </doc> - <rule name = "passive" on-failure = "not-found"> - <doc> - The client MAY ask the server to assert that a queue exists without - creating the queue if not. If the queue does not exist, the server - treats this as a failure. - </doc> - <doc type = "scenario"> - Client declares an existing queue with the passive option and expects - the server to respond with a declare-ok. Client then attempts to declare - a non-existent queue with the passive option, and the server must close - the channel with the correct reply-code. - </doc> - </rule> - </field> - - <field name = "durable" domain = "bit" label = "request a durable queue"> - <doc> - If set when creating a new queue, the queue will be marked as durable. Durable - queues remain active when a server restarts. Non-durable queues (transient - queues) are purged if/when a server restarts. Note that durable queues do not - necessarily hold persistent messages, although it does not make sense to send - persistent messages to a transient queue. - </doc> - <!-- Rule test name: was "amq_queue_03" --> - <rule name = "persistence"> - <doc>The server MUST recreate the durable queue after a restart.</doc> - - <!-- TODO: use 'client does something' rather than 'a client does something'. --> - <doc type = "scenario"> - A client creates a durable queue. The server is then restarted. The client - then attempts to send a message to the queue. The message should be successfully - delivered. - </doc> - </rule> - <!-- Rule test name: was "amq_queue_36" --> - <rule name = "types"> - <doc>The server MUST support both durable and transient queues.</doc> - <doc type = "scenario"> - A client creates two named queues, one durable and one transient. - </doc> - </rule> - <!-- Rule test name: was "amq_queue_37" --> - <rule name = "pre-existence"> - <doc>The server MUST ignore the durable field if the queue already exists.</doc> - <doc type = "scenario"> - A client creates two named queues, one durable and one transient. The client - then attempts to declare the two queues using the same names again, but reversing - the value of the durable flag in each case. Verify that the queues still exist - with the original durable flag values. - <!-- TODO: but how? --> - </doc> - </rule> - </field> - - <field name = "exclusive" domain = "bit" label = "request an exclusive queue"> - <doc> - Exclusive queues may only be consumed from by the current connection. Setting - the 'exclusive' flag always implies 'auto-delete'. - </doc> - - <!-- Rule test name: was "amq_queue_38" --> - <rule name = "types"> - <doc> - The server MUST support both exclusive (private) and non-exclusive (shared) - queues. - </doc> - <doc type = "scenario"> - A client creates two named queues, one exclusive and one non-exclusive. - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_04" --> - <rule name = "02" on-failure = "channel-error"> - <doc> - The client MAY NOT attempt to declare any existing and exclusive queue - on multiple connections. - </doc> - <doc type = "scenario"> - A client declares an exclusive named queue. A second client on a different - connection attempts to declare a queue of the same name. - </doc> - </rule> - </field> - - <field name = "auto-delete" domain = "bit" label = "auto-delete queue when unused"> - <doc> - If set, the queue is deleted when all consumers have finished using it. Last - consumer can be cancelled either explicitly or because its channel is closed. If - there was no consumer ever on the queue, it won't be deleted. - </doc> - - <!-- Rule test name: was "amq_queue_31" --> - <rule name = "pre-existence"> - <doc> - The server MUST ignore the auto-delete field if the queue already exists. - </doc> - <doc type = "scenario"> - A client creates two named queues, one as auto-delete and one explicit-delete. - The client then attempts to declare the two queues using the same names again, - but reversing the value of the auto-delete field in each case. Verify that the - queues still exist with the original auto-delete flag values. - <!-- TODO: but how? --> - </doc> - </rule> - </field> - - <field name = "nowait" domain = "bit" label = "do not send a reply method"> - <doc> - If set, the server will not respond to the method. The client should not wait - for a reply method. If the server could not complete the method it will raise a - channel or connection exception. - </doc> - </field> - - <field name = "arguments" domain = "table" label = "arguments for declaration"> - <doc> - A set of arguments for the declaration. The syntax and semantics of these - arguments depends on the server implementation. This field is ignored if passive - is 1. - </doc> - </field> - </method> - - <method name = "declare-ok" synchronous = "1" index = "11" label = "confirms a queue definition"> - <doc> - This method confirms a Declare method and confirms the name of the queue, essential - for automatically-named queues. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "queue" domain = "queue-name"> - <doc> - Reports the name of the queue. If the server generated a queue name, this field - contains that name. - </doc> - <assert check = "notnull" /> - </field> - - <field name = "message-count" domain = "long" label = "number of messages in queue"> - <doc> - Reports the number of messages in the queue, which will be zero for - newly-created queues. - </doc> - </field> - - <field name = "consumer-count" domain = "long" label = "number of consumers"> - <doc> - Reports the number of active consumers for the queue. Note that consumers can - suspend activity (Channel.Flow) in which case they do not appear in this count. - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "bind" synchronous = "1" index = "20" label = "bind queue to an exchange"> - <doc> - This method binds a queue to an exchange. Until a queue is bound it will not receive - any messages. In a classic messaging model, store-and-forward queues are bound to a - dest exchange and subscription queues are bound to a dest_wild exchange. - </doc> - - <!-- Rule test name: was "amq_queue_25" --> - <rule name = "duplicates"> - <doc> - A server MUST allow ignore duplicate bindings - that is, two or more bind - methods for a specific queue, with identical arguments - without treating these - as an error. - </doc> - <doc type = "scenario"> - A client binds a named queue to an exchange. The client then repeats the bind - (with identical arguments). - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_39" --> - <rule name = "failure" on-failure = "??????"> - <!-- - TODO: Find correct code. The on-failure code returned should depend on why the bind - failed. Assuming that failures owing to bad parameters are covered in the rules relating - to those parameters, the only remaining reason for a failure would be the lack of - server resorces or some internal error - such as too many queues open. Would these - cases qualify as "resource error" 506 or "internal error" 541? - --> - <doc>If a bind fails, the server MUST raise a connection exception.</doc> - <doc type = "scenario"> - TODO - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_12" --> - <rule name = "transient-exchange" on-failure = "not-allowed"> - <doc> - The server MUST NOT allow a durable queue to bind to a transient exchange. - </doc> - <doc type = "scenario"> - A client creates a transient exchange. The client then declares a named durable - queue and then attempts to bind the transient exchange to the durable queue. - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_13" --> - <rule name = "durable-exchange"> - <doc> - Bindings for durable queues are automatically durable and the server SHOULD - restore such bindings after a server restart. - </doc> - <doc type = "scenario"> - A server creates a named durable queue and binds it to a durable exchange. The - server is restarted. The client then attempts to use the queue/exchange combination. - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_17" --> - <rule name = "internal-exchange"> - <doc> - If the client attempts to bind to an exchange that was declared as internal, the server - MUST raise a connection exception with reply code 530 (not allowed). - </doc> - <doc type = "scenario"> - A client attempts to bind a named queue to an internal exchange. - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_40" --> - <rule name = "binding-count"> - <doc> - The server SHOULD support at least 4 bindings per queue, and ideally, impose no - limit except as defined by available resources. - </doc> - <doc type = "scenario"> - A client creates a named queue and attempts to bind it to 4 different non-internal - exchanges. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - - <response name = "bind-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <doc> - The client provides a valid access ticket giving "active" access rights to the - queue's access realm. - </doc> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue to bind. If the queue name is empty, refers to - the current queue for the channel, which is the last declared queue. - </doc> - - <rule name = "empty-queue" on-failure = "not-allowed"> - <doc> - A client MUST NOT be allowed to bind a non-existent and unnamed queue (i.e. - empty queue name) to an exchange. - </doc> - <doc type = "scenario"> - A client attempts to bind with an unnamed (empty) queue name to an exchange. - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_26" --> - <rule name = "queue-existence" on-failure = "not-found"> - <doc> - A client MUST NOT be allowed to bind a non-existent queue (i.e. not previously - declared) to an exchange. - </doc> - <doc type = "scenario"> - A client attempts to bind an undeclared queue name to an exchange. - </doc> - </rule> - </field> - - <field name = "exchange" domain = "exchange-name" label = "name of the exchange to bind to"> - <!-- Rule test name: was "amq_queue_14" --> - <rule name = "exchange-existence" on-failure = "not-found"> - <doc> - A client MUST NOT be allowed to bind a queue to a non-existent exchange. - </doc> - <doc type = "scenario"> - A client attempts to bind an named queue to a undeclared exchange. - </doc> - </rule> - </field> - - <field name = "routing-key" domain = "shortstr" label = "message routing key"> - <doc> - Specifies the routing key for the binding. The routing key is used for routing - messages depending on the exchange configuration. Not all exchanges use a - routing key - refer to the specific exchange documentation. If the queue name - is empty, the server uses the last queue declared on the channel. If the - routing key is also empty, the server uses this queue name for the routing - key as well. If the queue name is provided but the routing key is empty, the - server does the binding with that empty routing key. The meaning of empty - routing keys depends on the exchange implementation. - </doc> - </field> - - <field name = "nowait" domain = "bit" label = "do not send a reply method"> - <doc> - If set, the server will not respond to the method. The client should not wait - for a reply method. If the server could not complete the method it will raise a - channel or connection exception. - </doc> - </field> - - <field name = "arguments" domain = "table" label = "arguments for binding"> - <doc> - A set of arguments for the binding. The syntax and semantics of these arguments - depends on the exchange class. - </doc> - </field> - </method> - - <method name = "bind-ok" synchronous = "1" index = "21" label = "confirm bind successful"> - <doc>This method confirms that the bind was successful.</doc> - - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "purge" synchronous = "1" index = "30" label = "purge a queue"> - <doc> - This method removes all messages from a queue. It does not cancel consumers. Purged - messages are deleted without any formal "undo" mechanism. - </doc> - - <!-- Rule test name: was "amq_queue_15" --> - <rule name = "01"> - <doc>A call to purge MUST result in an empty queue.</doc> - </rule> - - <!-- Rule test name: was "amq_queue_41" --> - <rule name = "02"> - <doc> - On transacted channels the server MUST not purge messages that have already been - sent to a client but not yet acknowledged. - </doc> - </rule> - - <!-- TODO: Rule split? --> - - <!-- Rule test name: was "amq_queue_42" --> - <rule name = "03"> - <doc> - The server MAY implement a purge queue or log that allows system administrators - to recover accidentally-purged messages. The server SHOULD NOT keep purged - messages in the same storage spaces as the live messages since the volumes of - purged messages may get very large. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - - <response name = "purge-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <doc>The access ticket must be for the access realm that holds the queue.</doc> - - <rule name = "01"> - <doc> - The client MUST provide a valid access ticket giving "read" access rights to - the queue's access realm. Note that purging a queue is equivalent to reading - all messages and discarding them. - </doc> - </rule> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue to purge. If the queue name is empty, refers to - the current queue for the channel, which is the last declared queue. - </doc> - - <rule name = "01"> - <doc> - If the client did not previously declare a queue, and the queue name in this - method is empty, the server MUST raise a connection exception with reply - code 530 (not allowed). - </doc> - </rule> - - <!-- TODO Rule split? --> - - <!-- Rule test name: was "amq_queue_16" --> - <rule name = "02"> - <doc> - The queue MUST exist. Attempting to purge a non-existing queue MUST cause a - channel exception. - </doc> - </rule> - </field> - - <field name = "nowait" domain = "bit" label = "do not send a reply method"> - <doc> - If set, the server will not respond to the method. The client should not wait - for a reply method. If the server could not complete the method it will raise a - channel or connection exception. - </doc> - </field> - </method> - - <method name = "purge-ok" synchronous = "1" index = "31" label = "confirms a queue purge"> - <doc>This method confirms the purge of a queue.</doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "message-count" domain = "long" label = "number of messages purged"> - <doc>Reports the number of messages purged.</doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "delete" synchronous = "1" index = "40" label = "delete a queue"> - <doc> - This method deletes a queue. When a queue is deleted any pending messages are sent - to a dead-letter queue if this is defined in the server configuration, and all - consumers on the queue are cancelled. - </doc> - - <!-- TODO: Rule split? --> - - <!-- Rule test name: was "amq_queue_43" --> - <rule name = "01"> - <doc> - The server SHOULD use a dead-letter queue to hold messages that were pending on - a deleted queue, and MAY provide facilities for a system administrator to move - these messages back to an active queue. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - - <response name = "delete-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <doc> - The client provides a valid access ticket giving "active" access rights to the - queue's access realm. - </doc> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue to delete. If the queue name is empty, refers to - the current queue for the channel, which is the last declared queue. - </doc> - - <rule name = "01"> - <doc> - If the client did not previously declare a queue, and the queue name in this - method is empty, the server MUST raise a connection exception with reply - code 530 (not allowed). - </doc> - </rule> - - <!-- Rule test name: was "amq_queue_21" --> - <rule name = "02"> - <doc> - The queue must exist. If the client attempts to delete a non-existing queue - the server MUST raise a channel exception with reply code 404 (not found). - </doc> - </rule> - </field> - - <field name = "if-unused" domain = "bit" label = "delete only if unused"> - <doc> - If set, the server will only delete the queue if it has no consumers. If the - queue has consumers the server does does not delete it but raises a channel - exception instead. - </doc> - - <!-- Rule test name: was "amq_queue_29" and "amq_queue_30" --> - <rule name = "01"> - <doc>The server MUST respect the if-unused flag when deleting a queue.</doc> - </rule> - </field> - - <field name = "if-empty" domain = "bit" label = "delete only if empty"> - <doc> - If set, the server will only delete the queue if it has no messages. - </doc> - <rule name = "01"> - <doc> - If the queue is not empty the server MUST raise a channel exception with - reply code 406 (precondition failed). - </doc> - </rule> - </field> - - <field name = "nowait" domain = "bit" label = "do not send a reply method"> - <doc> - If set, the server will not respond to the method. The client should not wait - for a reply method. If the server could not complete the method it will raise a - channel or connection exception. - </doc> - </field> - </method> - - <method name = "delete-ok" synchronous = "1" index = "41" label = "confirm deletion of a queue"> - <doc>This method confirms the deletion of a queue.</doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "message-count" domain = "long" label = "number of messages purged"> - <doc>Reports the number of messages purged.</doc> - </field> - </method> - </class> - - <!-- == BASIC ============================================================ --> - - <class name = "basic" handler = "channel" index = "60" label = "work with basic content"> - <doc> - The Basic class provides methods that support an industry-standard messaging model. - </doc> - - <doc type = "grammar"> - basic = C:QOS S:QOS-OK - / C:CONSUME S:CONSUME-OK - / C:CANCEL S:CANCEL-OK - / C:PUBLISH content - / S:RETURN content - / S:DELIVER content - / C:GET ( S:GET-OK content / S:GET-EMPTY ) - / C:ACK - / C:REJECT - </doc> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MAY" /> - - <!-- Rule test name: was "amq_basic_08" --> - <rule name = "01"> - <doc> - The server SHOULD respect the persistent property of basic messages and - SHOULD make a best-effort to hold persistent basic messages on a reliable - storage mechanism. - </doc> - <doc type = "scenario"> - Send a persistent message to queue, stop server, restart server and then - verify whether message is still present. Assumes that queues are durable. - Persistence without durable queues makes no sense. - </doc> - </rule> - - <!-- Rule test name: was "amq_basic_09" --> - <rule name = "02"> - <doc> - The server MUST NOT discard a persistent basic message in case of a queue - overflow. - </doc> - <doc type = "scenario"> - Create a queue overflow situation with persistent messages and verify that - messages do not get lost (presumably the server will write them to disk). - </doc> - </rule> - - <rule name = "03"> - <doc> - The server MAY use the Channel.Flow method to slow or stop a basic message - publisher when necessary. - </doc> - <doc type = "scenario"> - Create a queue overflow situation with non-persistent messages and verify - whether the server responds with Channel.Flow or not. Repeat with persistent - messages. - </doc> - </rule> - - <!-- Rule test name: was "amq_basic_10" --> - <rule name = "04"> - <doc> - The server MAY overflow non-persistent basic messages to persistent - storage. - </doc> - <!-- Test scenario: untestable --> - </rule> - - <rule name = "05"> - <doc> - The server MAY discard or dead-letter non-persistent basic messages on a - priority basis if the queue size exceeds some configured limit. - </doc> - <!-- Test scenario: untestable --> - </rule> - - <!-- Rule test name: was "amq_basic_11" --> - <rule name = "06"> - <doc> - The server MUST implement at least 2 priority levels for basic messages, - where priorities 0-4 and 5-9 are treated as two distinct levels. - </doc> - <doc type = "scenario"> - Send a number of priority 0 messages to a queue. Send one priority 9 - message. Consume messages from the queue and verify that the first message - received was priority 9. - </doc> - </rule> - - <rule name = "07"> - <doc> - The server MAY implement up to 10 priority levels. - </doc> - <doc type = "scenario"> - Send a number of messages with mixed priorities to a queue, so that all - priority values from 0 to 9 are exercised. A good scenario would be ten - messages in low-to-high priority. Consume from queue and verify how many - priority levels emerge. - </doc> - </rule> - - <!-- Rule test name: was "amq_basic_12" --> - <rule name = "08"> - <doc> - The server MUST deliver messages of the same priority in order irrespective of - their individual persistence. - </doc> - <doc type = "scenario"> - Send a set of messages with the same priority but different persistence - settings to a queue. Consume and verify that messages arrive in same order - as originally published. - </doc> - </rule> - - <!-- Rule test name: was "amq_basic_13" --> - <rule name = "09"> - <doc> - The server MUST support automatic acknowledgements on Basic content, i.e. - consumers with the no-ack field set to FALSE. - </doc> - <doc type = "scenario"> - Create a queue and a consumer using automatic acknowledgements. Publish - a set of messages to the queue. Consume the messages and verify that all - messages are received. - </doc> - </rule> - - <rule name = "10"> - <doc> - The server MUST support explicit acknowledgements on Basic content, i.e. - consumers with the no-ack field set to TRUE. - </doc> - <doc type = "scenario"> - Create a queue and a consumer using explicit acknowledgements. Publish a - set of messages to the queue. Consume the messages but acknowledge only - half of them. Disconnect and reconnect, and consume from the queue. - Verify that the remaining messages are received. - </doc> - </rule> - - <!-- These are the properties for a Basic content --> - - <field name = "content-type" domain = "shortstr" label = "MIME content type" /> - <field name = "content-encoding" domain = "shortstr" label = "MIME content encoding" /> - <field name = "headers" domain = "table" label = "message header field table" /> - <field name = "delivery-mode" domain = "octet" label = "non-persistent (1) or persistent (2)" /> - <field name = "priority" domain = "octet" label = "message priority, 0 to 9" /> - <field name = "correlation-id" domain = "shortstr" label = "application correlation identifier" /> - <field name = "reply-to" domain = "shortstr" label = "destination to reply to" /> - <field name = "expiration" domain = "shortstr" label = "message expiration specification" /> - <field name = "message-id" domain = "shortstr" label = "application message identifier" /> - <field name = "timestamp" domain = "timestamp" label = "message timestamp" /> - <field name = "type" domain = "shortstr" label = "message type name" /> - <field name = "user-id" domain = "shortstr" label = "creating user id" /> - <field name = "app-id" domain = "shortstr" label = "creating application id" /> - <!-- This field is deprecated pending review --> - <field name = "cluster-id" domain = "shortstr" label = "intra-cluster routing identifier" /> - - <field name = "property-one" domain = "shortstr" label = "Extra property for testing only" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "qos" synchronous = "1" index = "10" label = "specify quality of service"> - <doc> - This method requests a specific quality of service. The QoS can be specified for the - current channel or for all channels on the connection. The particular properties and - semantics of a qos method always depend on the content class semantics. Though the - qos method could in principle apply to both peers, it is currently meaningful only - for the server. - </doc> - - <chassis name = "server" implement = "MUST" /> - <response name = "qos-ok" /> - - <field name = "prefetch-size" domain = "long" label = "prefetch window in octets"> - <doc> - The client can request that messages be sent in advance so that when the client - finishes processing a message, the following message is already held locally, - rather than needing to be sent down the channel. Prefetching gives a performance - improvement. This field specifies the prefetch window size in octets. The server - will send a message in advance if it is equal to or smaller in size than the - available prefetch size (and also falls into other prefetch limits). May be set - to zero, meaning "no specific limit", although other prefetch limits may still - apply. The prefetch-size is ignored if the no-ack option is set. - </doc> - <!-- Rule test name: was "amq_basic_17" --> - <rule name = "01"> - <doc> - The server MUST ignore this setting when the client is not processing any - messages - i.e. the prefetch size does not limit the transfer of single - messages to a client, only the sending in advance of more messages while - the client still has one or more unacknowledged messages. - </doc> - <doc type = "scenario"> - Define a QoS prefetch-size limit and send a single message that exceeds - that limit. Verify that the message arrives correctly. - </doc> - </rule> - </field> - - <field name = "prefetch-count" domain = "short" label = "prefetch window in messages"> - <doc> - Specifies a prefetch window in terms of whole messages. This field may be used - in combination with the prefetch-size field; a message will only be sent in - advance if both prefetch windows (and those at the channel and connection level) - allow it. The prefetch-count is ignored if the no-ack option is set. - </doc> - <!-- Rule test name: was "amq_basic_18" --> - <rule name = "01"> - <doc> - The server may send less data in advance than allowed by the client's - specified prefetch windows but it MUST NOT send more. - </doc> - <doc type = "scenario"> - Define a QoS prefetch-size limit and a prefetch-count limit greater than - one. Send multiple messages that exceed the prefetch size. Verify that - no more than one message arrives at once. - </doc> - </rule> - </field> - - <field name = "global" domain = "bit" label = "apply to entire connection"> - <doc> - By default the QoS settings apply to the current channel only. If this field is - set, they are applied to the entire connection. - </doc> - </field> - </method> - - <method name = "qos-ok" synchronous = "1" index = "11" label = "confirm the requested qos"> - <doc> - This method tells the client that the requested QoS levels could be handled by the - server. The requested QoS applies to all active consumers until a new QoS is - defined. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "consume" synchronous = "1" index = "30" label = "start a queue consumer"> - <doc> - This method asks the server to start a "consumer", which is a transient request for - messages from a specific queue. Consumers last as long as the channel they were - created on, or until the client cancels them. - </doc> - - <!-- Rule test name: was "amq_basic_01" --> - <rule name = "01"> - <doc> - The server SHOULD support at least 16 consumers per queue, and ideally, impose - no limit except as defined by available resources. - </doc> - <doc type = "scenario"> - Create a queue and create consumers on that queue until the server closes the - connection. Verify that the number of consumers created was at least sixteen - and report the total number. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - <response name = "consume-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "01" on-failure = "access-refused"> - <doc> - The client MUST provide a valid access ticket giving "read" access rights to - the realm for the queue. - </doc> - <doc type = "scenario"> - Attempt to create a consumer with an invalid (non-zero) access ticket. - </doc> - </rule> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue to consume from. If the queue name is null, - refers to the current queue for the channel, which is the last declared queue. - </doc> - <rule name = "01" on-failure = "not-allowed"> - <doc> - If the queue name is empty the client MUST have previously declared a - queue using this channel. - </doc> - <doc type = "scenario"> - Attempt to create a consumer with an empty queue name and no previously - declared queue on the channel. - </doc> - </rule> - </field> - - <field name = "consumer-tag" domain = "consumer-tag"> - <doc> - Specifies the identifier for the consumer. The consumer tag is local to a - connection, so two clients can use the same consumer tags. If this field is - empty the server will generate a unique tag. - </doc> - <rule name = "01" on-failure = "not-allowed"> - <doc> - The client MUST NOT specify a tag that refers to an existing consumer. - </doc> - <doc type = "scenario"> - Attempt to create two consumers with the same non-empty tag. - </doc> - </rule> - <rule name = "02" on-failure = "not-allowed"> - <doc> - The consumer tag is valid only within the channel from which the - consumer was created. I.e. a client MUST NOT create a consumer in one - channel and then use it in another. - </doc> - <doc type = "scenario"> - Attempt to create a consumer in one channel, then use in another channel, - in which consumers have also been created (to test that the server uses - unique consumer tags). - </doc> - </rule> - </field> - - <field name = "no-local" domain = "no-local" /> - - <field name = "no-ack" domain = "no-ack" /> - - <field name = "exclusive" domain = "bit" label = "request exclusive access"> - <doc> - Request exclusive consumer access, meaning only this consumer can access the - queue. - </doc> - <!-- Rule test name: was "amq_basic_02" --> - <rule name = "01" on-failure = "access-refused"> - <doc> - The client MAY NOT gain exclusive access to a queue that already has - active consumers. - </doc> - <doc type = "scenario"> - Open two connections to a server, and in one connection create a shared - (non-exclusive) queue and then consume from the queue. In the second - connection attempt to consume from the same queue using the exclusive - option. - </doc> - </rule> - </field> - - <field name = "nowait" domain = "bit" label = "do not send a reply method"> - <doc> - If set, the server will not respond to the method. The client should not wait - for a reply method. If the server could not complete the method it will raise - a channel or connection exception. - </doc> - </field> - </method> - - <method name = "consume-ok" synchronous = "1" index = "31" label = "confirm a new consumer"> - <doc> - The server provides the client with a consumer tag, which is used by the client - for methods called on the consumer at a later stage. - </doc> - <chassis name = "client" implement = "MUST" /> - <field name = "consumer-tag" domain = "consumer-tag"> - <doc> - Holds the consumer tag specified by the client or provided by the server. - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "cancel" synchronous = "1" index = "20" label = "end a queue consumer"> - <doc> - This method cancels a consumer. This does not affect already delivered - messages, but it does mean the server will not send any more messages for - that consumer. The client may receive an abitrary number of messages in - between sending the cancel method and receiving the cancel-ok reply. - </doc> - - <rule name = "01"> - <doc> - If the queue does not exist the server MUST ignore the cancel method, so - long as the consumer tag is valid for that channel. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - <response name = "cancel-ok" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - - <field name = "nowait" domain = "bit" label = "do not send a reply method"> - <doc> - If set, the server will not respond to the method. The client should not wait - for a reply method. If the server could not complete the method it will raise a - channel or connection exception. - </doc> - </field> - </method> - - <method name = "cancel-ok" synchronous = "1" index = "21" label = "confirm a cancelled consumer"> - <doc> - This method confirms that the cancellation was completed. - </doc> - <chassis name = "client" implement = "MUST" /> - <field name = "consumer-tag" domain = "consumer-tag" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "publish" content = "1" index = "40" label = "publish a message"> - <doc> - This method publishes a message to a specific exchange. The message will be routed - to queues as defined by the exchange configuration and distributed to any active - consumers when the transaction, if any, is committed. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "01"> - <doc> - The client MUST provide a valid access ticket giving "write" access rights - to the access realm for the exchange. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange to publish to. The exchange name can be - empty, meaning the default exchange. If the exchange name is specified, and that - exchange does not exist, the server will raise a channel exception. - </doc> - - <!-- Rule test name: was "amq_basic_06" --> - <rule name = "01"> - <doc> - The server MUST accept a blank exchange name to mean the default exchange. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <!-- Rule test name: was "amq_basic_14" --> - <rule name = "02"> - <doc> - If the exchange was declared as an internal exchange, the server MUST raise - a channel exception with a reply code 403 (access refused). - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <!-- Rule test name: was "amq_basic_15" --> - <rule name = "03"> - <doc> - The exchange MAY refuse basic content in which case it MUST raise a channel - exception with reply code 540 (not implemented). - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc> - Specifies the routing key for the message. The routing key is used for routing - messages depending on the exchange configuration. - </doc> - </field> - - <field name = "mandatory" domain = "bit" label = "indicate mandatory routing"> - <doc> - This flag tells the server how to react if the message cannot be routed to a - queue. If this flag is set, the server will return an unroutable message with a - Return method. If this flag is zero, the server silently drops the message. - </doc> - <!-- Rule test name: was "amq_basic_07" --> - <rule name = "01"> - <doc> - The server SHOULD implement the mandatory flag. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <field name = "immediate" domain = "bit" label = "request immediate delivery"> - <doc> - This flag tells the server how to react if the message cannot be routed to a - queue consumer immediately. If this flag is set, the server will return an - undeliverable message with a Return method. If this flag is zero, the server - will queue the message, but with no guarantee that it will ever be consumed. - </doc> - <!-- Rule test name: was "amq_basic_16" --> - <rule name = "01"> - <doc> - The server SHOULD implement the immediate flag. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - </method> - - <method name = "return" content = "1" index = "50" label = "return a failed message"> - <doc> - This method returns an undeliverable message that was published with the "immediate" - flag set, or an unroutable message published with the "mandatory" flag set. The - reply code and text provide information about the reason that the message was - undeliverable. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "reply-code" domain = "reply-code" /> - - <field name = "reply-text" domain = "reply-text" /> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange that the message was originally published to. - </doc> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc> - Specifies the routing key name specified when the message was published. - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "deliver" content = "1" index = "60" - label = "notify the client of a consumer message"> - <doc> - This method delivers a message to the client, via a consumer. In the asynchronous - message delivery model, the client starts a consumer using the Consume method, then - the server responds with Deliver methods as and when messages arrive for that - consumer. - </doc> - - <!-- Rule test name: was "amq_basic_19" --> - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The server SHOULD track the number of times a message has been delivered to - clients and when a message is redelivered a certain number of times - e.g. 5 - times - without being acknowledged, the server SHOULD consider the message to be - unprocessable (possibly causing client applications to abort), and move the - message to a dead letter queue. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "redelivered" domain = "redelivered" /> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange that the message was originally published to. - </doc> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc>Specifies the routing key name specified when the message was published.</doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "get" synchronous = "1" index = "70" label = "direct access to a queue"> - <doc> - This method provides a direct access to the messages in a queue using a synchronous - dialogue that is designed for specific types of application where synchronous - functionality is more important than performance. - </doc> - - <response name = "get-ok" /> - <response name = "get-empty" /> - <chassis name = "server" implement = "MUST" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "01"> - <doc> - The client MUST provide a valid access ticket giving "read" access rights to - the realm for the queue. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue to consume from. If the queue name is null, - refers to the current queue for the channel, which is the last declared queue. - </doc> - <rule name = "01"> - <doc> - If the client did not previously declare a queue, and the queue name in this - method is empty, the server MUST raise a connection exception with reply - code 530 (not allowed). - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - - <field name = "no-ack" domain = "no-ack" /> - </method> - - <method name = "get-ok" synchronous = "1" content = "1" index = "71" - label = "provide client with a message"> - <doc> - This method delivers a message to the client following a get method. A message - delivered by 'get-ok' must be acknowledged unless the no-ack option was set in the - get method. - </doc> - - <chassis name = "client" implement = "MAY" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "redelivered" domain = "redelivered" /> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange that the message was originally published to. - If empty, the message was published to the default exchange. - </doc> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc>Specifies the routing key name specified when the message was published.</doc> - </field> - - <field name = "message-count" domain = "long" label = "number of messages pending"> - <doc> - This field reports the number of messages pending on the queue, excluding the - message being delivered. Note that this figure is indicative, not reliable, and - can change arbitrarily as messages are added to the queue and removed by other - clients. - </doc> - </field> - </method> - - <method name = "get-empty" synchronous = "1" index = "72" - label = "indicate no messages available"> - <doc> - This method tells the client that the queue has no messages available for the - client. - </doc> - - <chassis name = "client" implement = "MAY" /> - - <!-- This field is deprecated pending review --> - <field name = "cluster-id" domain = "shortstr" label = "Cluster id"> - <doc> - For use by cluster applications, should not be used by client applications. - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "ack" index = "80" label = "acknowledge one or more messages"> - <doc> - This method acknowledges one or more messages delivered via the Deliver or Get-Ok - methods. The client can ask to confirm a single message or a set of messages up to - and including a specific message. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "multiple" domain = "bit" label = "acknowledge multiple messages"> - <doc> - If set to 1, the delivery tag is treated as "up to and including", so that the - client can acknowledge multiple messages with a single method. If set to zero, - the delivery tag refers to a single message. If the multiple field is 1, and the - delivery tag is zero, tells the server to acknowledge all outstanding mesages. - </doc> - - <!-- Rule test name: was "amq_basic_20" --> - <rule name = "01"> - <doc> - The server MUST validate that a non-zero delivery-tag refers to an delivered - message, and raise a channel exception if this is not the case. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "reject" index = "90" label = "reject an incoming message"> - <doc> - This method allows a client to reject a message. It can be used to interrupt and - cancel large incoming messages, or return untreatable messages to their original - queue. - </doc> - - <!-- Rule test name: was "amq_basic_21" --> - <rule name = "01"> - <doc> - The server SHOULD be capable of accepting and process the Reject method while - sending message content with a Deliver or Get-Ok method. I.e. the server should - read and process incoming methods while sending output frames. To cancel a - partially-send content, the server sends a content body frame of size 1 (i.e. - with no data except the frame-end octet). - </doc> - </rule> - - <!-- Rule test name: was "amq_basic_22" --> - <rule name = "02"> - <doc> - The server SHOULD interpret this method as meaning that the client is unable to - process the message at this time. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <rule name = "03"> - <!-- TODO: Rule split? --> - <doc> - A client MUST NOT use this method as a means of selecting messages to process. A - rejected message MAY be discarded or dead-lettered, not necessarily passed to - another client. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "requeue" domain = "bit" label = "requeue the message"> - <doc> - If this field is zero, the message will be discarded. If this bit is 1, the - server will attempt to requeue the message. - </doc> - - <!-- Rule test name: was "amq_basic_23" --> - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The server MUST NOT deliver the message to the same client within the - context of the current channel. The recommended strategy is to attempt to - deliver the message to an alternative consumer, and if that is not possible, - to move the message to a dead-letter queue. The server MAY use more - sophisticated tracking to hold the message on the queue and redeliver it to - the same client at a later stage. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - </field> - </method> - - <method name = "recover" index = "100" label = "redeliver unacknowledged messages"> - <doc> - This method asks the broker to redeliver all unacknowledged messages on a specified - channel. Zero or more messages may be redelivered. This method is only allowed on - non-transacted channels. - </doc> - - <rule name = "01"> - <doc> - The server MUST set the redelivered flag on all messages that are resent. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <rule name = "02"> - <doc> - The server MUST raise a channel exception if this is called on a transacted - channel. - </doc> - <doc type = "scenario"> - TODO. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - - <field name = "requeue" domain = "bit" label = "requeue the message"> - <doc> - If this field is zero, the message will be redelivered to the original - recipient. If this bit is 1, the server will attempt to requeue the message, - potentially then delivering it to an alternative subscriber. - </doc> - </field> - </method> - </class> - - <!-- == FILE ============================================================= --> - - <class name = "file" handler = "channel" index = "70" label = "work with file content"> - <doc> - The file class provides methods that support reliable file transfer. File - messages have a specific set of properties that are required for interoperability - with file transfer applications. File messages and acknowledgements are subject to - channel transactions. Note that the file class does not provide message browsing - methods; these are not compatible with the staging model. Applications that need - browsable file transfer should use Basic content and the Basic class. - </doc> - - <doc type = "grammar"> - file = C:QOS S:QOS-OK - / C:CONSUME S:CONSUME-OK - / C:CANCEL S:CANCEL-OK - / C:OPEN S:OPEN-OK C:STAGE content - / S:OPEN C:OPEN-OK S:STAGE content - / C:PUBLISH - / S:DELIVER - / S:RETURN - / C:ACK - / C:REJECT - </doc> - - <chassis name = "server" implement = "MAY" /> - <chassis name = "client" implement = "MAY" /> - - <rule name = "01"> - <doc> - The server MUST make a best-effort to hold file messages on a reliable storage - mechanism. - </doc> - </rule> - - <!-- TODO Rule implement attr inverse? --> - - <!-- TODO: Rule split? --> - - <rule name = "02"> - <doc> - The server MUST NOT discard a file message in case of a queue overflow. The server - MUST use the Channel.Flow method to slow or stop a file message publisher when - necessary. - </doc> - </rule> - - <!-- TODO: Rule split? --> - - <rule name = "03"> - <doc> - The server MUST implement at least 2 priority levels for file messages, where - priorities 0-4 and 5-9 are treated as two distinct levels. The server MAY implement - up to 10 priority levels. - </doc> - </rule> - - <rule name = "04"> - <doc> - The server MUST support both automatic and explicit acknowledgements on file - content. - </doc> - </rule> - - <!-- These are the properties for a File content --> - - <field name = "content-type" domain = "shortstr" label = "MIME content type" /> - <field name = "content-encoding" domain = "shortstr" label = "MIME content encoding" /> - <field name = "headers" domain = "table" label = "message header field table" /> - <field name = "priority" domain = "octet" label = "message priority, 0 to 9" /> - <field name = "reply-to" domain = "shortstr" label = "destination to reply to" /> - <field name = "message-id" domain = "shortstr" label = "application message identifier" /> - <field name = "filename" domain = "shortstr" label = "message filename" /> - <field name = "timestamp" domain = "timestamp" label = "message timestamp" /> - <!-- This field is deprecated pending review --> - <field name = "cluster-id" domain = "shortstr" label = "intra-cluster routing identifier" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "qos" synchronous = "1" index = "10" label = "specify quality of service"> - <doc> - This method requests a specific quality of service. The QoS can be specified for the - current channel or for all channels on the connection. The particular properties and - semantics of a qos method always depend on the content class semantics. Though the - qos method could in principle apply to both peers, it is currently meaningful only - for the server. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <response name = "qos-ok" /> - - <field name = "prefetch-size" domain = "long" label = "prefetch window in octets"> - <doc> - The client can request that messages be sent in advance so that when the client - finishes processing a message, the following message is already held locally, - rather than needing to be sent down the channel. Prefetching gives a performance - improvement. This field specifies the prefetch window size in octets. May be set - to zero, meaning "no specific limit". Note that other prefetch limits may still - apply. The prefetch-size is ignored if the no-ack option is set. - </doc> - </field> - - <field name = "prefetch-count" domain = "short" label = "prefetch window in messages"> - <doc> - Specifies a prefetch window in terms of whole messages. This is compatible with - some file API implementations. This field may be used in combination with the - prefetch-size field; a message will only be sent in advance if both prefetch - windows (and those at the channel and connection level) allow it. The - prefetch-count is ignored if the no-ack option is set. - </doc> - - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The server MAY send less data in advance than allowed by the client's - specified prefetch windows but it MUST NOT send more. - </doc> - </rule> - </field> - - <field name = "global" domain = "bit" label = "apply to entire connection"> - <doc> - By default the QoS settings apply to the current channel only. If this field is - set, they are applied to the entire connection. - </doc> - </field> - </method> - - <method name = "qos-ok" synchronous = "1" index = "11" label = "confirm the requested qos"> - <doc> - This method tells the client that the requested QoS levels could be handled by the - server. The requested QoS applies to all active consumers until a new QoS is - defined. - </doc> - - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "consume" synchronous = "1" index = "20" label = "start a queue consumer"> - <doc> - This method asks the server to start a "consumer", which is a transient request for - messages from a specific queue. Consumers last as long as the channel they were - created on, or until the client cancels them. - </doc> - - <rule name = "01"> - <doc> - The server SHOULD support at least 16 consumers per queue, unless the queue was - declared as private, and ideally, impose no limit except as defined by available - resources. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - - <response name = "consume-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "01"> - <doc> - The client MUST provide a valid access ticket giving "read" access rights to - the realm for the queue. - </doc> - </rule> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue to consume from. If the queue name is null, - refers to the current queue for the channel, which is the last declared queue. - </doc> - - <rule name = "01"> - <doc> - If the client did not previously declare a queue, and the queue name in this - method is empty, the server MUST raise a connection exception with reply - code 530 (not allowed). - </doc> - </rule> - </field> - - <field name = "consumer-tag" domain = "consumer-tag"> - <doc> - Specifies the identifier for the consumer. The consumer tag is local to a - connection, so two clients can use the same consumer tags. If this field is - empty the server will generate a unique tag. - </doc> - - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The tag MUST NOT refer to an existing consumer. If the client attempts to - create two consumers with the same non-empty tag the server MUST raise a - connection exception with reply code 530 (not allowed). - </doc> - </rule> - </field> - - <field name = "no-local" domain = "no-local" /> - - <field name = "no-ack" domain = "no-ack" /> - - <field name = "exclusive" domain = "bit" label = "request exclusive access"> - <doc> - Request exclusive consumer access, meaning only this consumer can access the - queue. - </doc> - - <!-- Rule test name: was "amq_file_00" --> - <rule name = "01"> - <doc> - If the server cannot grant exclusive access to the queue when asked, - - because there are other consumers active - it MUST raise a channel exception - with return code 405 (resource locked). - </doc> - </rule> - </field> - - <field name = "nowait" domain = "bit" label = "do not send a reply method"> - <doc> - If set, the server will not respond to the method. The client should not wait - for a reply method. If the server could not complete the method it will raise a - channel or connection exception. - </doc> - </field> - </method> - - <method name = "consume-ok" synchronous = "1" index = "21" label = "confirm a new consumer"> - <doc> - This method provides the client with a consumer tag which it MUST use in methods - that work with the consumer. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag"> - <doc>Holds the consumer tag specified by the client or provided by the server.</doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "cancel" synchronous = "1" index = "30" label = "end a queue consumer"> - <doc> - This method cancels a consumer. This does not affect already delivered messages, but - it does mean the server will not send any more messages for that consumer. - </doc> - - <response name = "cancel-ok" /> - - <chassis name = "server" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - - <field name = "nowait" domain = "bit" label = "do not send a reply method"> - <doc> - If set, the server will not respond to the method. The client should not wait - for a reply method. If the server could not complete the method it will raise a - channel or connection exception. - </doc> - </field> - </method> - - <method name = "cancel-ok" synchronous = "1" index = "31" label = "confirm a cancelled consumer"> - <doc>This method confirms that the cancellation was completed.</doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "open" synchronous = "1" index = "40" label = "request to start staging"> - <doc> - This method requests permission to start staging a message. Staging means sending - the message into a temporary area at the recipient end and then delivering the - message by referring to this temporary area. Staging is how the protocol handles - partial file transfers - if a message is partially staged and the connection breaks, - the next time the sender starts to stage it, it can restart from where it left off. - </doc> - - <response name = "open-ok" /> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <field name = "identifier" domain = "shortstr" label = "staging identifier"> - <doc> - This is the staging identifier. This is an arbitrary string chosen by the - sender. For staging to work correctly the sender must use the same staging - identifier when staging the same message a second time after recovery from a - failure. A good choice for the staging identifier would be the SHA1 hash of the - message properties data (including the original filename, revised time, etc.). - </doc> - </field> - - <field name = "content-size" domain = "longlong" label = "message content size"> - <doc> - The size of the content in octets. The recipient may use this information to - allocate or check available space in advance, to avoid "disk full" errors during - staging of very large messages. - </doc> - - <rule name = "01"> - <doc> - The sender MUST accurately fill the content-size field. Zero-length content - is permitted. - </doc> - </rule> - </field> - </method> - - <method name = "open-ok" synchronous = "1" index = "41" label = "confirm staging ready"> - <doc> - This method confirms that the recipient is ready to accept staged data. If the - message was already partially-staged at a previous time the recipient will report - the number of octets already staged. - </doc> - - <response name = "stage" /> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - - <field name = "staged-size" domain = "longlong" label = "already staged amount"> - <doc> - The amount of previously-staged content in octets. For a new message this will - be zero. - </doc> - - <rule name = "01"> - <doc> - The sender MUST start sending data from this octet offset in the message, - counting from zero. - </doc> - </rule> - - <rule name = "02"> - <!-- TODO: Rule split? --> - <doc> - The recipient MAY decide how long to hold partially-staged content and MAY - implement staging by always discarding partially-staged content. However if - it uses the file content type it MUST support the staging methods. - </doc> - </rule> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "stage" content = "1" index = "50" label = "stage message content"> - <doc> - This method stages the message, sending the message content to the recipient from - the octet offset specified in the Open-Ok method. - </doc> - - <chassis name = "server" implement = "MUST" /> - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "publish" index = "60" label = "publish a message"> - <doc> - This method publishes a staged file message to a specific exchange. The file message - will be routed to queues as defined by the exchange configuration and distributed to - any active consumers when the transaction, if any, is committed. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "01"> - <doc> - The client MUST provide a valid access ticket giving "write" access rights - to the access realm for the exchange. - </doc> - </rule> - </field> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange to publish to. The exchange name can be - empty, meaning the default exchange. If the exchange name is specified, and that - exchange does not exist, the server will raise a channel exception. - </doc> - - <rule name = "01"> - <doc> - The server MUST accept a blank exchange name to mean the default exchange. - </doc> - </rule> - - <rule name = "02"> - <doc> - If the exchange was declared as an internal exchange, the server MUST - respond with a reply code 403 (access refused) and raise a channel - exception. - </doc> - </rule> - - <!-- TODO: Rule split? --> - - <rule name = "03"> - <doc> - The exchange MAY refuse file content in which case it MUST respond with a - reply code 540 (not implemented) and raise a channel exception. - </doc> - </rule> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc> - Specifies the routing key for the message. The routing key is used for routing - messages depending on the exchange configuration. - </doc> - </field> - - <field name = "mandatory" domain = "bit" label = "indicate mandatory routing"> - <doc> - This flag tells the server how to react if the message cannot be routed to a - queue. If this flag is set, the server will return an unroutable message with a - Return method. If this flag is zero, the server silently drops the message. - </doc> - - <!-- Rule test name: was "amq_file_00" --> - <rule name = "01"> - <doc>The server SHOULD implement the mandatory flag.</doc> - </rule> - </field> - - <field name = "immediate" domain = "bit" label = "request immediate delivery"> - <doc> - This flag tells the server how to react if the message cannot be routed to a - queue consumer immediately. If this flag is set, the server will return an - undeliverable message with a Return method. If this flag is zero, the server - will queue the message, but with no guarantee that it will ever be consumed. - </doc> - - <!-- Rule test name: was "amq_file_00" --> - <rule name = "01"> - <doc>The server SHOULD implement the immediate flag.</doc> - </rule> - </field> - - <field name = "identifier" domain = "shortstr" label = "staging identifier"> - <doc> - This is the staging identifier of the message to publish. The message must have - been staged. Note that a client can send the Publish method asynchronously - without waiting for staging to finish. - </doc> - </field> - </method> - - <method name = "return" content = "1" index = "70" label = "return a failed message"> - <doc> - This method returns an undeliverable message that was published with the "immediate" - flag set, or an unroutable message published with the "mandatory" flag set. The - reply code and text provide information about the reason that the message was - undeliverable. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "reply-code" domain = "reply-code" /> - - <field name = "reply-text" domain = "reply-text" /> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange that the message was originally published to. - </doc> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc>Specifies the routing key name specified when the message was published.</doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "deliver" index = "80" label = "notify the client of a consumer message"> - <doc> - This method delivers a staged file message to the client, via a consumer. In the - asynchronous message delivery model, the client starts a consumer using the Consume - method, then the server responds with Deliver methods as and when messages arrive - for that consumer. - </doc> - - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The server SHOULD track the number of times a message has been delivered to - clients and when a message is redelivered a certain number of times - e.g. 5 - times - without being acknowledged, the server SHOULD consider the message to be - unprocessable (possibly causing client applications to abort), and move the - message to a dead letter queue. - </doc> - </rule> - - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "redelivered" domain = "redelivered" /> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange that the message was originally published to. - </doc> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc>Specifies the routing key name specified when the message was published.</doc> - </field> - - <field name = "identifier" domain = "shortstr" label = "staging identifier"> - <doc> - This is the staging identifier of the message to deliver. The message must have - been staged. Note that a server can send the Deliver method asynchronously - without waiting for staging to finish. - </doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "ack" index = "90" label = "acknowledge one or more messages"> - <doc> - This method acknowledges one or more messages delivered via the Deliver method. The - client can ask to confirm a single message or a set of messages up to and including - a specific message. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "multiple" domain = "bit" label = "acknowledge multiple messages"> - <doc> - If set to 1, the delivery tag is treated as "up to and including", so that the - client can acknowledge multiple messages with a single method. If set to zero, - the delivery tag refers to a single message. If the multiple field is 1, and the - delivery tag is zero, tells the server to acknowledge all outstanding mesages. - </doc> - - <rule name = "01"> - <doc> - The server MUST validate that a non-zero delivery-tag refers to an delivered - message, and raise a channel exception if this is not the case. - </doc> - </rule> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "reject" index = "100" label = "reject an incoming message"> - <doc> - This method allows a client to reject a message. It can be used to return - untreatable messages to their original queue. Note that file content is staged - before delivery, so the client will not use this method to interrupt delivery of a - large message. - </doc> - - <rule name = "01"> - <doc> - The server SHOULD interpret this method as meaning that the client is unable to - process the message at this time. - </doc> - </rule> - - <!-- TODO: Rule split? --> - - <rule name = "02"> - <doc> - A client MUST NOT use this method as a means of selecting messages to process. A - rejected message MAY be discarded or dead-lettered, not necessarily passed to - another client. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "requeue" domain = "bit" label = "requeue the message"> - <doc> - If this field is zero, the message will be discarded. If this bit is 1, the - server will attempt to requeue the message. - </doc> - - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The server MUST NOT deliver the message to the same client within the - context of the current channel. The recommended strategy is to attempt to - deliver the message to an alternative consumer, and if that is not possible, - to move the message to a dead-letter queue. The server MAY use more - sophisticated tracking to hold the message on the queue and redeliver it to - the same client at a later stage. - </doc> - </rule> - </field> - </method> - </class> - - <!-- == STREAM =========================================================== --> - - <class name = "stream" handler = "channel" index = "80" label = "work with streaming content"> - <doc> - The stream class provides methods that support multimedia streaming. The stream class - uses the following semantics: one message is one packet of data; delivery is - unacknowleged and unreliable; the consumer can specify quality of service parameters - that the server can try to adhere to; lower-priority messages may be discarded in favour - of high priority messages. - </doc> - - <doc type = "grammar"> - stream = C:QOS S:QOS-OK - / C:CONSUME S:CONSUME-OK - / C:CANCEL S:CANCEL-OK - / C:PUBLISH content - / S:RETURN - / S:DELIVER content - </doc> - - <chassis name = "server" implement = "MAY" /> - <chassis name = "client" implement = "MAY" /> - - <rule name = "01"> - <doc> - The server SHOULD discard stream messages on a priority basis if the queue size - exceeds some configured limit. - </doc> - </rule> - - <rule name = "02"> - <!-- TODO: Rule split? --> - <doc> - The server MUST implement at least 2 priority levels for stream messages, where - priorities 0-4 and 5-9 are treated as two distinct levels. The server MAY implement - up to 10 priority levels. - </doc> - </rule> - - <rule name = "03"> - <doc> - The server MUST implement automatic acknowledgements on stream content. That is, as - soon as a message is delivered to a client via a Deliver method, the server must - remove it from the queue. - </doc> - </rule> - - <!-- These are the properties for a Stream content --> - - <field name = "content-type" domain = "shortstr" label = "MIME content type" /> - <field name = "content-encoding" domain = "shortstr" label = "MIME content encoding" /> - <field name = "headers" domain = "table" label = "message header field table" /> - <field name = "priority" domain = "octet" label = "message priority, 0 to 9" /> - <field name = "timestamp" domain = "timestamp" label = "message timestamp" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "qos" synchronous = "1" index = "10" label = "specify quality of service"> - <doc> - This method requests a specific quality of service. The QoS can be specified for the - current channel or for all channels on the connection. The particular properties and - semantics of a qos method always depend on the content class semantics. Though the - qos method could in principle apply to both peers, it is currently meaningful only - for the server. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <response name = "qos-ok" /> - - <field name = "prefetch-size" domain = "long" label = "prefetch window in octets"> - <doc> - The client can request that messages be sent in advance so that when the client - finishes processing a message, the following message is already held locally, - rather than needing to be sent down the channel. Prefetching gives a performance - improvement. This field specifies the prefetch window size in octets. May be set - to zero, meaning "no specific limit". Note that other prefetch limits may still - apply. - </doc> - </field> - - <field name = "prefetch-count" domain = "short" label = "prefetch window in messages"> - <doc> - Specifies a prefetch window in terms of whole messages. This field may be used - in combination with the prefetch-size field; a message will only be sent in - advance if both prefetch windows (and those at the channel and connection level) - allow it. - </doc> - </field> - - <field name = "consume-rate" domain = "long" label = "transfer rate in octets/second"> - <doc> - Specifies a desired transfer rate in octets per second. This is usually - determined by the application that uses the streaming data. A value of zero - means "no limit", i.e. as rapidly as possible. - </doc> - - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The server MAY ignore the prefetch values and consume rates, depending on - the type of stream and the ability of the server to queue and/or reply it. - The server MAY drop low-priority messages in favour of high-priority - messages. - </doc> - </rule> - </field> - - <field name = "global" domain = "bit" label = "apply to entire connection"> - <doc> - By default the QoS settings apply to the current channel only. If this field is - set, they are applied to the entire connection. - </doc> - </field> - </method> - - <method name = "qos-ok" synchronous = "1" index = "11" label = "confirm the requested qos"> - <doc> - This method tells the client that the requested QoS levels could be handled by the - server. The requested QoS applies to all active consumers until a new QoS is - defined. - </doc> - - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "consume" synchronous = "1" index = "20" label = "start a queue consumer"> - <doc> - This method asks the server to start a "consumer", which is a transient request for - messages from a specific queue. Consumers last as long as the channel they were - created on, or until the client cancels them. - </doc> - - <rule name = "01"> - <doc> - The server SHOULD support at least 16 consumers per queue, unless the queue was - declared as private, and ideally, impose no limit except as defined by available - resources. - </doc> - </rule> - - <rule name = "02"> - <doc> - Streaming applications SHOULD use different channels to select different - streaming resolutions. AMQP makes no provision for filtering and/or transforming - streams except on the basis of priority-based selective delivery of individual - messages. - </doc> - </rule> - - <chassis name = "server" implement = "MUST" /> - <response name = "consume-ok" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "01"> - <doc> - The client MUST provide a valid access ticket giving "read" access rights to - the realm for the queue. - </doc> - </rule> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue to consume from. If the queue name is null, - refers to the current queue for the channel, which is the last declared queue. - </doc> - - <rule name = "01"> - <doc> - If the client did not previously declare a queue, and the queue name in this - method is empty, the server MUST raise a connection exception with reply - code 530 (not allowed). - </doc> - </rule> - </field> - - <field name = "consumer-tag" domain = "consumer-tag"> - <doc> - Specifies the identifier for the consumer. The consumer tag is local to a - connection, so two clients can use the same consumer tags. If this field is - empty the server will generate a unique tag. - </doc> - - <rule name = "01"> - <!-- TODO: Rule split? --> - <doc> - The tag MUST NOT refer to an existing consumer. If the client attempts to - create two consumers with the same non-empty tag the server MUST raise a - connection exception with reply code 530 (not allowed). - </doc> - </rule> - </field> - - <field name = "no-local" domain = "no-local" /> - - <field name = "exclusive" domain = "bit" label = "request exclusive access"> - <doc> - Request exclusive consumer access, meaning only this consumer can access the - queue. - </doc> - - - <!-- Rule test name: was "amq_file_00" --> - <rule name = "01"> - <doc> - If the server cannot grant exclusive access to the queue when asked, - - because there are other consumers active - it MUST raise a channel exception - with return code 405 (resource locked). - </doc> - </rule> - </field> - - <field name = "nowait" domain = "bit" label = "do not send a reply method"> - <doc> - If set, the server will not respond to the method. The client should not wait - for a reply method. If the server could not complete the method it will raise a - channel or connection exception. - </doc> - </field> - </method> - - <method name = "consume-ok" synchronous = "1" index = "21" label = "confirm a new consumer"> - <doc> - This method provides the client with a consumer tag which it may use in methods that - work with the consumer. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag"> - <doc>Holds the consumer tag specified by the client or provided by the server.</doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "cancel" synchronous = "1" index = "30" label = "end a queue consumer"> - <doc> - This method cancels a consumer. Since message delivery is asynchronous the client - may continue to receive messages for a short while after canceling a consumer. It - may process or discard these as appropriate. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <response name = "cancel-ok" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - - <field name = "nowait" domain = "bit" label = "do not send a reply method"> - <doc> - If set, the server will not respond to the method. The client should not wait - for a reply method. If the server could not complete the method it will raise a - channel or connection exception. - </doc> - </field> - </method> - - <method name = "cancel-ok" synchronous = "1" index = "31" label = "confirm a cancelled consumer"> - <doc>This method confirms that the cancellation was completed.</doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "publish" content = "1" index = "40" label = "publish a message"> - <doc> - This method publishes a message to a specific exchange. The message will be routed - to queues as defined by the exchange configuration and distributed to any active - consumers as appropriate. - </doc> - - <chassis name = "server" implement = "MUST" /> - - <field name = "ticket" domain = "access-ticket"> - <rule name = "01"> - <doc> - The client MUST provide a valid access ticket giving "write" access rights - to the access realm for the exchange. - </doc> - </rule> - </field> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange to publish to. The exchange name can be - empty, meaning the default exchange. If the exchange name is specified, and that - exchange does not exist, the server will raise a channel exception. - </doc> - - <rule name = "01"> - <doc> - The server MUST accept a blank exchange name to mean the default exchange. - </doc> - </rule> - - <rule name = "02"> - <doc> - If the exchange was declared as an internal exchange, the server MUST - respond with a reply code 403 (access refused) and raise a channel - exception. - </doc> - </rule> - - <rule name = "03"> - <doc> - The exchange MAY refuse stream content in which case it MUST respond with a - reply code 540 (not implemented) and raise a channel exception. - </doc> - </rule> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc> - Specifies the routing key for the message. The routing key is used for routing - messages depending on the exchange configuration. - </doc> - </field> - - <field name = "mandatory" domain = "bit" label = "indicate mandatory routing"> - <doc> - This flag tells the server how to react if the message cannot be routed to a - queue. If this flag is set, the server will return an unroutable message with a - Return method. If this flag is zero, the server silently drops the message. - </doc> - - <!-- Rule test name: was "amq_stream_00" --> - <rule name = "01"> - <doc>The server SHOULD implement the mandatory flag.</doc> - </rule> - </field> - - <field name = "immediate" domain = "bit" label = "request immediate delivery"> - <doc> - This flag tells the server how to react if the message cannot be routed to a - queue consumer immediately. If this flag is set, the server will return an - undeliverable message with a Return method. If this flag is zero, the server - will queue the message, but with no guarantee that it will ever be consumed. - </doc> - - <!-- Rule test name: was "amq_stream_00" --> - <rule name = "01"> - <doc>The server SHOULD implement the immediate flag.</doc> - </rule> - </field> - </method> - - <method name = "return" content = "1" index = "50" label = "return a failed message"> - <doc> - This method returns an undeliverable message that was published with the "immediate" - flag set, or an unroutable message published with the "mandatory" flag set. The - reply code and text provide information about the reason that the message was - undeliverable. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "reply-code" domain = "reply-code" /> - - <field name = "reply-text" domain = "reply-text" /> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange that the message was originally published to. - </doc> - </field> - - <field name = "routing-key" domain = "shortstr" label = "Message routing key"> - <doc>Specifies the routing key name specified when the message was published.</doc> - </field> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "deliver" content = "1" index = "60" - label = "notify the client of a consumer message"> - <doc> - This method delivers a message to the client, via a consumer. In the asynchronous - message delivery model, the client starts a consumer using the Consume method, then - the server responds with Deliver methods as and when messages arrive for that - consumer. - </doc> - - <chassis name = "client" implement = "MUST" /> - - <field name = "consumer-tag" domain = "consumer-tag" /> - - <field name = "delivery-tag" domain = "delivery-tag" /> - - <field name = "exchange" domain = "exchange-name"> - <doc> - Specifies the name of the exchange that the message was originally published to. - </doc> - </field> - - <field name = "queue" domain = "queue-name"> - <doc> - Specifies the name of the queue that the message came from. Note that a single - channel can start many consumers on different queues. - </doc> - <assert check = "notnull" /> - </field> - </method> - </class> - - <!-- == TX =============================================================== --> - - <class name = "tx" handler = "channel" index = "90" label = "work with standard transactions"> - <doc> - Standard transactions provide so-called "1.5 phase commit". We can ensure that work is - never lost, but there is a chance of confirmations being lost, so that messages may be - resent. Applications that use standard transactions must be able to detect and ignore - duplicate messages. - </doc> - - <!-- TODO: Rule split? --> - - <rule name = "01"> - <doc> - An client using standard transactions SHOULD be able to track all messages received - within a reasonable period, and thus detect and reject duplicates of the same - message. It SHOULD NOT pass these to the application layer. - </doc> - </rule> - - <doc type = "grammar"> - tx = C:SELECT S:SELECT-OK - / C:COMMIT S:COMMIT-OK - / C:ROLLBACK S:ROLLBACK-OK - </doc> - - <chassis name = "server" implement = "SHOULD" /> - <chassis name = "client" implement = "MAY" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "select" synchronous = "1" index = "10" label = "select standard transaction mode"> - <doc> - This method sets the channel to use standard transactions. The client must use this - method at least once on a channel before using the Commit or Rollback methods. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "select-ok" /> - </method> - - <method name = "select-ok" synchronous = "1" index = "11" label = "confirm transaction mode"> - <doc> - This method confirms to the client that the channel was successfully set to use - standard transactions. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "commit" synchronous = "1" index = "20" label = "commit the current transaction"> - <doc> - This method commits all messages published and acknowledged in the current - transaction. A new transaction starts immediately after a commit. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "commit-ok" /> - </method> - - <method name = "commit-ok" synchronous = "1" index = "21" label = "confirm a successful commit"> - <doc> - This method confirms to the client that the commit succeeded. Note that if a commit - fails, the server raises a channel exception. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "rollback" synchronous = "1" index = "30" - label = "abandon the current transaction"> - <doc> - This method abandons all messages published and acknowledged in the current - transaction. A new transaction starts immediately after a rollback. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "rollback-ok" /> - </method> - - <method name = "rollback-ok" synchronous = "1" index = "31" label = "confirm successful rollback"> - <doc> - This method confirms to the client that the rollback succeeded. Note that if an - rollback fails, the server raises a channel exception. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - </class> - - <!-- == DTX ============================================================== --> - - <class name = "dtx" handler = "channel" index = "100" label = "work with distributed transactions"> - <doc> - Distributed transactions provide so-called "2-phase commit". The AMQP distributed - transaction model supports the X-Open XA architecture and other distributed transaction - implementations. The Dtx class assumes that the server has a private communications - channel (not AMQP) to a distributed transaction coordinator. - </doc> - - <doc type = "grammar"> - dtx = C:SELECT S:SELECT-OK - C:START S:START-OK - </doc> - - <chassis name = "server" implement = "MAY" /> - <chassis name = "client" implement = "MAY" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "select" synchronous = "1" index = "10" label = "select standard transaction mode"> - <doc> - This method sets the channel to use distributed transactions. The client must use - this method at least once on a channel before using the Start method. - </doc> - <chassis name = "server" implement = "MUST" /> - <response name = "select-ok" /> - </method> - - <method name = "select-ok" synchronous = "1" index = "11" label = "confirm transaction mode"> - <doc> - This method confirms to the client that the channel was successfully set to use - distributed transactions. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "start" synchronous = "1" index = "20" - label = "start a new distributed transaction"> - <doc> - This method starts a new distributed transaction. This must be the first method on a - new channel that uses the distributed transaction mode, before any methods that - publish or consume messages. - </doc> - <chassis name = "server" implement = "MAY" /> - <response name = "start-ok" /> - <field name = "dtx-identifier" domain = "shortstr" label = "transaction identifier"> - <doc> - The distributed transaction key. This identifies the transaction so that the - AMQP server can coordinate with the distributed transaction coordinator. - </doc> - <assert check = "notnull" /> - </field> - </method> - - <method name = "start-ok" synchronous = "1" index = "21" - label = "confirm the start of a new distributed transaction"> - <doc> - This method confirms to the client that the transaction started. Note that if a - start fails, the server raises a channel exception. - </doc> - <chassis name = "client" implement = "MUST" /> - </method> - </class> - - <!-- == TUNNEL =========================================================== --> - - <class name = "tunnel" handler = "tunnel" index = "110" label = "methods for protocol tunneling"> - <doc> - The tunnel methods are used to send blocks of binary data - which can be serialised AMQP - methods or other protocol frames - between AMQP peers. - </doc> - - <doc type = "grammar"> - tunnel = C:REQUEST - / S:REQUEST - </doc> - - <chassis name = "server" implement = "MAY" /> - <chassis name = "client" implement = "MAY" /> - - <field name = "headers" domain = "table" label = "message header field table" /> - <field name = "proxy-name" domain = "shortstr" label = "identity of tunnelling proxy" /> - <field name = "data-name" domain = "shortstr" label = "name or type of message being tunnelled" /> - <field name = "durable" domain = "octet" label = "message durability indicator" /> - <field name = "broadcast" domain = "octet" label = "message broadcast mode" /> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <method name = "request" content = "1" index = "10" label = "sends a tunnelled method"> - <doc> - This method tunnels a block of binary data, which can be an encoded - AMQP method or other data. The binary data is sent as the content for - the Tunnel.Request method. - </doc> - <chassis name = "server" implement = "MUST" /> - <field name = "meta-data" domain = "table" label = "meta data for the tunnelled block"> - <doc> - This field table holds arbitrary meta-data that the sender needs to - pass to the recipient. - </doc> - </field> - </method> - </class> -</amqp> diff --git a/gentools/xml-src/cluster-0.9.test.xml b/gentools/xml-src/cluster-0.9.test.xml deleted file mode 100644 index 142e6c9380..0000000000 --- a/gentools/xml-src/cluster-0.9.test.xml +++ /dev/null @@ -1,59 +0,0 @@ -<?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. - - - --> - -<amqp major="0" minor="9" port="5672" comment="AMQ protocol 0.80"> - -<class name = "cluster" index = "101"> - -<doc> - An extension that allows brokers to communicate in order to - provide a clustered service to clients. -</doc> - -<method name = "join" index="10"> - <field name = "broker" type = "shortstr" /> -</method> - -<method name = "membership" index="20"> - <field name = "members" type = "longstr" /> -</method> - -<method name = "synch" index="30"> -</method> - -<method name = "leave" index="40"> - <field name = "broker" type = "shortstr" /> -</method> - -<method name = "suspect" index="50"> - <field name = "broker" type = "shortstr" /> -</method> - -<method name = "ping" index="60"> - <field name = "broker" type = "shortstr" /> - <field name = "load" type = "long" /> - <field name = "response required" type = "bit" /> -</method> - -</class> - -</amqp> |